C语言刷力扣——三数之和

216 阅读3分钟

「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战」。

前言

一个程序,有一种书本上的描述:解决一个问题除了要有一个数据结构来表示和组织信息外,还需要一系列步骤来完成问题的解决方案。

当然了,第一个逗号前面的那当然就是数据结构了,那后面的一系列步骤其实说的就是算法。

也可以称为:操作数据结构的方法;或者称为:解决问题的方案

我学算法的目的

因为我想在找工作的时候更有竞争力,更有话语权,所以我来学算法!

一、题目描述

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

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

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/3s… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
实例:

输入: nums = [-1,0,1,2,-1,-4]
输出: [[-1,-1,2],[-1,0,1]]
输入: nums = []
输出: []


提示:

  • 0 <= nums.length <= 3000

  • -105 <= nums[i] <= 105

  • 0 <= nums.length <= 3000

  • -105 <= nums[i] <= 105

二、题目解析

  • 空数组/元素数目小于3返回空
  • 排序原数组
  • 遍历排序后的数组
  • 使用二分法找到三数之和 细节处理:
  • 当前数组大于0,表示后续没有三数之和为0,结束遍历
  • 当前元素与上一次相等,跳过此次计算,去重 什么是二分法: 二分查找法是一种算法

他经常用在:

给定一个升序的数组/列表和一个目标值,尽可能快的查找其中的目标值

若存在,返回目标值得索引

若不存在,返回-1

这样的场景

因为是升序的,所以我们可以以数组中间的元素为中线,将数组分为左右两个数组

三、代码讲解

/**
 * 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().
 */
 /*
   - 空数组/元素数目小于3返回空
   - 排序原数组
   - 遍历排序后的数组
   - 使用二分法找到三数之和
   细节处理:
   - 当前数组大于0,表示后续没有三数之和为0,结束遍历
   - 当前元素与上一次相等,跳过此次计算,去重
 */
 // qsort的比较函数 
int cmp(const void* a, const void* b) {
    return *(int*)a - *(int*)b;
}
int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
    // 先记录返回的行数为0 
    *returnSize = 0;
    // 输入为空、或元素个数小于3则返回NULL 
    if (nums == NULL || numsSize < 3) {
        return NULL;
    }
    // 将nums排序为升序排列 
    qsort(nums, numsSize, sizeof(int), cmp);
    // 分配返回数组、返回数组的列数
    int** ret = (int**)malloc(numsSize * numsSize * sizeof(int*));
    *returnColumnSizes = (int*)malloc(numsSize * numsSize *sizeof(int));
    // 排序后的数组从头到尾进行遍历 
    for (int i = 0; i < numsSize; i++) {
        // 当前数组大于0,表示后续没有三数之和为0,结束遍历 
        if (nums[i] > 0) {
            break;
        }
        // 当前元素与上一次相等,跳过此次计算,去重
        if (i > 0 && nums[i] == nums[i - 1]) {
            continue;
        }
        // 定义左右指针
        int left = i + 1, right = numsSize - 1;
        // 开始查找三数之和为0 
        while (left < right) {
            int sum = nums[i] + nums[left] + nums[right];
            if (sum == 0) {
                ret[*returnSize] = (int*)malloc(sizeof(int) * 3);
                ret[*returnSize][0] = nums[i];
                ret[*returnSize][1] = nums[left];
                ret[*returnSize][2] = nums[right];
                // 返回数组当前行的列数为3 
                (*returnColumnSizes)[*returnSize] = 3;
                // 返回数组的行数自加1 
                (*returnSize)++;
                // 对左右指针进行去重 
                while (left < right && nums[left]  == nums[++left]);
                while (left < right && nums[right] == nums[--right]);
            } else if (sum < 0) {
                left++;
            } else {
                right--;
            }
        }
    }
    return ret;
}

结语

算法的出现也是因为有了问题,之前也说过算法是什么了,就是一个问题的解决方案,所以我们的算法是为了解决问题才出现的。

当然,主要还是为了money,刷算法,冲大厂,加油。

成功不难,就在于你是否会比别人更会吃苦。