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

发布于:2025-06-19 ⋅ 阅读:(12) ⋅ 点赞:(0)

一. 简介

本文记录力扣网上的逻辑编程题,涉及数组方面的,这里记录一下 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语言有区别。好像写起来也没想象中困难,加油!


网站公告

今日签到

点亮在社区的每一天
去签到