题目

31_下一个排列_i++

分析题目

 如何变大:从低位挑一个大一点的数,交换前面一个小一点的数。

变大的幅度要尽量小。
像 [3,2,1] 这样递减的,没有下一个排列,已经稳定了,没法变大。
像 [1,5,2,4,3,2] 这种,怎么稍微变大?

从低位挑一个大一点的数,尽量低位,换掉它前面一个小一点的数。

即从右往左,寻找第一个比右邻居小的数,把它换到后面去

“第一个”意味着会尽量在低位,“比右邻居小”意味着它是从右往左的第一个波谷

比如,1 5 (2) 4 3 2,中间这个 2。

接着依然从右往左,寻找第一个比这个 2 微大的数。15 (2) 4 (3) 2,交换后变成 15 (3) 4 (2) 2。

还没结束!变大的幅度可以再小一点,仟位微变大了,后三位可以再小一点。

后三位肯定是递减的,翻转,变成[1,5,3,2,2,4],即为所求。

代码

after是右相邻数值的索引值,i是从右边倒数第二位开始的,因为还要给右相邻留给位置。

如果当前索引值比右相邻大,则从右到左找一个比当前值大一点的值交换位置。这个大一点的值一定能找得到,因为最差的情况我还有右相邻点。为什么从右向左找呢? 最右边代表个位,然后十位百位....

找到后交换该值和大一点的值顺序。此时产生的新值,绝对比原值大,因为第i位比原来大。

for (let i = nums.length - 2; i >= 0; i--) {
                if (change == 1)
                    break;
                after = i + 1;
                if (nums[i] < nums[after]) {
                    //从左往右找一个稍微比它大一点的
                    for (let j = nums.length - 1; j > i; j--) {
                        if (nums[j] > nums[i]) {
                            index = j;
                            let temp;
                            temp = nums[i];
                            nums[i] = nums[index];
                            nums[index] = temp;
                            change = 1;
                            index = i;
                            break;
                        }
                    }
                }
            }

如果change为0说明没改变,这个值原本就是nums数组能拼出的最大值,我们按题目要求改成最小值,sort给数字排序时参数里记得要添加一个函数。

change为1说明改变了,index指向的是交换顺序两个数中的高位的索引值(靠左边是是高位),index右边的数组我们按从小到大排序然后赋值给nums的对应位置即可。

不用担心新数组拼成的数会不会比原值小,新数组有个高位比原数组的高位数值大,高位右边的低位们不管怎样组合,最终的结果都会比原来的值大。

       if (change == 0)
                // 没有改变 说明原数是最大值
                nums.sort(mysort); //变成最小排列
            else //改变了
            {
                if (index != nums.length - 1) {
                    let arr = nums.slice(index+1,nums.length).sort(mysort);
                    let t = 0;
                    for (let i = index + 1; i < nums.length ; i++) {
                        nums[i] = arr[t];
                        t++;
                    }
                }

            }
            return nums;

31_下一个排列_数组_02