leetcode-018-四数之和

news/2024/9/23 6:39:07/

题目及测试

package pid018;
/* 18. 四数之和
给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。
请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] 
(若两个四元组元素一一对应,则认为两个四元组重复):0 <= a, b, c, d < n
a、b、c 和 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]]提示:1 <= nums.length <= 200
-109 <= nums[i] <= 109
-109 <= target <= 109*/import java.util.List;public class main {public static void main(String[] args) {int[][] testTable = {{1,0,-1,0,-2,2},{2,2,2,2,2}};int[] testTable2={0,8};for (int i=0;i<testTable.length;i++) {test(testTable[i],testTable2[i]);}}private static void test(int[] ito,int ito2) {List<List<Integer>> rtn;Solution solution=new Solution();long begin = System.currentTimeMillis();for (int i = 0; i < ito.length; i++) {System.out.print(ito[i]+" ");		    }System.out.println();//开始时打印数组System.out.println("ito2="+ito2);rtn = solution.fourSum(ito,ito2);//执行程序long end = System.currentTimeMillis();	System.out.println( "rtn=" );for(int i=0;i<rtn.size();i++){for(int j=0;j<rtn.get(i).size();j++){System.out.print( rtn.get(i).get(j)+"  ");}		System.out.println();}System.out.println();System.out.println("耗时:" + (end - begin) + "ms");System.out.println("-------------------");}}

没做出来

解法1(别人的)

排序 + 双指针
思路与算法

最朴素的方法是使用四重循环枚举所有的四元组,然后使用哈希表进行去重操作,得到不包含重复四元组的最终答案。假设数组的长度是 nn,则该方法中,枚举的时间复杂度为 O(n^4),去重操作的时间复杂度和空间复杂度也很高,因此需要换一种思路。

为了避免枚举到重复四元组,则需要保证每一重循环枚举到的元素不小于其上一重循环枚举到的元素,且在同一重循环中不能多次枚举到相同的元素。

为了实现上述要求,可以对数组进行排序,并且在循环过程中遵循以下两点:

每一种循环枚举到的下标必须大于上一重循环枚举到的下标;

同一重循环中,如果当前元素与上一个元素相同,则跳过当前元素。

使用上述方法,可以避免枚举到重复四元组,但是由于仍使用四重循环,时间复杂度仍是 O(n^4)。注意到数组已经被排序,因此可以使用双指针的方法去掉一重循环。

使用两重循环分别枚举前两个数,然后在两重循环枚举到的数之后使用双指针枚举剩下的两个数。假设两重循环枚举到的前两个数分别位于下标 i 和 j,其中 i<j。初始时,左右指针分别指向下标 j+1 和下标 n−1。每次计算四个数的和,并进行如下操作:

如果和等于 target,则将枚举到的四个数加到答案中,然后将左指针右移直到遇到不同的数,将右指针左移直到遇到不同的数;

如果和小于 target,则将左指针右移一位;

如果和大于 target,则将右指针左移一位。

使用双指针枚举剩下的两个数的时间复杂度是 O(n),因此总时间复杂度是 O(n^3),低于 O(n^4)。

具体实现时,还可以进行一些剪枝操作:

在确定第一个数之后,如果 nums[i]+nums[i+1]+nums[i+2]+nums[i+3]>target,说明此时剩下的三个数无论取什么值,四数之和一定大于 target,因此退出第一重循环;
在确定第一个数之后,如果 nums[i]+nums[n−3]+nums[n−2]+nums[n−1]<target,说明此时剩下的三个数无论取什么值,四数之和一定小于 target,因此第一重循环直接进入下一轮,枚举 \textit{nums}[i+1]nums[i+1];
在确定前两个数之后,如果 nums[i]+nums[j]+nums[j+1]+nums[j+2]>target,说明此时剩下的两个数无论取什么值,四数之和一定大于 target,因此退出第二重循环;
在确定前两个数之后,如果 nums[i]+nums[j]+nums[n−2]+nums[n−1]<target,说明此时剩下的两个数无论取什么值,四数之和一定小于 target,因此第二重循环直接进入下一轮,枚举 nums[j+1]。
 

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


http://www.ppmy.cn/news/56292.html

相关文章

【MySQL】数据的家——MySQL的数据目录

1. 数据库和文件系统的关系 InnoDB、MyISAM 等 存储引擎把表存储在磁盘上&#xff0c;操作系统使用文件系统来管理磁盘。所以&#xff0c;InnoDB、MyISAM 等 存储引擎都是把数据存储在文件系统上。 当读取数据时&#xff0c;存储引擎会从文件系统中把数据读出来返回给我们&am…

微服务开发LCM(Life Cycle Model)

02_Project Execution_项目执行1_Order Clarification_订单澄清099-Project approval--099项目批准110-Context diagram--110上下文图121-Process model--121过程模型130-Application description--130应用程序说明131-Architecture diagram--131架构图137-Technical interface…

华为OD机试 - 端口合并(Python)

题目描述 有M个端口组(1<=M<=10), 每个端口组是长度为N的整数数组(1<=N<=100), 如果端口组间存在2个及以上不同端口相同,则认为这2个端口组互相关联,可以合并。 输入描述 第一行输入端口组个数M,再输入M行,每行逗号分割,代表端口组。 备注:端口组内数字…

Python中的异常处理机制可以帮助程序员在程序运行过程中遇到错误时进行处理

Python中的异常处理机制可以帮助程序员在程序运行过程中遇到错误时进行处理&#xff0c;防止程序崩溃或出现不可预测的错误。 Python中的异常处理使用try-except语句。try语句块包含可能会出现异常的代码&#xff0c;而except语句块则定义了出现异常时应该执行的操作。下面是一…

nginx负载均衡+RabbitMq集群及镜像队列(2)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、nginx是什么&#xff1f;二、搭建步骤1.软件和环境2.安装nginx3.负载均衡配置nginx.conf4.应用程序配置 总结 前言 提示&#xff1a;这里可以添加本文要记…

【原创】生成文件MD5图像,类似于GitHub的像素风格头像

前言 我想通过文件的md5生成关于这个md5的图像&#xff0c;类似于GitHub的随机像素头像&#xff0c;用处是让这个md5更加直观&#xff0c;也能用于生成各种用户头像&#xff0c;跟GitHub一样。 网上搜了一下&#xff0c;没有现成的方法&#xff0c;只能有一篇类似的文章可以借…

GeoTools实战指南: 轻松实现GeoTIFF与Shapefile的可视化和叠加

GeoTools实战指南: 轻松实现GeoTIFF与Shapefile的可视化和叠加 介绍 本教程将指导您如何使用GeoTools库渲染栅格数据(GeoTIFF文件)和矢量数据(Shapefile文件),并将它们叠加在地图窗口中显示。下面是基于提供的代码示例的教程。 准备环境 首先,您需要将GeoTools库添加…

matlab 实现常用的混沌映射(Tent, Sine, Sinusoidal, Piecewise, Logistic, Cubic, Chebyshev)

大部分混沌映射的系数是有限制的, 针对每个模型最优的混沌系数是不一样的, 因此混沌系数要根据自己的模型来定. 下面的系数都是根据我自己的模型而设定的. 混沌映射 1 Tent 映射2 Sine 映射3 Sinusoidal 映射4 Piecewise 映射5 Logistic 映射6 Cubic 映射7 Chebyshev 映射 1 Te…