下一个排列问题的思考过程

题目链接:下一个排列

不妨先看一下全排列的生成,

例如 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]大的第一个(这个使一定有的)。

至此,分析结束。

原文地址:https://www.cnblogs.com/backinfile/p/6445922.html