算法题目 -- 下一个排列

109 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情

下一个排列

整数数组的一个排列,就是将其所有成员以序列或线性顺序排列。

例如有一串数字,123,它的字典序是123,132,213,231,312,321。所谓整数数组字典序的下一个排列,就是指找到数组的一个排序,使其组成的数比当前数大的最小的数。

例如,arr = [1,2,3] 的下一个排列是 [1,3,2] 。

类似地,arr = [2,3,1] 的下一个排列是 [3,1,2] 。

而 arr = [3,2,1] 的下一个排列是 [1,2,3] ,因为 [3,2,1] 不存在一个字典序更大的排列。 给你一个整数数组 nums ,找出 nums 的下一个排列。 必须 原地 修改,只允许使用额外常数空间。

解析

我们带入一个稍长的例子进行讲解:[2,7,6,3,5,4,1]的下一个排列是什么?即比2763541大的最小数是多少?

  • 步骤1: 2763541 [找最后一个正序35]
  • 步骤2 : 2763541 [找3后面比3大的最后一个数]
  • 步骤3: 2764531 [交换3,4的位置]
  • 步骤4: 2764135 [把4后面的531反序排列为135即得到最后的排列(q)]

可得比2763541大的最小数:2764135。

总结

先遍历数组找到最后一个正序

     for (int i = 0; i < nums.length - 1; i++) {
         //找到最后的两个正序
         if (nums[i] < nums[i + 1]) {
             local = i;
         }
     }

找到比正序的第一个数字大的最后一个数

for (int j = local + 2; j < nums.length; j++) {
             if (nums[local] < nums[j] && nums[j] <= nums[k]) {
                 k = j;
             }
         }

交换两数的位置

public static void swap(int[] nums, int l, int r) {
    int temp = nums[l];
    nums[l] = nums[r];
    nums[r] = temp;
}

将该位置以后的数组反序

public static void change(int[] nums, int l, int r) {
    while (l < r) {
        swap(nums, l++, r--);
    }
}

代码

public static void next(int[] nums) {
     int local = -1;
     for (int i = 0; i < nums.length - 1; i++) {
         //找到最后的两个正序
         if (nums[i] < nums[i + 1]) {
             local = i;
         }
     }
     if (local == -1) {
         change(nums, 0, nums.length - 1);
     } else {
         //此时的i是最后一个正序
         int k = local + 1;
         //找到两个正序中的第一个,后面比他大的最小数,交换
         for (int j = local + 2; j < nums.length; j++) {
             if (nums[local] < nums[j] && nums[j] <= nums[k]) {
                 k = j;
             }
         }
         swap(nums, local, k);

         //将该位置后的数反序
         change(nums, local + 1, nums.length - 1);
     }
 }
 
public static void change(int[] nums, int l, int r) {
    while (l < r) {
        swap(nums, l++, r--);
    }
}

public static void swap(int[] nums, int l, int r) {
    int temp = nums[l];
    nums[l] = nums[r];
    nums[r] = temp;
}