问题描述
我们需要找到一个整数数组的下一个字典序排列。如果不存在更大的排列,则将其重置为最小的升序排列。关键约束是必须在原地操作,不能分配额外内存。
核心思路
要找到下一个更大的排列,关键在于找到数组中'可提升'的位置。我们从右向左扫描,寻找第一个满足 nums[i-1] < nums[i] 的位置。这个位置左侧的元素决定了前缀不变,而右侧的子序列目前是降序的(即最大状态)。
一旦找到这个分界点 i-1,我们需要在右侧降序子序列中找到一个刚好比 nums[i-1] 大的元素进行交换。这样能保证新排列只比原排列大一点点。交换之后,右侧子序列依然是降序的,为了得到'下一个'排列,我们需要将其反转为升序(即最小状态)。
如果整个数组都是降序的(例如 4321),说明已经是最大排列,此时直接将整个数组反转即可得到最小排列(1234)。
代码实现
下面是具体的 C 语言实现。注意这里的排序部分使用了简单的冒泡排序来保持逻辑清晰且无需额外库函数,实际工程中可根据需求替换为更高效的排序方式。
void sort(int* nums, int numsSize, int index) {
int i, j, tmp;
int swapped;
for (i = index; i < numsSize; i++) {
swapped = 0;
for (j = index; j < numsSize - 1; j++) {
if (nums[j] > nums[j + 1]) {
tmp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = tmp;
swapped = 1;
}
}
if (!swapped)
break;
}
}
void nextPermutation(int* nums, int numsSize) {
int i = numsSize - 1;
int j = numsSize - 1;
int tmp;
while (i >= 1) {
if (nums[i] > nums[i - 1]) {
while (nums[i - 1] >= nums[j]) {
j--;
}
tmp = nums[i - ];
nums[i - ] = nums[j];
nums[j] = tmp;
sort(nums, numsSize, i);
;
} (i == ) {
(i = ; i < numsSize / ; i++) {
tmp = nums[i];
nums[i] = nums[numsSize - - i];
nums[numsSize - - i] = tmp;
}
;
} {
i--;
}
}
}

