当前位置: 首页 > news >正文

LeetCode 15.三数之和

15.三数之和

给你一个整数数组 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
-10^5 <= nums[i] <= 10^5

题解

做这道题目之前可以看看这道题目 167.两数之和 II

在两数之和中,我们通过使用左右两个指针在 O(n) 的时间内实现了寻找两个和为target的数

即使用 l 和 r 左右两个指针,假如nums[ l ] + nums[ r ] > target 则 r-- 若小于则 l++ 否则就找到了

  • 类似的,对于三个数和为target,我们可以将其拆分为两个数和一个数的和

  • 那么我们可以先枚举一个数作为三元组中最小的数,对于每一个数 nums[ i ],我们需要找到和为 target - nums[ i ] 的两个数,那么问题就回到了167.两数之和 II

需要注意的是,我们需要先将nums数组进行排序,否则无法在O(n)的时间内实现找到两个数

以及题目要求不能有重复的三元组,那么我们需要在枚举时略过相同的nums[ i ],同时,在找另外两个数时,也要略过相同的nums[ l ],nums[ r ]


优化

可以发现,由于我们枚举第一个数nums[ i ]是递增的,那么假如某一个nums[ i ]与剩下的最小的两个数之和大于0,那么之后的nums[ i ]肯定也是大于0的,所以就可以直接break掉循环

类似的,假如某一个nums[ i ]与剩下的最大的两个数之和仍旧小于0,那么就可以直接continue


代码如下↓

/**
 * 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) {
    int cmp(const void* a, const void* b)
    {
        return *(int*)a - *(int*)b;
    }
    qsort(nums,numsSize,sizeof(int),cmp);
    int** arr = (int**)malloc(sizeof(int*)*99999);
    int n=0;
    for(int i=0;i<numsSize-2;i++)
    {
        if(i>0 && nums[i]==nums[i-1])
        {
            continue;
        }
        if(nums[i]+nums[i+1]+nums[i+2]>0)
        {
            break;
        }
        if(nums[i]+nums[numsSize-1]+nums[numsSize-2]<0)
        {
            continue;
        }
        int k=-nums[i];
        int l=i+1;
        int r=numsSize-1;
        while(l<r)
        {
            if(nums[l]+nums[r]==k)
            {
                int* arrr = (int*)malloc(sizeof(int)*3);
                arrr[0]=nums[i];
                arrr[1]=nums[l];
                arrr[2]=nums[r];
                arr[n++]=arrr;
                l++;
                r--;
            }
            else if(nums[l]+nums[r]>k)
            {
                r--;
            }
            else
            {
                l++;
            }
            while(l>i+1 && l<r && nums[l]==nums[l-1])
            {
                l++;
            }
        }
    }
    *returnSize=n;
    *returnColumnSizes=(int*)malloc(sizeof(int)*n);
    for(int i=0;i<n;i++)
    {
        (*returnColumnSizes)[i]=3;
    }
    return arr;
}

相关文章:

  • Imagination DXTP GPU IP:加速游戏AI应用,全天候畅玩无阻
  • Linux | Ubuntu 与 Windows 双系统安装 / 高频故障 / UEFI 安全引导禁用
  • 香橙派/树莓派 利用Wiring库 使用GPIO模拟PWM
  • WebSocketHandler 是 Spring Framework 中用于处理 WebSocket 通信的接口
  • 普中单片机-51TFT-LCD显示屏(1.8寸 STM32)
  • tableau之雷达图和凹凸图
  • 图数据库 | 23、如何评测图系统 — 评测内容?
  • 正则表达式用法及其示例:匹配、查找、替换文本中的模式,及QT下如何使用正则表达式。
  • Linux网络基础(协议 TCP/IP 网络传输基本流程 IP VS Mac Socket编程UDP)
  • RAG 阿里云
  • go 语言中的线程池
  • 四、Redis主从复制与读写分离
  • nvidia驱动更新,centos下安装openwebui+ollama(非docker)
  • 面试基础---ConcurrentHashMap vs HashMap
  • 网络运维学习笔记(DeepSeek优化版)003网工初级(HCIA-Datacom与CCNA-EI)命令入门
  • 【paddle】详解 padde.autograd.backward
  • 人工智能发展全景与DeepSeek-R1
  • 设计模式Python版 备忘录模式
  • uni-app集成sqlite
  • Vue组件间通信的方式
  • 公司企业网站怎么建设/怎样自己开发一款软件
  • 网页美工设计视频/网站打开速度优化
  • dedecms网站安装/媒体发稿平台
  • 成都科技公司排名/seo研究协会网
  • 网页网站开发手机游戏/百度提交收录
  • 怎么注册网站啊/神马推广登录