力扣第 46 题 - 全排列

-
本题需要寻找所有的排列组合可能,根据数学知识可知组合数为数组长度的阶乘,又因为题目给定的数组长度最长为 6,所以组合数最大为 6!=720。
-
这道题和力扣第 31 题很像,31 题是找出输入数组的下一个字典排序,那么本题也可以使用这种思想,找到所有的下一个字典排序就能保证不漏情况。
-
简单回顾一下下一个字典排序的算法逻辑:从数组末尾向前找到第一个极大值点,即 nums[i] < nums[i + 1],再从末尾向前寻找到第一个大于 nums[i] 的元素 nums[j],交换二者位置,最后将包括 nums[i + 1] 的后续数组元素升序排序(左右指针或者 qsort),此时就能保证数组排序是下一个字典序。
-
由于要不断执行下一个字典排序的相关代码,所以将这些代码封装为函数,每次都在系统给定函数中调用即可。具体代码如下:
// 比较函数:用于 qsort 升序排序(生成第一个排列的前提)
int cmp(const void* a, const void* b){
return *(int*)a - *(int*)b;
}
// 辅助函数:交换两个整数的值
void swap(int* a, int* b){
int tmp = *a;
*a = *b;
*b = tmp;
}
// 辅助函数:反转数组 [left, right] 区间的元素
void reverse(int* nums, int left, int right){
while (left < right){
swap(&nums[left], &nums[right]);
left++;
right--;
}
}
bool next(int* nums, int numsSize){
int i, j;
// 步骤 1:从后向前找第一个 nums[i] < nums[i+1] 的位置 i(升序对)
for (i = numsSize - ; i >= ; i--){
(nums[i] < nums[i + ]){
;
}
}
(i == ){
;
} {
(j = numsSize - ; j > i; j--){
(nums[j] > nums[i]){
;
}
}
swap(&nums[i], &nums[j]);
}
reverse(nums, i + , numsSize - );
;
}
** {
qsort(nums, numsSize, (), cmp);
** result = (**)((*) * );
*returnColumnSizes = (*)(() * );
*returnSize = ;
result[*returnSize] = (*)(() * numsSize);
(*returnColumnSizes)[*returnSize] = numsSize;
( k = ; k < numsSize; k++){
result[*returnSize][k] = nums[k];
}
(*returnSize)++;
(next(nums, numsSize)){
result[*returnSize] = (*)(() * numsSize);
(*returnColumnSizes)[*returnSize] = numsSize;
( k = ; k < numsSize; k++){
result[*returnSize][k] = nums[k];
}
(*returnSize)++;
}
result;
}



