一、题目描述
二、思路
双指针法:
先对数组进行排序,将无序数组变为有序数组;接着设置三个指针i、left、right,进行如下操作:
首先判断 i 指针,若nums[ i ] > 0,则整个数组找不出满足条件的三元组,跳出循环;若满足 ( i > 0 && nums[ i ] == nums[ i - 1] ),则移动 i 至 nums[ i ] != nums[ i - 1] 处。当 nums[ i ] + nums[ left ] + nums[ right ] < 0 时,将 left 指针向右移动,以此来增大 nums[ left ] 的值,从而使和接近 0 ;同理,当 nums[ i ] + nums[ left ] + nums[ right ] > 0 时,将right指针向左移动,直到 right 与 left 指针相遇为止;当 nums[ i ] + nums[ left ] + nums[ right ] == 0 时,记录三元组,并移动 left 指针直到 nums[ left ] != nums[ left - 1 ] 为止,同理,移动 right 指针直到nums[ right ] != nums[ right + 1 ],从而保证不会得到重复的三元组。
三、解题过程
-
实现快速排序接口函数
void swap(int* arr, int a, int b){
int tmp = arr[a];
arr[a] = arr[b];
arr[b] = tmp;
}
void QuickSort(int* arr, int begin, int end){
if(begin >= end) return ;
int key = arr[begin];
int left = begin;
int right = end;
while(left < right){
while(nums[right] >= key && left < right) right --;
while(nums[left] < key && left < right) left ++;
swap(arr, left, right);
}
swap(arr, left, begin);
QuickSort(arr, begin, left);
QuickSort(arr, left + 1,end);
}
-
处理数组并初始化各个变量
QuickSort(nums,0 ,numsSize - 1);
int** cnt = (int**)malloc(sizeof(int*) * 18000);
int index = 0;
int left, right;
int i = 0;
-
进入循环
for(; i < numsSize - 2; i ++){
//当nums[i]大于0时,三数之和不可能为零
if(nums[i] > 0) break;
//移动 i 至 nums[ i ] != nums[ i - 1] 处,保证不会得到重复的三元组
if(i > 0 && nums[i] == nums[i - 1]) continue;
//更新left和right的值
left = i + 1;
right = numsSize - 1;
//进入循环,找到所有不重复的三元组
while(left < right){
int sum = nums[i] + nums[left] + nums[right];
//当三数之和小于零时,将left指针右移
if(sum < 0) left ++;
//当三数之和大于零时,将right指针左移
else if(sum > 0) right --;
//当三数之和等于零时,更新输出数组
else{
int* arr = (int*)malloc(sizeof(int) * 3);
arr[0] = nums[i];
arr[1] = nums[left];
arr[2] = nums[right];
(cnt)[index ++] = arr;
//移动 left 指针直到 nums[left] != nums[left - 1] 为止
while(left < right && nums[left] == nums[left + 1]) left ++;
//移动 right 指针直到nums[ right ] != nums[ right + 1 ]
while(left < right && nums[right] == nums[right - 1]) right --;
//更新left和right
left ++;
right --;
}
}
}
-
更新二维数组的大小并输出数组
*returnSize = index;
*returnColumnSizes = (int*)malloc(sizeof(int) * index);
for(int j = 0; j < index; j ++){
(*returnColumnSizes)[j] = 3;
}
return cnt;
四、代码
/**
* 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().
*/
void swap(int* arr, int a, int b){
int tmp = arr[a];
arr[a] = arr[b];
arr[b] = tmp;
}
void QuickSort(int* arr, int begin, int end){
if(begin >= end) return ;
int key = arr[begin];
int left = begin;
int right = end;
while(left < right){
while(arr[right] >= key && left < right) right --;
while(arr[left] < key && left < right) left ++;
swap(arr, left, right);
}
swap(arr, left, begin);
QuickSort(arr, begin, left);
QuickSort(arr, left + 1,end);
}
int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
QuickSort(nums,0 ,numsSize - 1);
int** cnt = (int**)malloc(sizeof(int*) * 18000);
int index = 0;
int left, right;
int i = 0;
for(; i < numsSize - 2; i ++){
if(nums[i] > 0) break;
if(i > 0 && nums[i] == nums[i - 1]) continue;
left = i + 1;
right = numsSize - 1;
while(left < right){
int sum = nums[i] + nums[left] + nums[right];
if(sum < 0) left ++;
else if(sum > 0) right --;
else{
int* arr = (int*)malloc(sizeof(int) * 3);
arr[0] = nums[i];
arr[1] = nums[left];
arr[2] = nums[right];
(cnt)[index ++] = arr;
while(left < right && nums[left] == nums[left + 1]) left ++;
while(left < right && nums[right] == nums[right - 1]) right --;
left ++;
right --;
}
}
}
*returnSize = index;
*returnColumnSizes = (int*)malloc(sizeof(int) * index);
for(int j = 0; j < index; j ++){
(*returnColumnSizes)[j] = 3;
}
return cnt;
}
时间复杂度:O(n^2)。
五、遇到的问题
- 一开始完全没思路。。。
- 去重的那块绕了好久才绕明白
- 对cnt的动态内存分配不理解为什么是*18000,确实17000之类的小于18000的没能通过,但是,为啥?答案也给的18000,但也没解释。我不李姐。