思想
使用数组里的数字,看成n位的10进制数,然后从小到大进行数数;
C代码
/**
* Return an array of arrays of size *returnSize.
* The sizes of the arrays are returned as *returnColumnSizes array.
* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
*/
int comp(const void *a, const void *b) {
return *((int *)a) - *((int *)b);
}
void swap(int *nums, int a, int b) {
nums[a] ^= nums[b];
nums[b] ^= nums[a];
nums[a] ^= nums[b];
}
int* copy_arr(int *nums, int numsSize) {
int *ret = NULL;
if (numsSize <= 0) {
return NULL;
}
ret = calloc(numsSize, sizeof(int));
memcpy(ret, nums, sizeof(int) * numsSize);
return ret;
}
int find_idx(int *nums, int numsSize, int *s, int *e) {
int si, ei;
if(numsSize <= 1) {
return -1;
}
ei = numsSize - 1;
si = numsSize - 2;
while(1) {
if(si < 0 || ei < 1)
break;
if(nums[si] >= nums[si+1]) {
si--;
continue;
}
if(nums[ei] <= nums[si]) {
ei--;
continue;
}
*s = si;
*e = ei;
return 0;
}
return -1;
}
int* find_next(int *nums, int numsSize) {
int s,e;
int *ret = NULL;
if(find_idx(nums, numsSize, &s, &e) == -1) {
return NULL;
}
ret = copy_arr(nums, numsSize);
swap(ret, s, e);
qsort(ret+s+1, numsSize-s-1, sizeof(int), comp);
return ret;
}
int** permute(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
int **ret = NULL;
int *t = NULL;
int listSize = 1 << 4;
int ls = 1;
int i;
ret = calloc(listSize, sizeof(int *));
qsort(nums, numsSize, sizeof(int), comp);
ret[ls-1] = nums;
t = nums;
while(1) {
t = find_next(t, numsSize);
if( t == NULL)
break;
ls++;
if(ls > listSize - 4) {
listSize = listSize << 1;
ret = realloc(ret, listSize * sizeof(int *));
}
ret[ls-1] = t;
}
*returnSize = ls;
*returnColumnSizes = calloc(ls, sizeof(int));
for(i = 0; i < ls; i++) {
(*returnColumnSizes)[i] = numsSize;
}
return ret;
}
注意点
- 数字从小到大排,所以开始
find_idx()
函数里面的si
应该是找第一个顺序对,即nums[si]>=nums[si+1]
时说明可以跳过si; - 注意遍历过程中,上一个数组的保留,因为上一个数组的结果是下一个迭代的入参,这样避免重复输入nums初始值导致死循环超时;