输入一个数比如:5.产生序列:1 2 3 4 5.
然后输出它的全排列,有5!个组合。
具体产生方法:
【例】 如何得到346987521的下一个 1,从尾部往前找第一个P(i-1) < P(i)的位置 3 4 6 <- 9 <- 8 <- 7 <- 5 <- 2 <- 1 最终找到6是第一个变小的数字,记录下6的位置i-1 2,从i位置往后找到最后一个大于6的数 3 4 6 -> 9 -> 8 -> 7 5 2 1 最终找到7的位置,记录位置为m 3,交换位置i-1和m的值 3 4 7 9 8 6 5 2 1 4,倒序i位置后的所有数据 3 4 7 1 2 5 6 8 9 则347125689为346987521的下一个排列
这4步很形象。我的程序也是按照这4步来的。
#include <stdlib.h> #include <string> #include <string.h> #include <iostream> #include <vector> #include <algorithm> #include <forward_list> #include <list> #include <deque> #include <numeric> using namespace std; int main(int argc, char*argv[]) { int n; while (cin>>n) { int *a = (int*)malloc(sizeof(int)*n); for (int i = 1; i < n + 1; i++) { a[i-1] = i; } //获得数组 int nn = 1; for (int i = n; i>0; i--) { nn *= i; } nn--;//产生阶乘,但是要--,因为没有顺序的那个数组 while (nn--) { int index = 0; for (int j = n - 1; j>0; j--) { index = j - 1; if (a[j - 1] < a[j]) { index = j - 1; break; } }//找到第一个降序的下标 int min = a[index]; int index_swap = index; for (int j = index; j < n; j++) { if (a[j]>min) { index_swap = j; } }//在那个i-1下标后面找到最后一个比降序第一个元素大的元素 int tmp = a[index_swap]; a[index_swap] = a[index]; a[index] = tmp;
//交换两个元素 for (int i = index + 1; i < n - 1; i++) { for (int j = index + 1; j < n - 1 - i + index + 1; j++)//冒泡是每个次方最后一个,加入i=index+1,则第一次j的最后值肯定是n-1,所以为n-1-i+index+1 { if (a[j]>a[j + 1]) { int tmp = a[j]; a[j] = a[j + 1]; a[j + 1] = tmp; } } }
//用冒泡排列i-1(index)后面的所有元素,注意第二个循环的变量 int i; for (i = 0; i < n; i++) { cout << a[i]; } cout << endl; } free(a); a = NULL; } return 0; }