LeetCode学习笔记——“多”数之和(JAVA实现)

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 欢迎来互相交流学习。

END
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值