方法:通过遍历固定两位后,对另外两位使用双指针法
void QuickSort(int*nums,int left,int right){//快排
if(left>right)
return;
int i=left;
int j=right;
int key=nums[i];
int temp;
while(i<j){
while(i<j&&nums[j]>=key)
j--;
while(i<j&&nums[i]<=key)
i++;
if(i<j){
temp=nums[i];
nums[i]=nums[j];
nums[j]=temp;
}
}
nums[left]=nums[i];
nums[i]=key;
QuickSort(nums,left,i-1);
QuickSort(nums,i+1,right);
}
int** fourSum(int* nums, int numsSize, int target, int* returnSize, int** returnColumnSizes){
if(numsSize<4){
*returnSize=0;
return NULL;
}//如果总长度小于4,直接返回空
QuickSort(nums,0,numsSize-1);//快排
int index=0;
int **number=(int **)malloc(10000*sizeof(int *));
for(int i=0;i<numsSize-3;i++){
if(target>=0&&nums[i]>target)
//如果target是正数或0,且nums数组最小的数大于target,直接退出循环
break;
if(target<=0&&nums[numsSize-1]<target)
//如果target是负数或0,且nums数组最大的数小于target,直接退出循环
break;
if(i>0&&nums[i]==nums[i-1])
//i如果自增后和上一位的i相同,直接continue
continue;
for(int j=i+1;j<numsSize-2;j++){
if(j>i+1&&nums[j]==nums[j-1])
//j如果自增后和上一位的j相同,直接continue
continue;
int left=j+1;
int right=numsSize-1;
//固定j后将left初始化为j+1,right初始化为numsSize-1,遍历时将两个指针向中间移动
while(left<right){
long sum=(long)nums[i]+nums[j]+nums[left]+nums[right];//这里要用long,因为测试里有超级超级大的数
if(sum<target)
left++;//如果和小于target,就将left右移一位
else if(sum>target)
right--;//如果和大于target,则将right左移一位
else{
int *array=(int *)malloc(4*sizeof(int));
array[0]=nums[i];
array[1]=nums[j];
array[2]=nums[left];
array[3]=nums[right];
number[index++]=array;
left++;
right--;
while(left<right&&nums[left]==nums[left-1])
left++;
while(left<right&&nums[right]==nums[right+1])
right--;
}
}//while
}//forj
}//fori
*returnSize=index;
(*returnColumnSizes)=(int *)malloc(index*sizeof(int));
for(int i=0;i<index;i++){
(*returnColumnSizes)[i]=4;
}
return number;
}
除了每轮循环对i和j用if语句判断是否与上一轮的i和j相同外,也可以考虑建立一个bool类型的变量symbol,每次当sum=target时,将number中每个数组的前三位依次与nums[i],nums[j],nums[left]对比,若sum=target且四个数中前三个跟number某数组前三个数相等,说明第四个数也一定相等,所以对应元素相同,不将这四个数加入number数组
当我试了一下,这个方法效率差的有点多…
代码(放在else中):
symbol=false;
if(index>0){
for(int k=0;k<index;k++){
if(nums[i]==number[k][0]&&nums[j]==number[k][1]&&nums[left]==number[k][2]){
symbol=true;
break;
}
}
}
if(symbol){
right--;
left++;
continue;
}