小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
说明:文章部分内容及图片出自网络,如有侵权请与我本人联系(主页有公众号:小攻城狮学前端)
作者:小只前端攻城狮、 主页:小只前端攻城狮的主页、 来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
题目描述
实现获取 下一个排列 的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列(即,组合出下一个更大的整数)。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须 原地 修改,只允许使用额外常数空间。
示例 1:
输入:nums = [1,2,3]
输出:[1,3,2]
思路1:
- 小数和大数交换即可,关键小数是从后到前第一个上升序列的前一个数(否则小数选别的都是变小,或者不是最近的更大的数)
- 大数是从最后一个数到小数后一个数中第一个大于小数的数,交换大小数
- 经过上面两步选择,小数的后一个数到最后必定是下降序列,这部分取反
var nextPermutation = function (nums) {
// 为了找更大的下一个数字
// 1、需要将左边的小数和右边的大数交换
// 2、然后将交换完的大数后改成升序
// 找小数
let left = 0, temp = 0
for (let i = nums.length - 1; i > 0; i--) {
if (nums[i] > nums[i - 1]) {
left = i - 1
temp = i
break
}
}
// 找大数(因为temp后面都是递减的)
let right = 0
for (let i = nums.length - 1; i >= temp; i--) {
if (nums[i] > nums[left]) {
right = i
break
}
}
// 交换
let a = nums[left]
nums[left] = nums[right]
nums[right] = a
// 交换完之后把temp到最后升序(直接取反)
// nums = nums.slice(0, temp).concat(nums.slice(temp).reverse())
思路2;双指针
- 初始待交换位置为-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)
};
感谢阅读,希望能对你有所帮助,文章若有错误或者侵权,可以在评论区留言或在我的主页添加公众号联系我。
写作不易,如果觉得不错,可以「点赞」+「评论」 谢谢支持❤