2Sum/3Sum/3SumClosest/4Sum系列问题

本文介绍了解决LeetCode上数组求和问题的方法,包括twoSum、threeSum、threeSumClosest及fourSum等题目的高效算法实现,通过双指针技巧减少复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

leetcode(http://leetcode.com/onlinejudge)上有好几道关于数组中几个数据和为target的题目。恰好正在看剑指offer中“和为s的两个数组这章”,据此思想,leetcode上的三道题目都被我解决了。总结一下。

1.twoSum:输入一个递增数组和一个数字s,在数组中查找两个数使得它们的和正好是s。

既然题目中已经提到了“递增数组”,那么肯定不会暴力了。因此肯定有<O(n*n)的办法了。

算法:最初我们找到数组的第一个数字和最后一个数字。当两个数字的和大于输入的数字时,把较大的数字往前移动;当两个数字的和小于数字时,把较小的数字往后移动;当相等时,打完收工。这样扫描的顺序是从数组的两端向数组的中间扫描。

链接:http://zhedahht.blog.163.com/blog/static/2541117420072143251809/

2.threeSum: Given an array S of n integers, are there elements abc in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note:

  • Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ? b ? c)
  • The solution set must not contain duplicate triplets.
有了twoSum的启发,threeSum所有做的事,只需加上排序,和一层循环。

首先是求解:因为要求3个数,如果我们固定其中1个数,再用求“和为某值的2个数的组合”的解法,就能把剩下的2个数求出来。因

此,先对数组进行非递减排序,这样整个数组的数就由小到大排列。i 的取值由 0 至 n-1,对每一个i,我们求当num[i]是解当中的其

中一个数时,其他的2个数。设有指针p指向数组头(实际只要p从i+1开始),q指向数组尾,sum = num[i] + num[p]+ num[q],因为num[i]

是一定在解中的,所以如果sum < 0,因为num[q]已经不能增大,所以说明num[p]太小了,这时p需要向后移动,找一个更大的数。

同理,sum > 0,说明num[q]太大了,需要q向前移动。当sum == 0时,说明找到了一个解。但找到了一个解,并不说明解中有num[i]的

所有解都找到了,因此p或q还需要继续移动寻找其他的解,直到p == q为止。

 

上面是求解的过程,那么去重怎么做?去重就在于和之前的解进行比较,但我们不需要比较所有的解,这里有一个技巧。

1. 如果num[i] = num[i - 1],说明刚才i-1时求的解在这次肯定也会求出一样的,所以直接跳过不求;

2. 其实指针p不需要从数组头开始,因为如果num[i]所在的解中如果有i之前的数,设其位置为j,那么我们求num[j]时,肯定把num[i]

    也找出来放到和num[j]一起的解里了,所以指针p其实应该从i+1开始,即初始时p = i + 1, q = num.size() - 1;

3. 当sum == 0,我们保存了当前解以后,需要num[i]在解中的其他的2个数组合,这个时候,肯定是p往后或者q往前,如果++p,发

    现其实num[p] == num[p-1],说明这个解肯定和刚才重复了,再继续++p。同理,如果--q后发现num[q] == num[q+1],继续--q。

    这个去重操作主要针对这种有多个同值的数组,如:-3, 1,1,1, 2,2,3,4。


