leetcode复盘:15.三数之和

leetcode复盘:15.三数之和

题目描述:给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。

一、个人小结:

(1)排序:由于不能包含重复的三元组,需要先对数组进行排序;排序时可以使用C中自带的qsort方法,排序常用代码如下:

 int cmp(const void *a, const void *b) 
 {
	//从小到大排序
     return *(int*)a - *(int*)b;
 }

 //nums为数组名,numsize为数组大小,cmp为比较函数
 //高级做法,可以比较结构体中的数据
 qsort(nums, numsSize, sizeof(int), cmp);

(2)内存申请(二位数组):malloc函数,入参为申请内存大小,赋值前一般强制转化成目标类型,比如一次指针或二次指针。
一维数组内存申请:

int *arrOne = (int*)malloc(arrOneSize * sizeof(int));  

注:arrOne为一次指针类型,则malloc自然强制转化成一次指针类型,arrOne为int型指针,每个元素大小为sizeof(int),且共有arrOneSize个元素,所有内存申请大小为(arrOneSize * sizeof(int)),其单位为字节。
二维数组内存申请:

    int **arrTwo = (int**)malloc(arrTwoSize * sizeof(int *));

注:
(a)与一位数组内存申请如出一辙,只不过arrTwo为二次指针,即指向指针的指针,即*arrTwo或者arrTwo[0]仍然是一个指针;
(b)申请完以上内存后,arrTwo指向的一片内存中,一共可以存放arrTwoSize个int型的指针,所以其大小为(arrTwoSize * sizeof(int *)),单位为字节;
(c)申请完以上内存后,只能存放几个地址,还不能存放用户数据,所有可以针对每个指针,再次申请存放数据的内存:

    int arrTwo[0] = (int *)malloc(arrTwoSize0 * sizeof(int));  
    int arrTwo[1] = (int *)malloc(arrTwoSize1 * sizeof(int));  
    int arrTwo[2] = (int *)malloc(arrTwoSize2 * sizeof(int)); 
    int arrTwo[3] = (int *)malloc(arrTwoSize3 * sizeof(int)); 

(d)arrTwo[0]、arrTwo[1]、arrTwo[2]、arrTwo[3]均为指针,其值存放在第一次为arrTwo申请的内存中,这样的指针一共由arrTwoSize个;而现在arrTwo[0]指向了一片新申请的内存,其中可以存放(arrTwoSize0 * sizeof(int))这么多字节的数据,至此,就完成了二维数组的申请

二:解题过程

解题参考 画家王铁男https://leetcode-cn.com/problems/3sum/solution/chun-c-kuai-pai-shuang-zhi-zhen-by-hua-jia-wang-ti/
(1)先将数组排序;求三数之和,可以先固定一个数,然后求其他两个数;固定当前数后,使用双指针法,一头一尾逐步搜索, 逼近;
(2)本题中,一个大坑在于对returnColumnSizes的处理,该变量实际上使用个一维指针就可以,偏偏要用个二维指针,其实是在当一维指针用,用于存储每个返回数组的长度,其实冗余,题意中已经明确返回数组长度为3,强行提高题目难度;
(3)变量去重,是本题的难点,在数组排序后,遍历cur、low、high时,需要考虑重复;去重操作是本题的精髓所在;在确定cur时,需要针对low、high去重;在遍历cur时,需要对cur去重

/**
 * 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 cmp(const void *a, const void *b) 
 {
     //从小到大
     return *(int*)a - *(int*)b;
 }
int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
        *returnSize = 0;
    if (numsSize < 3) {
        return NULL;
    }
    qsort(nums, numsSize, sizeof(int), cmp);
    //申请内存
    int **threeNum = (int**)malloc(6 * numsSize * sizeof(int *));
    //实际上使用个一维指针就可以,偏偏要用个二维指针,其实是在当一维指针用
    *returnColumnSizes = (int*)malloc(6 * numsSize * sizeof(int));
    int cur = 0;
    int low = cur + 1;
    int high = numsSize - 1;
    while ((nums[cur] <= 0) && (cur < numsSize - 2)) {
        low = cur + 1;
        high = numsSize - 1;
        while (low < high) {
            if (nums[cur] + nums[low] + nums[high] == 0) {
                threeNum[*returnSize] = (int*)malloc(3*sizeof(int));
                //(*returnColumnSizes)[*returnSize] = 3;
                returnColumnSizes[0][*returnSize] = 3;
                threeNum[*returnSize][0] = nums[cur];
                threeNum[*returnSize][1] = nums[low];
                threeNum[*returnSize][2] = nums[high];
                (*returnSize)++;
                //low\high 去重
                while((nums[low] == nums[++low]) && (low < high)){
                }
                while((nums[high] == nums[--high]) && (low < high)){
                }
            } else if (nums[cur] + nums[low] + nums[high] > 0) {
                high--;
            } else {
                low++;
            }
        }
        //cur去重
        while((nums[cur] == nums[++cur]) && (cur < numsSize - 2)){
        }
    }
    return threeNum;
}

三、运行结果

posted @ 2020-07-06 02:18  Pangolin2  阅读(272)  评论(0编辑  收藏  举报