力扣网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语言有区别。好像写起来也没想象中困难,加油!

相关推荐
独自破碎E5 分钟前
【队列】按之字形顺序打印二叉树
leetcode
mjhcsp7 分钟前
C++ KMP 算法:原理、实现与应用全解析
java·c++·算法·kmp
lizhongxuan8 分钟前
Manus: 上下文工程的最佳实践
算法·架构
AlenTech12 分钟前
206. 反转链表 - 力扣(LeetCode)
数据结构·leetcode·链表
踩坑记录12 分钟前
leetcode hot100 438. 找到字符串中所有字母异位词 滑动窗口 medium
leetcode·职场和发展
CS创新实验室20 分钟前
《计算机网络》深入学:海明距离与海明码
计算机网络·算法·海明距离·海明编码
WW_千谷山4_sch22 分钟前
MYOJ_10599:CSP初赛题单10:计算机网络
c++·计算机网络·算法
YuTaoShao43 分钟前
【LeetCode 每日一题】1458. 两个子序列的最大点积——(解法三)状态压缩
算法·leetcode·职场和发展
位东风1 小时前
希尔排序(Shell Sort)详解
算法·排序算法