[java]  view plain copy
  1. import java.util.ArrayList;  
  2. import java.util.Arrays;  
  3.   
  4. public class ThreeSumSolution2 {  
  5.     private ArrayList<ArrayList<Integer>> list;  
  6.       
  7.     public ArrayList<ArrayList<Integer>> threeSum(int[] num) {  
  8.         list = new ArrayList<ArrayList<Integer>>();  
  9.         Arrays.sort(num);  
  10.           
  11.         int i = 0;  
  12.         for (i = 0; i <= num.length - 3; i++) {  
  13.             if (i != 0 && num[i] == num[i - 1]) {  
  14.                 continue;  
  15.             }  
  16.             judgeAndPut(num, i, i + 1, num.length - 1);  
  17.         }  
  18.          
  19.         return list;  
  20.     }  
  21.   
  22.     private void judgeAndPut(int[] num, int i, int p, int q) {  
  23.         while (p < q) {  
  24.             if (num[p] + num[q] < -num[i]) {  
  25.                 p++;  
  26.             } else if (num[p] + num[q] > -num[i]){  
  27.                 q--;  
  28.             } else if (num[p] + num[q] == -num[i]) {  
  29.                 ArrayList<Integer> tmpList = new ArrayList<Integer>();  
  30.                 tmpList.add(num[i]);  
  31.                 tmpList.add(num[p]);  
  32.                 tmpList.add(num[q]);  
  33.                 list.add(tmpList);  
  34.                 p++;  
  35.                 q--;  
  36.                 while (p < q && num[p] == num[p - 1]) {  
  37.                     p++;  
  38.                 }  
  39.                 while (p < q && num[q] == num[q + 1]) {  
  40.                     q--;  
  41.                 }  
  42.             }  
  43.         }  
  44.     }  
  45.       
  46.     public static void main(String[] args) {  
  47.         int num[] = {-1,0,1,2,-1,-4};  
  48.         System.out.println(new ThreeSumSolution2().threeSum(num));  
  49.     }  
  50. }  
3. threeSumClosest:  Given an array  S  of  n  integers, find three integers in  S  such tha t the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
思路和threeSum几乎一样,只是查找条件有所变化而已。代码更简洁了。
[java]  view plain copy
  1. import java.util.Arrays;  
  2.   
  3. public class ThreeSumClosest {  
  4.     private int closest;  
  5.     private boolean needInit;  
  6.       
  7.     public int threeSumClosest(int[] num, int target) {  
  8.         closest = 0;  
  9.         needInit = true;  
  10.         Arrays.sort(num);  
  11.           
  12.         int i = 0;  
  13.         for (i = 0; i <= num.length - 3; i++) {  
  14.             if (i != 0 && num[i] == num[i - 1]) {  
  15.                 continue;  
  16.             }  
  17.             judgeAndPut(num, i, i + 1, num.length - 1, target);  
  18.         }  
  19.         return closest;  
  20.     }  
  21.   
  22.     private void judgeAndPut(int[] num, int i, int p, int q, int target) {  
  23.           
  24.         while (p < q) {  
  25.             int sum = num[i] + num[p] + num[q];  
  26.             if (needInit || Math.abs(sum - target) < Math.abs(closest - target)) {  
  27.                 closest = sum;  
  28.             }  
  29.             needInit = false;  
  30.               
  31.             if (sum <= target) {  
  32.                 p++;  
  33.                 while (p < q && num[p] == num[p - 1]) {  
  34.                     p++;  
  35.                 }  
  36.             } else if (sum > target){  
  37.                 q--;  
  38.                 while (p < q && num[q] == num[q + 1]) {  
  39.                     q--;  
  40.                 }  
  41.             }  
  42.         }  
  43.           
  44.     }  
  45.       
  46.     public static void main(String[] args) {  
  47.         int num[] = {0,1,2};  
  48.         System.out.println(new ThreeSumClosest().threeSumClosest(num, 3));  
  49.     }  
  50. }  
4. fourSum: 

Given an array S of n integers, are there elements abc, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

Note:

  • Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ? b ? c ? d)
  • The solution set must not contain duplicate quadruplets.
