31. 下一个排列

题目描述

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

  • 例如,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 class Solution {
 2     // 思路: 1.从后往前遍历,找到第一个满足条件 nums[i] > nums[i - 1]。若不存在,则反转数组
 3     //       2.排序[i, length - 1]之间的元素
 4     //       3.从i开始往后找比nums[i]大的元素t,找到后swap(),交换 nums[i - 1] 和 元素t 即可
 5     //       nums[i - 1]相当于分割线
 6     public void nextPermutation(int[] nums) {
 7         int len = nums.length;
 8         int k = -1; // 记录分割节点索引
 9         for (int i = len - 1; i > 0; i--) {
10             if (nums[i] > nums[i - 1]) {
11                 k = i - 1;
12                 break;
13             }
14         }
15         if (k == -1) { // 若不存在,反转整个链表
16             reverse(nums, 0, len - 1); 
17             return;
18         }
19         // [k + 1, len]自然排序
20         Arrays.sort(nums, k + 1, len);
21         // 从k + 1处往后找比nums[k]大的元素并交换位置
22         for (int i = k + 1; i < len; i++) { 
23             if (nums[i] > nums[k]) {
24                 swap(nums, k, i);
25                 break;
26             }
27         }
28 
29     }
30     // 反转数组[i, j]之间的元素
31     void reverse(int[] nums, int i, int j) {
32         while (i < j) {
33             swap(nums, i, j);
34             i++;
35             j--;
36         }
37     }
38     // 交换nums[i], nums[j]两元素
39     void swap(int[] nums, int i, int j) {
40         int tem = nums[i];
41         nums[i] = nums[j];
42         nums[j] = tem;
43     }
44 }
posted @ 2023-04-04 18:49  along-Blog  阅读(13)  评论(0编辑  收藏  举报