题目
分析题目
如何变大:从低位挑一个大一点的数,交换前面一个小一点的数。
变大的幅度要尽量小。
像 [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;