题目
整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。
- 例如,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:
输入:
输出:
示例 2:
输入:
输出:
示例 3:
输入:
输出:
提示:
题解
怎么说呢,首先你得读懂题目。
就是按照升序排序,然后依次选取次大的元素进行排序组合。
举个例子,
所以下一个排列就是
这道题记住思路,就很容易解决。
1、从右开始遍历,先找出第一个索引,满足,如果不存在,就翻转整个数组;
2、再从右开始遍历,找出第二个索引,满足;
3、交换和;
4、最后翻转。
比如,下一个排列是什么?
我们找到第一个索引是;
再找到第二个索引是;
交换,;
翻转,。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| class Solution { public: void nextPermutation(vector<int>& nums) { if (nums.size() == 0) { return; } int firstIndex = -1; for (int i = nums.size() - 2; i >= 0; i--) { if (nums[i] < nums[i + 1]) { firstIndex = i; break; } } if (firstIndex == -1) { reverse(nums.begin(), nums.end()); return; } int secondIndex = -1; for (int i = nums.size() - 1; i > 0; i--) { if (nums[i] > nums[firstIndex]) { secondIndex = i; break; } } int temp = nums[firstIndex]; nums[firstIndex] = nums[secondIndex]; nums[secondIndex] = temp; reverse(nums.begin() + firstIndex + 1, nums.end()); } };
|
题目
给定一个整数数组来表示排列,按升序找出其上一个排列。
示例 1:
输入:
输出:
示例 2:
输入:
输出:
示例 3:
输入:
输出:
提示:
题解
跟下一个排列一样,只不过求的是上一个,而不是下一个。
举个例子,
所以上一个排列就是
所以只需要根据第一题的代码,只用把遍历里的>换成<即可。
1、从右开始遍历,先找出第一个索引,满足,如果不存在,就翻转整个数组;
2、再从右开始遍历,找出第二个索引,满足;
3、交换和;
4、最后翻转。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| class Solution { public: void prevPermutation(vector<int>& nums) { if (nums.size() == 0) { return; } int firstIndex = -1; for (int i = nums.size() - 2; i >= 0; i--) { if (nums[i] > nums[i + 1]) { firstIndex = i; break; } } if (firstIndex == -1) { reverse(nums.begin(), nums.end()); return; } int secondIndex = -1; for (int i = nums.size() - 1; i > 0; i--) { if (nums[i] < nums[firstIndex]) { secondIndex = i; break; } } int temp = nums[firstIndex]; nums[firstIndex] = nums[secondIndex]; nums[secondIndex] = temp; reverse(nums.begin() + firstIndex + 1, nums.end()); } };
|
题目
给你一个正整数数组 arr(可能存在重复的元素),请你返回可在 一次交换(交换两数字 arr[i] 和 arr[j] 的位置)后得到的、按字典序排列小于 arr 的最大排列。
如果无法这么操作,就请返回原数组。
示例 1:
输入:
输出:
解释:交换 2 和 1
示例 2:
输入:
输出:
解释:已经是最小排列
示例 3:
输入:
输出:
解释:交换 9 和 7
提示:
题解
这题跟我『上一个排列』差不多,主要是它找的排列是两个元素调换位置的,不像『上一个排列』那样,元素可以全部重排。
那首先照搬『上一个排列』解法,最后交换 firstIndex 和 secondIndex ,不用 reverse 逆序排列。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| class Solution { public: vector<int> prevPermOpt1(vector<int>& nums) { if (nums.size() == 0) { return nums; } int firstIndex = -1; for (int i = nums.size() - 2; i >= 0; i--) { if (nums[i] > nums[i + 1]) { firstIndex = i; break; } } if (firstIndex == -1) { return nums; } int secondIndex = -1; for (int i = nums.size() - 1; i > 0; i--) { if (nums[i] < nums[firstIndex]) { if (nums[i] == nums[i - 1]) { continue; } secondIndex = i; break; } } int temp = nums[firstIndex]; nums[firstIndex] = nums[secondIndex]; nums[secondIndex] = temp; return nums; } };
|