下一个排列问题的思考过程
题目链接:下一个排列
不妨先看一下全排列的生成,
例如 nums = [1,2,3,4]
1.取出最小值1,再将[2,3,4]排列, 暂令nums = [2,3,4]
2.再取出最小值2, 令nums = [3,4]
3.再取出最小值3, 令 nums = [4]
4,将以上取出的值合并,为[1,2,3,4],第一个排列
5,回溯到第3步时,取出次小值4,合并生成 [1,2,4,3]
6.回溯到第2步时, 取出次小值3,最终生成 [1,3,2,4],[1,3,4,2]
7.第2步还可以回溯, 取次小值4,可生成 [1,4,2,3],[1,4,3,2]
8.继续回溯直到 [4,3,2,1]
粗暴的讲,就是以下的python代码:
nums = [1,2,3,4] [(x,y,z,k) for x in nums for y in nums if y != x for z in nums if z != x and z != y for k in nums if k != x and k != y and k != z]
[(1, 2, 3, 4), (1, 2, 4, 3), (1, 3, 2, 4), (1, 3, 4, 2), (1, 4, 2, 3), (1, 4, 3, 2), (2, 1, 3, 4), (2, 1, 4, 3), (2, 3, 1, 4), (2, 3, 4, 1), (2, 4, 1, 3), (2, 4, 3, 1), (3, 1, 2, 4), (3, 1, 4, 2), (3, 2, 1, 4), (3, 2, 4, 1), (3, 4, 1, 2), (3, 4, 2, 1), (4, 1, 2, 3), (4, 1, 3, 2), (4, 2, 1, 3), (4, 2, 3, 1), (4, 3, 1, 2), (4, 3, 2, 1)]
可以看到,再求下一个排列时,前几位数字一般不变,只有在后面几个数字完全逆序时,才会变。例如:
3,4,2,1
4,2,1为逆序,则3必须变。怎么变呢,取次小值4,剩3,2,1 ,这里必须使3,2,1顺序。生成4,1,2,3.
伪代码:
for (int i = 0; i < LENGTH; i++) { if (i到LENGTH-1逆序) { nums[i] = 次小值 i+1到LENGTH-1排序 return nums } }
其中次小值取自i到LENGTH-1之中。
再做一次变形:
看到伪代码中,不就是在数组尾部找到一个逆序组吗,咱可以假设尾部有一个逆序数组,找一个非逆序的(顺序的)就好了。
for (int i=LENGTH-1; i>0; i++) { if (nums[i] > nums[i-1]) { // 顺序的!! nums[i] = 取次小值 排序(反转)i+1到LENGTH-1 return nums } } 反转nums // 找不到就反转整个数组 return nums
注意上面 排序==反转,因为后面都是逆序。
次小值怎么去呢,就是比nums[i]大的第一个(这个使一定有的)。
至此,分析结束。