zoukankan      html  css  js  c++  java
  • 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)++;
                    //lowhigh 去重
                    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;
    }
    
    

    三、运行结果

  • 相关阅读:
    CMLLVDS
    js获取url中的参数(解决中文乱码)
    解决跳转出现 No input file specified.
    ThinkPHP关联模型详解
    Thinkphp表单自动验证
    手机号登录注册
    JS实现每隔一段时间数量增加或减少
    文章或者观点说说等点赞功能实现(thinkphp)
    thinkphp整合Ueditor编辑器
    点击切换状态 类似开关按钮
  • 原文地址:https://www.cnblogs.com/HZL2017/p/13252878.html
Copyright © 2011-2022 走看看