小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
题目
实现获取 下一个排列 的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列(即,组合出下一个更大的整数)。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须 原地 修改,只允许使用额外常数空间。
示例 1:
**输入:**nums = [1,2,3] 输出:[1,3,2]
示例 2:
**输入:**nums = [3,2,1] 输出:[1,2,3]
示例 3:
**输入:**nums = [1,1,5] 输出:[1,5,1]
示例 4:
**输入:**nums = [1] 输出:[1]
提示:
1 <= nums.length <= 1000 <= nums[i] <= 100
解题思路
- 初始
待交换位置为-1。倒序找第一个后 > 前位置,前为待交换位置 倒序找第一个> 待交换位置的位置,与待交换位置交换- 从
待交换位置 + 1和数组尾部,向中间,双指针交换
代码
var nextPermutation = function(nums) {
let s = (l, r, t) => (t = nums[l], nums[l] = nums[r], nums[r] = t), l = -1, r = nums.length
for(let i = r; i--;)
if (nums[i] > nums[i - 1]) l = i - 1, i = 0
if (l !== -1)
for(i = r; i-- > l;)
if (nums[i] > nums[l]) s(i, l), i = 0
while (++l < --r) s(l, r)
};
结果
完整思路
数组看成数- 数怎样
变大?- 举例:数
19,高位是十位1,低位是个位9高位 < 低位,交换高位和低位成91,数变大
- 举例:数
21,高位是十位2,低位是个位1高位 > 低位,再交换成12,数变小
- 举例:数
- 所以数
变大,需找:高位 < 低位,然后交换
倒序遍历数组,即从低位到高位遍历数。举例:[1, 4, 6, 5]高位 < 低位,然后交换6 > 5过,4 < 6交换,得[1, 6, 4, 5]1645 > 1465新数变大了。如果不要求下一个排列,这样做即可
下一个排列怎么找?- 回到例子
[1, 4, 6, 5] - 个位上的
5比十位上的6更小,更适合与4交换 - 找
4到数组尾部的最小值与4交换 更好 - 回想一下,
4是怎样找到的呢?倒序遍历数组,找高位 < 低位- 这意味着
4到数组尾部,都是高位 > 低位,是一个降序序列 - 数组末尾就是
最小值
- 直接与
数组末尾交换,行不行?- 回到例子:
4 < 5,交换,得[1, 5, 6, 4],似乎可以 - 改下例子:
[1, 4, 6, 3],得[1, 3, 6, 4],变小了 - 所以,除了
4到数组尾部的最小值,还需这个数比4大
- 回到例子:
- 所以,找下一个排列:
倒序遍历数组,从最小值开始,找比4大的
- 回到例子
- 好像还不对?
- 回到例子,交换
4和5,得[1, 5, 6, 4] - 十位
+个位64,显然46更好 - 回想一下,
4到数组尾部,都是高位 > 低位,是一个降序序列- 数组看成
数,降序序列最大。升序序列最小
- 数组看成
- 回到例子,交换
- 双指针交换
- 从
4开始(4 + 1)和数组尾部向中间交换,将降序序列变升序序列即可 - 如果本来就是降序序列,可声明左指针初始为
-1,复用交换逻辑
- 从