递归-输出整数的全排列
递归
题目
1、本实验要求用递归方法而不是循环方法实现,更不可以直接用语言内置的函数。
2、输入1-20个大于0的正整数(1、2、3或者100、200、300),输入0作为结束,0不参与排列。
3、输出这几个整数的全排列,每个数之间用英文半角","隔开,中间不要有空格,
每个排列单独一行。
分析
每一层递归决定“第 k 位放哪个还没用过的数”,然后递归到第 k+1 位;选完并回溯时,把该数标记为未使用,供其他分支再选。
通俗:要实现利用递归输出整数的所有全排列,可以将每一次递归都是做一个小整数串的递归,上一层需要决定的是起始元素是什么,下一层重复操作;喂给下一层递归的元素有几个、内容是什么由num和ans共享
代码分析
#include <iostream>
using namespace std;
int num[25] ;
bool used[25] ;
int ans[25] ;
int n = 0 ;
void perm ( int k ){
if ( k == n ){
for ( int i = 0 ; i < n ; i++ ){
if ( i > 0 ) cout << ',' ;
cout << ans[i] ;
}
cout << endl ;
return ;
}
for ( int i = 0 ; i < n ; i++ ){
if ( !used[i] ) {
used[i] = true ;
ans[k] = num[i] ;
perm( k+1 ) ;
used[i] = false ;
}
}
}
int main(){
cout << "input" << endl << "output" << endl ;
int x ;
while( n<=20 ){
cin >> x ;
if ( x == 0 ) break;
num[ n ] = x ;
n++;
}
perm( 0 ) ;
cout << "end";
return 0 ;
}
思路探讨
-
我想不到怎么去设一个used【i】这个数组用于回溯?
-
过程思考:
-
假设你是人,给你三个数 1、2、3,让你写出所有排列。你会怎么做?
你大概率会这样:
- 第一位放 1。
- 第二位……1 已经用过了,不能再用,所以只能放 2 或 3。
- 第二位放 2,第三位……1、2 都用过了,只能放 3。
- 得到一个排列 1,2,3。
- 退回去,第二位改放 3,第三位只能放 2,得到 1,3,2。
- 再退回去,第一位改放 2……
你在做这件事的时候,脑子里一直在判断一件事:
“这个数,我前面是不是已经用过了?”
对,就是这个判断。
used[]数组,就是把这个“脑子里记着哪些数用过了”变成代码。需要将人类思考"我这个用过了,还能不能再用"的思考结果转换成机器标记
-
-
没有used标记:
for (int i = 0; i < n; i++) {
ans[k] = num[i];
perm(k + 1);
}输出结果
没有标注的情况会重复利用数据
-
修改成这样,为什么输出结果是一样的?
for (int i = 0; i < n; i++) {
if ( !used[i] ){
used[i] == true ;
ans[k] = num[i];
perm(k + 1);
used[i] == false ;
}
}因为你把赋值写成比较了!!!!!
-
-
浙公网安备 33010602011771号