夯实算法-下一个排列

174 阅读2分钟

题目:LeetCode

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

  • 例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3][1,3,2][3,1,2][2,3,1] 。

整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。

  • 例如,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 的下一个排列。

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

示例 1:

输入: nums = [1,2,3]
输出: [1,3,2]

示例 2:

输入: nums = [3,2,1]
输出: [1,2,3]

示例 3:

输入: nums = [1,1,5]
输出: [1,5,1]

提示:

  • 1 <= nums.length <= 100
  • 0 <= nums[i] <= 100

解题思路

根据题目意图:要比当前数大一点,只需把数组元素交换一下,让它变大一点即可。
就是要找到两个点,它们交换以后,数组变大,即要找到nums[right]>nums[left]nums[right] > nums[left],left要尽量大,以使整体增大的幅度最小,nums[right]nums[right]要尽量小,同样是为了整体增大的幅度最小,按此思想,双重循环,找到rightrightleftleft即可解决问题, 获取到leftleftrightright以后,把nums[left]nums[left]nums[right]nums[right]交换,并把leftleft右边的元素升序排序,以使右边最小,就可以保证整体增大的幅度最小

代码实现

public void nextPermutation(int[] nums) {
    //要找到尽量大的left,以及尽量小的nums[right]
    int left = 0;
    int right = 0;
    int min = Integer.MAX_VALUE; //用min来记录最小的nums[right]
    //双重循环,针对每个i找到最小的nums[j]
    for (int i = 0; i < nums.length; i++) {
        for (int j = i + 1; j < nums.length; j++) {
            //如果nums[j] > nums[i],才有可能交换
            if (nums[j] > nums[i]) {
                //如果i更大了,肯定要交换
                if (i > left) {
                    left = i;
                    right = j;
                    min = nums[j];
                } //如果i相等,但是nums[j]更小了,也要交换
                else if (i == left && nums[j] < min) {
                    left = i;
                    right = j;
                    min = nums[j];
                }
            }
        }
    }
    //如果left和right相等,说明循环过程种没有找到合适的交换点,也就是说数组是降序的,那就把数组升序排序后返回即可
    if (left == right) {
        Arrays.sort(nums);
        return;
    }
    //交换
    swap(nums, left, right);
    //把left右边的数按升序排序,以确保最小
    Arrays.sort(nums, left + 1, nums.length);
}

public void swap(int[] arr, int index1, int index2) {
    int temp = arr[index1];
    arr[index1] = arr[index2];
    arr[index2] = temp;
}

运行结果

Snipaste_2023-02-04_22-47-16.png

复杂度分析

  • 空间复杂度:O(n)O(n)
  • 时间复杂度:O(n2)O(n^2)

掘金(JUEJIN)  一起分享知识, Keep Learning!