上周的沸点活动-每日算法题里有一个这样的题目:下一个排列,要求是这样的:
实现获取 下一个排列 的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须 原地 修改,只允许使用额外常数空间。
思路:
1、目的是返回下一个更大的排列,以1 2 3 4为例,依次排列是:
1 2 3 4
1 2 4 3
1 3 2 4
1 3 4 2
.
.
.
4 3 2 1
可以看出后一列一直大于前一列:1234 < 1243 < 1324 < 1342 < ... < 4321
2、我们从末尾开始一步一步向前排列,只要第一次找到nums[length] > nums[length - 1],就返回,然后nums[length]和nums[length - 1]交换,这时如果nums[length]就是最后一位数,没问题,结束了
3、但是如果nums[length]不是最后一位数,则还需要判断nums[length - 1]和nums[flag1 + 1]的大小,如果nums[flag1 + 1]大,这时候交换nums[flag1 - 1] 和nums[flag1 + 1]。
上代码
function nextLargerSpread(nums) {
if (nums.lenght === 1) return nums;
let before,
after,
next;
let flag1 = nums.length - 1,
flag2;
for (let i = 0; i < nums.length; i++) {
if (nums[flag1] > nums[flag1 -1 ]) {
before = nums[flag1 - 1];
after = nums[flag1];
if (nums[flag1 - 1] < nums[flag1 + 1] && nums[flag1 + 1]) {
flag2 = flag1 + 1;
next = nums[flag1 + 1];
nums[flag1 - 1] = next;
nums[flag1 + 1] = before;
} else {
nums[flag1 - 1] = after;
nums[flag1] = before
}
break;
}
flag1--;
if (flag1 === 0) {
nums = nums.reverse();
}
}
if (flag2 < nums.length - 1 && nums[flag2 + 1]) {
let start = (nums.slice(0, flag2 - 1));
let endList = nums.slice(flag2 - 1).sort();
nums = [...start, ...endList];
}
};
上一个imageslr大佬的图:
如果看不懂我的思路的话,可以点击下面链接看看大佬回答的图,我一开始看到这个题目也是一脸懵逼,然后就是看了大佬的图理解的。