再多两层循环,此时已经是n立方的时间效率了,尝试了一下,居然也AC了。不知道还有没有更高效的算法。
[java]  view plain copy
  1. import java.util.ArrayList;  
  2. import java.util.Arrays;  
  3.   
  4. public class FourSum {  
  5.     private ArrayList<ArrayList<Integer>> list;  
  6.       
  7.     public ArrayList<ArrayList<Integer>> fourSum(int[] num, int target) {  
  8.         list = new ArrayList<ArrayList<Integer>>();  
  9.         Arrays.sort(num);  
  10.           
  11.         int i = 0;  
  12.         int j = 0;  
  13.         for (i = 0; i <= num.length - 4; i++) {  
  14.             if (i != 0 && num[i] == num[i - 1]) {  
  15.                 continue;  
  16.             }  
  17.               
  18.             for (j = i + 1; j <= num.length - 3; j++) {  
  19.                 if (j != i + 1 && num[j] == num[j - 1]) {  
  20.                     continue;  
  21.                 }  
  22.                 judgeAndPut(num, i, j, j + 1, num.length - 1, target);  
  23.             }  
  24.               
  25.         }  
  26.          
  27.         return list;              
  28.     }  
  29.   
  30.     private void judgeAndPut(int[] num, int i, int j, int p, int q, int target) {  
  31.         while (p < q) {  
  32.             int sum = num[i] + num[j] + num[p] + num[q];  
  33.             if (sum < target) {  
  34.                 p++;  
  35.             } else if (sum > target){  
  36.                 q--;  
  37.             } else if (sum == target) {  
  38.                 ArrayList<Integer> tmpList = new ArrayList<Integer>();  
  39.                 tmpList.add(num[i]);  
  40.                 tmpList.add(num[j]);  
  41.                 tmpList.add(num[p]);  
  42.                 tmpList.add(num[q]);  
  43.                 list.add(tmpList);  
  44.                 p++;  
  45.                 q--;  
  46.                 while (p < q && num[p] == num[p - 1]) {  
  47.                     p++;  
  48.                 }  
  49.                 while (p < q && num[q] == num[q + 1]) {  
  50.                     q--;  
  51.                 }  
  52.             }  
  53.         }  
  54.           
  55.     }  
  56.       
  57.     public static void main(String[] args) {  
  58.         int num[] = {-1,0,1,0,-2,2};  
  59.         System.out.println(new FourSum().fourSum(num, 0));  
  60.   
  61.     }  
  62.   
  63. }  
电动汽车数据集:2025年3K+记录 真实电动汽车数据:特斯拉、宝马、日产车型,含2025年电池规格销售数据 关于数据集 电动汽车数据集 这个合成数据集包含许多品牌年份的电动汽车插电式车型的记录,捕捉技术规格、性能、定价、制造来源、销售安全相关属性。每一行代表由vehicle_ID标识的唯一车辆列表。 关键特性 覆盖范围:全球制造商车型组合,包括纯电动汽车插电式混合动力汽车。 范围:电池化学成分、容量、续航里程、充电标准速度、价格、产地、自主水平、排放、安全等级、销售保修。 时间跨度:模型跨度多年(包括传统即将推出的)。 数据质量说明: 某些行可能缺少某些字段(空白)。 几个分类字段包含不同的、特定于供应商的值(例如,Charging_Type、Battery_Type)。 各列中的单位混合在一起;注意kWh、km、hr、USD、g/km额定值。 列 列类型描述示例 Vehicle_ID整数每个车辆记录的唯一标识符。1 制造商分类汽车品牌或OEM。特斯拉 型号类别特定型号名称/变体。型号Y 与记录关联的年份整数模型。2024 电池_类型分类使用的电池化学/技术。磷酸铁锂 Battery_Capacity_kWh浮充电池标称容量,单位为千瓦时。75.0 Range_km整数表示充满电后的行驶里程(公里)。505 充电类型主要充电接口或功能。CCS、NACS、CHAdeMO、DCFC、V2G、V2H、V2L Charge_Time_hr浮动充电的大致时间(小时),上下文因充电方法而异。7.5 价格_USD浮动参考车辆价格(美元).85000.00 颜色类别主要外观颜色或饰面。午夜黑 制造国_制造类别车辆制造/组装的国家。美国 Autonomous_Level浮点自动化能力级别(例如0-5),可能包括子级别的小
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值