我的js算法爬坑之旅-下一个排列

149 阅读1分钟

第三十四天:力扣第31题,下一个排列

思路:先找第一个比左边n大的数字m,再找右边的最小大于n的数,对后面的数再进行排序

var nextPermutation = function(nums) {
  let flag = 0;
  let res = 0;
  for(let i = nums.length - 1; i > 0; i--)
  {
    if(nums[i] > nums[i - 1]){
      res = i;
      flag = 1;
      for(let j = i + 1; j < nums.length; j++)
      {
        if(nums[j] <= nums[res] && nums[j] > nums[i - 1])
        {
          res = j;
        }
      }
      [nums[res],nums[i - 1]] = [nums[i - 1],nums[res]];
      if(res - i > 0)
      {
        var a = nums.slice(-(nums.length - i)).sort((a,b) => a-b);
        nums.splice(i,nums.length - i);
        nums.push(a);
      }
      break;
    }
  }
  return flag == 1 ? nums : nums.sort((a,b) => a - b)
};

代码在idea上可以跑起来,在力扣上是NaN,就很烦

再贴一下大佬的代码,思路其实差不多

function nextPermutation(nums) {
  let i = nums.length - 2;  // 从倒数第二个,向左遍历
  while (i >= 0 && nums[i] >= nums[i + 1]) { // 寻找第一个小于右邻居的数
    i--;
  }
  if (i >= 0) { // 这个数在数组中存在
    let j = nums.length - 1; // 从最后一项,向左遍历
    while (j >= 0 && nums[j] <= nums[i]) { // 寻找第一个小于 nums[i] 的数
      j--;
    }
    [nums[i], nums[j]] = [nums[j], nums[i]]; // 两数交换,实现变大
  }
  // 如果i=-1,说明是递减排列,如 321,则直接翻转为最小排列:123
  let l = i + 1;            // i 右边的数进行翻转,使得变大的幅度小一些
  let r = nums.length - 1;
  while (l < r) {
    [nums[l], nums[r]] = [nums[r], nums[l]];
    l++;
    r--;
  }
}