假设有类似下面的多重循环:
for(i=0; i<3; i++)
for (j=2; j<6; j++)
for (k=5; k<16; k++)
for (l=3; l<5; l++)
{
//do something with i,j,k,l
}
像上面一共有4重循环,有时候可能更多,如何将任意多重循环用2重循环来改写呢?
方法1:
int main()
{
vector<int> upper = {3,6,16,5};
vector<int> lower = {0,2,5,3};
vector<int> index = lower;
int level;
do{
level =upper.size() - 1;
//do something with index[]
for (auto i : index) cout<<i<<" ";
cout<<endl;
while(level >= 0 && (++index[level] >= upper[level])) {
index[level] = lower[level];
level--;
}
} while (level >= 0);
return 0;
}
输出结果为:
0 2 5 3
0 2 5 4
0 2 6 3
...
2 5 15 3
2 5 15 4
上面的两层循环中,外层的do循环每次都从level=3开始,经过内层循环后检测level是不是还>=0。内层循环会做如下工作:
1) ++index[level]
2) 判断当前的level是不是已经到边界(upper[level]),
如果已到边界,将index[level]重新置为起始值,并将level减1,也就是到了上面一层;
否则跳过内层循环。
3) 什么时候终止外层循环呢? 当level < 0时。而level<0只有可能内部的while循环总共执行了4次已经,即index[0], index[1], index[2], index[3]分别和lower[0], lower[1], lower[2], lower[3]相等后,level再--,此时level = -1。
如果还想不明白,在//do something的地方打印出index[0],index[1], index[2], index[3]即可,它们分别对应前面的i,j,k,l。也可以用下面的方法,原理差不多:
方法2:
注意do while循环只有当level = -1才终止。此时对应所以的组合都打印完毕,即从0,2, 6, 5打印到2,5,15,4,最后当index[]={2,5,15,4}时,对应for循环内部level--已经执行了4次,然后level再--,此时level = -1。注意没有打印到最后时,for循环内部level--都没有执行过4次,因为都break出来了。
int main()
{
const vector<int> upper = {3, 6, 16, 5};
const vector<int> lower = {0, 2, 5, 3};
vector<int> index = lower;
int level;
do{
for (auto i : index) cout<<i<<" ";
cout<<endl;
for (level = upper.size() - 1; level >= 0; level--) {
index[level]++;
if (index[level] >= upper[level])
index[level] = lower[level];
else
break;
}
} while (level >= 0);
return 0;
}
方法3:
说起循环我们就应该想到递归,所以我们也可以用递归来改写这个多重循环,原理跟上面的方法差不多,只是外层循环用递归代替了。代码如下:
const vector<int> upper = {3, 6, 16, 5};
const vector<int> lower = {0, 2, 5, 3};
void dfs(vector<int> & nums, int level) {
//do something with arr[], such as print
for (auto n : nums) cout<<n<<" ";
cout<<endl;
bool endCondition = true;
for (int i = 0; i <= level; ++i) {
if (nums[i] < upper[i] - 1) {
endCondition = false;
break;
}
}
if (endCondition) return;
for (int i = nums.size() - 1; i >= 0; i--) {
nums[i]++;
if (nums[i] >= upper[i])
nums[i] = lower[i];
else
break;
}
dfs(nums, level);
}
int main()
{
vector<int> nums = lower;
dfs(nums, 4);
return 0;
}
调用的时候用dfs(index, 3)即可。