Letcode经典黄题——三数之和

还是那句话,一个题思路很重要,没有思路等于无头苍蝇乱撞

题目要求:给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

第一种
我们可以采用暴力的手法,直接整三个循环,但是这样有很多弊端.
1.复杂度太高下来的话他需要O(n^3)。
2.最最关键的是不能重复。
第二种
我们可以采用排序加双指针的方法来完成。
1.排序的话个人建议不要用库里面的函数,我们能自己敲尽量自己敲,巩固我们的知识,当然我指的是快排之类的而不是那些冒泡选择排序。
2.双指针从左到右依次遍历,当我们从小到大将数字排好之后,如果检测到数字小则左边向右移一位,如果检测到数字大我们将右边指针向左移一位。
3.为了避免重复 我们在中间设立while循环 如果这个数和下一个数相等我们++,直至不相等再开始比较。
特别注意
本题需要返回的要求有三点
Letcode经典黄题——三数之和_第1张图片
第一个意思就是:returnSize表示返回数组的行数。
第二个意思是:数组的大小以
returnColumnSizes数组的形式返回。
第三个意思是:返回的数组和*columnSizes数组都必须进行mallocated,假设调用者调用free()。

下面看具体代码实现
首先排序这边我们使用快排:Quicksort(nums,0,numsSize-1);

int Sort(int* arr,int left,int right)
 {
     int i=left,j=right;
     int temp=arr[i];
     while(i<j)
     {
        while(i<j&&arr[j]>=temp)
        j--;
        arr[i]=arr[j];
        while(i<j&&arr[i]<=temp)
        i++;
        arr[j]=arr[i];
     }
     arr[i]=temp;
     return i;
 }

 void Quicksort(int* arr,int left,int right)
 {
    if(left<right)
    {
        int i=Sort(arr,left,right);
        Quicksort(arr,left,i-1);
        Quicksort(arr,i+1,right);
    }
 }

排序好之后
我们进行双指针查找,
由于力扣一直在跟我讲空间不够,所以我一气之下直接开了10w个空间

int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes)
{
    int** res=(int**)malloc(sizeof(int)*100000);//存储答案
    *returnColumnSizes=(int*)malloc(sizeof(int)*100000);//题目要求
    Quicksort(nums,0,numsSize-1); //快排对数组进行排序
    * returnSize=0; //返回的row
    for(int i=0;i<numsSize;i++)//右左向右一个数一个数遍历
    {
        if(i>0&&nums[i]==nums[i-1])  //判断最初是否和前一个相等,避免重复项
        {
            continue;
        }
        int left=i+1,right=numsSize-1;
        while(left<right)  //双指针遍历
        {
            if(nums[left]+nums[right]==-nums[i])  //满足条件存入数组
            {
                res[*returnSize]=(int*)malloc(sizeof(int)*3);  //开辟空间
                (*returnColumnSizes)[*returnSize]=3;
                res[*returnSize][0]=nums[i];
                res[*returnSize][1]=nums[left];
                res[*returnSize][2]=nums[right];
                (*returnSize)++;
            }
            if(nums[left]+nums[right]<-nums[i]) //如果小于目标值则left++
            {
                while(left<right&&nums[left]==nums[left+1])//避免重复
                left++;
                left++; 
            }
            else//如果大于目标值则right--
            {
                while(left<right&&nums[right]==nums[right-1]) //避免重复
                right--;
                right--;
            }
        }
    }
    return res;//返回结果数组
}

时间复杂度分析,从左到右遍历是O(n),双指针是O(n),嵌套则是O(n^2).

你可能感兴趣的:(算法,C语言,算法,排序算法,数据结构)