🌈【LeetCode.31下一个排列】- JavaScript =>双指针解法

382 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。


说明:文章部分内容及图片出自网络,如有侵权请与我本人联系(主页有公众号:小攻城狮学前端)

作者:小只前端攻城狮、 主页:小只前端攻城狮的主页、 来源:掘金

GitHub:P-J27、 CSDN:PJ想做前端攻城狮

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


题目描述

实现获取 下一个排列 的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列(即,组合出下一个更大的整数)。

如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。

必须 原地 修改,只允许使用额外常数空间。

示例 1:

输入:nums = [1,2,3]
输出:[1,3,2]
思路1:
  1. 小数和大数交换即可,关键小数是从后到前第一个上升序列的前一个数(否则小数选别的都是变小,或者不是最近的更大的数)
  2. 大数是从最后一个数到小数后一个数中第一个大于小数的数,交换大小数
  3. 经过上面两步选择,小数的后一个数到最后必定是下降序列,这部分取反
 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。倒序找第一个后 > 前位置,前为待交换位置
  2. 倒序找第一个> 待交换位置的位置,与待交换位置交换
  3. 从待交换位置 + 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)
};

感谢阅读,希望能对你有所帮助,文章若有错误或者侵权,可以在评论区留言或在我的主页添加公众号联系我。

写作不易,如果觉得不错,可以「点赞」+「评论」 谢谢支持❤