c++矢量旋转所有组合

c++ vector rotation all combinations

本文关键字:组合 旋转 c++      更新时间:2023-10-16

我想找到给定向量的所有可能的向量旋转组合。我的代码在一个向量中依次找到一个特定的元素,然后围绕它旋转,但是当两个相同的元素连续出现时,这个逻辑就失效了,比如在{1,1,2}中下面是代码片段,有人可以帮助我规避这个问题,最好是让我们说一个if else循环在我的for循环。

#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
vector<vector<int> > allrot(const vector<int>& a);
int main()
{
      int myints[] = { 1, 1, 2 };
      std::vector<int> a (myints, myints + sizeof(myints) / sizeof(int));
      std::vector<vector<int> > b;
      b = allrot(a);
}
vector<vector<int> > allrot(const vector<int>& a) {
        std::vector<vector<int> > b;
        for(int i = 1; i <= a.size(); i++) {
                //int k;
                //if (a[i] == a[i+1])
                    //k = a [i+1];
                //else
                    //k = a[i];
                auto pivot = std::find(a.begin(), a.end(), a[i]);
                std::vector<int> dest(a.size());
                std::rotate_copy(a.begin(), pivot, a.end(), dest.begin());
                for (const auto &i : dest) {
                    std::cout << i << ' ';
                }
                std::cout << 'n';
                b.push_back(dest);
        }
        return b;
}

如果这个问题看起来很幼稚,我很抱歉,我是c++新手。

首先,您的代码有一个潜在的分段错误:

for(int i = 1; i <= a.size(); i++)

由于std::vector索引以0为基数,因此i = a.size()越界。

对于实际的问题:注意,如果你只想要不同的旋转,你只需要旋转初始向量到它重复的点——那就是它的周期,从那个点开始,不会有新的不同的旋转。

这个周期可以是1到a.size()之间的任何值,它总是存在的,所以达到它应该是你的停机条件。

可能的算法是

  • 对初始向量a进行b的临时拷贝
  • b压入结果向量
  • b旋转1
  • 比较ba。如果相等,返回结果向量,否则返回步骤2

向量比较(最后一步)计算量很大,可以优化,例如,period将始终是a.size()的除数,因此您可以基于此跳过一些步骤。

您可能还需要切换到更适合旋转的数据结构,例如std::liststd::deque,至少对于处理实际旋转的对象来说是这样。

我认为问题在于auto pivot = std::find(a.begin(), a.end(), a[i]);行,这将发现a[i]处的值出现的第一个实例。

可以考虑以下实现:

vector<vector<int>> all_rot(const vector<int>& a){
  vector<vector<int>> b;
  for (auto it = a.begin(); it != a.end(); ++it){
    vector<int> dest(a.size());
    dest = std::rotate_copy(a.begin(), it, a.end(), dest.begin());
    if (b.size() != 0 && dest == b[0]){ return b; } // checks to see if you have repetition in cycles.
    b.push_back(dest);
    for (const auto item& : dest){
      std::cout << item << " ";
    }
    std::cout << endl;
  }
  return b;
}

既然你知道pivot(上面我叫它it)在ith位置,我们不需要找到它。不过,因为我们只需要迭代器,所以我只迭代输入中的每个元素,并基于该元素旋转。

另一个需要考虑的边缘情况是当每个元素都相同时。

如果向量的所有元素都相同,则正好有1次不同的旋转。