LeetCode学习笔记——“多”数之和(JAVA实现)
个人博客:The Blog Of WaiterXiaoYY 欢迎来互相交流学习。
前言
在最近LeetCode的刷题过程中,
发现了几道有意思又相似的题目,
就是求两数之和,三数之和,四数之和,
一开始在做两数之和的时候,我使用的是C,
在做到三数之和的时候,一开始还是想使用C尝试一下,
但是面临要去重的问题,用C感觉就很麻烦(主要是不会),
但是用到Java的话,就感觉大大便利了。
1.两数之和
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
解题思路
题目要求的是找出等于target的两个数的数组下标,且说明了一次输入只有一个答案,
所以可以定义一个长度为2数组来保留两个数的数组下标。
找数组中两个数,我一开始想到的就是双指针,
慢指针(姑且这么叫吧)作为一端的端点,而快指针(姑且也这么叫吧)则从端点+1的位置遍历数组,
直到找出等于target的两个数,将数组下标保存在数组中,返回。
代码
class Solution {
public int[] twoSum(int[] nums, int target) {
//数组内初始值为-1,不能为0,在没有找到值的时候返回0会错误。
int[] res= {-1,-1};
int n = nums.length;
int i,j;
for(i=0;i < n-1;i++){
for(j=i+1;j < n;j++){
//相等时则存入数组下标
if(nums[i] + nums[j] == target){
res[0] = i;
res[1] = j;
}
}
}
return res;
}
}
15.三数之和
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
解题思路
相比于两数之和,这道题难度我感觉大大真高了,在leetcode里面也属于mid类的,
主要是涉及到去重的问题,可以用java中的HashSet来实现,
与ArrayList不同HashSet不能保存相同的东西,这样我们就可以使用HashSet的列表去保留我们找到的数值,
如果数是完全重复的,那么就不会加到里面去,最后我们再把它整个加到一个新的数组里面,返回新的数组。
上面是关于去重的做法,下面是这道题的思路,
与两数之和思路有相同之处,不过我们先对数组进行排序,从小到大排序,
我们还是先找到一个端点,就从数组下标0开始,也弄一个双指针,一个从端点+1开始,一个在数组末端,
判断三个数的大小,
等于0则加入到HashSet的列表中,
如果小于0,因为我们已经排好序,那就将左边的指针+1,
如果大于0,就将右边的指针-1。
代码
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
//创建一个HashSet的列表,用于去重
Set<List<Integer>> res = new HashSet<>();
//将数组进行排序
Arrays.sort(nums);
int n = nums.length;
for(int i=0;i < n -2;i++){
int l = i + 1; //左指针
int r = n - 1; //右指针
while(l < r){
if(nums[i] + nums[l] + nums[r] == 0){ //等于0,则加入到列表中
res.add(Arrays.asList(nums[i],nums[l],nums[r]));
l++;
r--;
}
else if(nums[i] + nums[l] + nums[r] < 0){ //小于0,左指针++
l++;
}else{ //大于0,右指针--
r--;
}
}
}
//创建一个新的数组
List<List<Integer>> ans = new ArrayList<>();
ans.addAll(res); //将HashSet全部加到数组里面
return ans;
}
}
18.四数之和
给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
注意:答案中不可以包含重复的四元组。
示例
给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。
满足要求的四元组集合为:
[
[-1, 0, 0, 1],
[-2, -1, 1, 2],
[-2, 0, 0, 2]
]
解题思路
四数之和其实和三数之和是差不多的,我也是直接在三数之和的基础上改的,
去重的方式一样,这里就不赘述了,
但四数之和要比三数之和多一个指针,其实也看作是一个端点(叫做后端点),
相比于前端点多了一个位置,其实就是两层for循环。
与三数之和相同,两个的端点的值不能到达数组末尾了,因为我们要保留一个四元组。
代码
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
//新建一个HashSet的列表,用于去重
Set<List<Integer>> res = new HashSet<>();
//将数组进行排序
Arrays.sort(nums);
int n = nums.length;
int i,j;
//i只能到达n-3的位置,后面要有足够的空间判断
for(i=0;i < n-3;i++){
//j只能到达n-2
for(j=i+1;j < n-2;j++){
int l = j + 1;
int r = n - 1;
while(l < r){
//相等则将数存入数组列表中
if(nums[i] + nums[j] + nums[l] + nums[r] == target){
res.add(Arrays.asList(nums[i],nums[j],nums[l],nums[r]));
l++;
r--;
}
//小于就左指针++
else if(nums[i] + nums[j] + nums[l] + nums[r] < target){
l++;
}
else //大于就右指针--
r--;
}
}
}
//新建一个数组,将HashSet中的值全部转移过来
List<List<Integer>> ans = new ArrayList<>();
ans.addAll(res);
return ans;
}
}
整理于2020.3.10
个人博客:The Blog Of WaiterXiaoYY 欢迎来互相交流学习。