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

LeetCode算法日记 - Day 4: 三数之和、四数之和

1. 三数之和

15. 三数之和 - 力扣(LeetCode)

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != 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 。

1.1 题目解析

解决该问题可以用排序+对撞指针解决,解决问题的可以分两种:暴力枚举 和 优化之后的算法。

a)暴力枚举可以通过三层 for 循环+ set 集合去重的方法解决,不过大概率面临 “迷失” 的风险。

b)我们可以通过先排序来使整个数组变为有序数组,然后通过固定一个数 a 再定义额外俩指针,使这俩指针的数 和 a 的绝对值相同。因为只有 a 为负数的时候才面临三数相加等于 0,所以当 a 大于 0 时就可以返回数组了。

这个解法的核心就是不用 set 去重,要面临三重去重的问题,下面我来详细解答。

1.2 解法

i)排序

ii)固定数 a

iii)在这个数后面的区间内,使用 [双指针算法] 快速找到两个数之和等于 -a 。

iiii)当找到一个结果之后,left 和 right 配合 while 循环跳过重复的元素。

iiiii)使用完一次双指针之后,对固定的 a 也要使用 while 循环跳过重复的元素。

1.3 代码实现

class Solution {public List<List<Integer>> threeSum(int[] nums) {Arrays.sort(nums);int n = nums.length;List<List<Integer>> ret = new ArrayList<>();for(int i=0;i<n-2;){if(nums[i]>0){break;}int left = i+1, right = n-1, target = -nums[i]; while(left<right){int sum = nums[right] + nums[left];if(sum < target){left++;}else if(sum>target){right--;}else{ret.add(new ArrayList<Integer>(Arrays.asList(nums[i],nums[left],nums[right])));left++;right--;while(nums[left] == nums[left-1] && left<right){left++;}while(nums[right] == nums[right+1]&& right>left){right--;}}}i++;while(i<n-2 &&nums[i] == nums[i-1]){i++;}}return ret;}
}

2. 四数之和

18. 四数之和 - 力扣(LeetCode)

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

  • 0 <= a, b, c, d < n
  • abc 和 d 互不相同
  • nums[a] + nums[b] + nums[c] + nums[d] == target

你可以按 任意顺序 返回答案 。

示例 1:

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

示例 2:

输入:nums = [2,2,2,2,2], target = 8
输出:[[2,2,2,2]]

2.1 题目解析

四数之和与三数之和的解决办法如出一辙,都可以通过先排序,再双指针来解决问题。固定一个数 a ,在 a 之后的区间内再固定一个数 b,在 b 之后的区间内使用双指针即可解决。不过需要注意的是,要对数 a 也就是最外层的数也要进行去重。

2.2 解法

i)排序

ii)固定数 a

iii)固定数b。

iii)在数 b 后面的区间内,使用 [双指针算法] 快速找到两个数之和等于 -a-b 。

iiii)当找到一个结果之后,left 和 right 配合 while 循环跳过重复的元素。

iiiii)使用完一次双指针之后,对固定的 b 也要使用 while 循环跳过重复的元素。

iiiiii)最后对数 a 进行去重,使用 while 循环跳过重复的元素。

2.3 代码实现

class Solution {public List<List<Integer>> fourSum(int[] nums, int target) {Arrays.sort(nums);int n = nums.length;List<List<Integer>> ret = new ArrayList<>();for(int i = 0; i<n-3;){for(int j =i+1;j<n-2;){long dest = ((long)target-(long)nums[i]-(long)nums[j]);int left = j+1, right = n-1;while(left<right){long sum = (long)nums[left] + (long)nums[right];if(sum<dest){left++;}else if(sum > dest){right--;}else{ret.add(new ArrayList<Integer>(Arrays.asList(nums[i],nums[j],nums[left],nums[right])));left++;right--;while(left<right&&nums[left]==nums[left-1]){left++;}while(left<right&&nums[right] == nums[right+1]){right--;}}}j++;while(j<n-2&&nums[j]==nums[j-1]){j++;}}i++;while(i<n-3&&nums[i] == nums[i-1]){i++;}}return ret;}
}

http://www.dtcms.com/a/319330.html

相关文章:

  • LeetCode每日一题,2025-8-7
  • .NET PDF处理组件IronPDF:如何通过 AI 简化开发人员处理 PDF的方式
  • 第五节 Pyside6可视化界面
  • PCIe Base Specification解析(八)
  • 如何高效利用服装工厂跟单软件提升效率?
  • 【论坛系统自动化功能测试报告】
  • ⚖️ AI的“成本陷阱”:当技术狂欢遇上商业现实
  • XXL-JOB定时任务
  • 如何将服务器中的Docker镜像批量导出?
  • 论文Review BALM2 | 港大MARS出品!机器人顶刊TRO | 经典激光BA续作!BALM升级版 | TODO待精读
  • 远程制作《最后生还者》中的Xsens动作捕捉技术
  • 使用SETNX实现分布式锁
  • python的web接口数据库链接封装
  • Linux---第三天---权限
  • 并发测试:你的应用扛得住“早高峰”吗?
  • python中的集合
  • uniapp vue3中使用pinia 和 pinia持久化(没有使用ts)
  • PPT漏斗图,让数据更美观!
  • 线程池创建线程
  • Mac 电脑安装 ADB 环境完整指南
  • 流程图使用规范
  • Git Status 命令深度指南:洞悉仓库状态的核心艺术
  • 专题二_滑动窗口_长度最小的子数组
  • 进程Linux
  • 打靶日记-PHPinclude-labs(一)
  • 攻防世界WEB(新手模式)2-2-upload1
  • MySQL中的DDL(一)
  • 深入理解动态规划算法
  • 数字孪生系统让汽车工厂虚实联动预测维护少停机
  • LabVIEW注册表操作