力扣网C语言编程题:三数之和

一. 简介

本文记录力扣网上的逻辑编程题,涉及数组方面的,这里记录一下 C语言实现和Python实现。

二. 力扣网C语言编程题:三数之和

题目:三数之和

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。

示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。

示例 2:
输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。

示例 3:
输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。

提示:
3 <= nums.length <= 3000
-105 <= nums[i] <= 105

解题思路:

根据题目要求,数组中找到三个元素之和为0,且不重复的三元组。这里解决不重复的方法就是排序,排序后查重就可以保证不重复。

固定一个元素,使用双指针,从数组的头部与尾部进行同时进行查找,查找第二元素和第三个元素。

具体方法:

  1. 从小到大进行排序;

  2. 遍历数组,元素去重;

  3. 开始从数组首部和尾部开始同时进行,统计三个元素为 0的元素,如果和小于0,则移动左指针。如果大于0则移动右指针。如果等于0则保存数据,然后对左边指针的元素进行查重,右边指针的元素进行查重;

C语言实现如下:

复制代码
#include <stdio.h>

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

/**
 * 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** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes) {
    if((nums == NULL) || (numsSize <= 0) || (returnSize == NULL) || (returnColumnSizes == NULL)) {
        return NULL;
    }
    *returnSize = 0;

    int left = 0;
    int right = 0;
    int i = 0; 
    //分配返回数组的缓存
    int** ret_data = (int**)malloc(10*numsSize * sizeof(int*));
    *returnColumnSizes = (int*)malloc(10*numsSize * sizeof(int));

    //从小到大排序
    qsort(nums, numsSize, sizeof(int), compare_data);
    
    //遍历数组(从头部和尾部同时)
    for(i = 0; i < (numsSize-2); i++) {
        //当前元素大于0,那么更不可能存在sum值等于0的数了,结束遍历
        if(nums[i] > 0) {
            break;
        }
        //元素去重(当前元素与上一次元素相等,跳过此次计算)
        if(i > 0 && nums[i] == nums[i-1]) {
            continue;
        }

        left = i+1;
        right = numsSize-1;

        //开始查找三数之和
        while(left < right) {
            //判断和的值
            int sum = nums[i] + nums[left] + nums[right];
            if(sum == 0) { 
                //分配内存,保存结果
                ret_data[*returnSize] = (int*)malloc(3 * sizeof(int));
                ret_data[*returnSize][0] = nums[i];
                ret_data[*returnSize][1] = nums[left];
                ret_data[*returnSize][2] = nums[right];
                (*returnColumnSizes)[*returnSize] = 3; //返回数组当前行的列数为3
                (*returnSize)++; //三元组的个数
                //左边指针的元素进行查重
                while((left < right) && (nums[left] == nums[++left]));
                //右边指针的元素进行查重
                while((left < right) && (nums[right] == nums[--right]));
            }
            else if(sum < 0) { //左指针向右移找大值
                left++;
            }
            else { //右指针向左移找小值
                right--;
            }  
        }
    }
    return ret_data;
}

Python实现如下:

复制代码
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        ret = []
        n = len(nums)

        #从小到大进行排序,方便去重
        nums.sort()

        #遍历数组元素(从数组的首部和尾部同时进行)
        #0 ~ n-3
        for i in range(0, n-2):
            #如果第一个元素大于0,则不必查找了(后面元素更大)
            if(nums[i] > 0):
                break
            #元素查重(如果当前元素与上一次元素相等,则跳过这次计算)
            if(i > 0 and nums[i] == nums[i-1]):
                continue
            left = i + 1
            right = n - 1
            #查找和为0的三元组
            while(left < right):
                sum = nums[i] + nums[left] + nums[right] 
                #和 == 0
                if(sum == 0):
                    ret.append([nums[i], nums[left], nums[right]])
                    #左右指针的元素查重
                    while(left < right and nums[left] == nums[left+1]):
                        left += 1
                    while(left < right and nums[right] == nums[right-1]):
                        right -= 1
                    left += 1
                    right -= 1
                #和 < 0,则左指针向右移(说明和小了,需要和增大)
                elif(sum < 0): 
                    left += 1
                #和 > 0,则右指针向左移(说明和大了,需要和减小)
                else:
                    right -= 1
               
        return ret

第一次写 Python,是与 C语言有区别。好像写起来也没想象中困难,加油!

相关推荐
晨非辰4 分钟前
#C语言——刷题攻略:牛客编程入门训练(一):简单输出、基本类型
c语言·学习·学习方法·visual studio
努力写代码的熊大23 分钟前
八大排序算法
java·算法·排序算法
xiaobaibai1531 小时前
智慧交通中目标检测 mAP↑28%:陌讯多模态融合算法实战解析
人工智能·算法·目标检测·计算机视觉·目标跟踪·视觉检测
战争热诚1 小时前
基于transformer的目标检测——匈牙利匹配算法
算法·目标检测·transformer
计算机科研圈1 小时前
ICCV 2025 | EPD-Solver:西湖大学发布并行加速扩散采样算法
人工智能·算法·语言模型·自然语言处理·数据挖掘·iccv
Yzxs0092 小时前
【8月优质EI会议合集|高录用|EI检索稳定】计算机、光学、通信技术、电子、建模、数学、通信工程...
大数据·人工智能·算法·计算机视觉·信息与通信
好好先森&2 小时前
C语言:模块化编程
c语言·c++·windows
重生之我是Java开发战士2 小时前
【C语言】结构体详解
c语言·开发语言
佳航张3 小时前
选择排序原理与C语言实现详解
算法
hans汉斯3 小时前
【建模与仿真】二阶邻居节点信息驱动的节点重要性排序算法
人工智能·python·算法·分类·数据挖掘·排序算法·xca