31. 下一个排列
最后更新:2024-05-12-22
链接:https://leetcode.cn/problems/next-permutation/description/
题目描述
整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。
- 例如,
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
的下一个排列。
必须 原地 修改,只允许使用额外常数空间。
题目示例
输入: nums = [1,2,3]
输出: [1,3,2]
输入: nums = [3,2,1]
输出: [1,2,3]
输入: nums = [1,1,5]
输出: [1,5,1]
提示:
- \(1 <= nums.length <= 100\)
- \(0 <= nums[i] <= 100\)
分割数组,然后排序,交换
C |
---|
| int compare(void *a, void *b)
{
return *(int*)a - *(int*)b;
}
void swap(int *a, int *b) {
int t = *a;
*a = *b, *b = t;
}
int findLastPeakPos(int* nums, int numsSize)
{
int cur = numsSize - 2;
while (cur >= 0) {
if (nums[cur + 1] > nums[cur]) {
break;
}
cur--;
}
cur++;
return cur;
}
int findSwapPos(int* nums, int numsSize, int pos)
{
for (int i = pos; i < numsSize; i++) {
if (nums[i] > nums[pos]) {
return i;
}
}
return -1;
}
void nextPermutation(int* nums, int numsSize)
{
if ((nums == NULL) || (numsSize < 2)) {
return;
}
int last_peak = findLastPeakPos(nums, numsSize);
qsort(nums + last_peak, (numsSize - last_peak), sizeof(int), compare);
if (last_peak < 1) {
return;
}
int swap_pos = findSwapPos(nums, numsSize, (last_peak - 1));
if (swap_pos < 0) {
return;
}
swap(&nums[last_peak - 1], &nums[swap_pos]);
}
|
我们可以把当前的序列分割成两个子序列a和b,以从后往前的第一个峰值为中心点。
那么中心点之后的子序列,其下一个序列必然是对b进行升序重排列的序列。
因为下一个序列要比当前序列更大,那么我们只能找到b中比a大的第一个值,然后两个数字交换即可
- 从后往前找到第一个降序的值a = nums[pos]
- 从后往前找到比a大的那个值b
- 交换a、b两个值
- 对pos 之后的数组进行升序排序
特殊:如果本身就是降序的,那么下一个序列就是全数组升序。
C |
---|
| int compare(void *a, void *b)
{
return *(int*)a - *(int*)b;
}
void swap(int *a, int *b) {
int t = *a;
*a = *b, *b = t;
}
void nextPermutation(int* nums, int numsSize)
{
if ((nums == NULL) || (numsSize < 2)) {
return;
}
// 第一步,从后往前找第一个下降的点
int i = numsSize - 2;
while (i >= 0) {
if (nums[i + 1] > nums[i]) {
break;
}
i--;
}
if (i < 0) {
// 整改序列是降序的,直接重排
qsort(nums, numsSize, sizeof(int), compare);
return;
}
int j = numsSize - 1;
while (j >= 0) {
if (nums[j] > nums[i]) {
break;
}
j--;
}
swap(&nums[i], &nums[j]);
// 对i之后的进行排序
qsort(&nums[i + 1], (numsSize - i - 1), sizeof(int), compare);
}
|