两数之和、四数相加II、三数之和、四数之和

1. 两数之和

这道题可以暴力也可以用哈希。

首先来说暴力,就是两个嵌套的循环,找到的第一个相加为target的一组数返回。

哈希就相对复杂一点。当然大家可能会有疑问,什么时候使用哈希,使用哪种哈希?每当我们遇到要判断这种元素是否出现过时,就可以使用哈希,具体使用哪种可以看我之前的文章。对于本题,我们要找到和为目标值的数的下标,首先找到这两个数,再找到下标,相当于key和value,且key不能重复,所以要使用HashMap。代码如下

java 复制代码
class Solution {
    public int[] twoSum(int[] nums, int target) {
     Map<Integer,Integer> map=new HashMap<>();
     for(int i=0;i<nums.length;i++){
        int s=target-nums[i];
        if(map.containsKey(s)){
            return new int[]{map.get(s),i};
        }
        map.put(nums[i],i);
     }
     return new int[0];
    }
}

令s=target-numsi,查询map中是否有numsi的另一半,如果有就返回,如果没有就存到map中继续向后循环。

454. 四数相加 II

这道题一个暴力的思路是四个for循环,但这样太麻烦了,我们依然可以使用哈希表。这道题可能出现很大的数,因此不能用数组。又因为我们不仅要统计这个数是否出现过,还要统计出现的次数,因此还是用HashMap。代码如下

java 复制代码
class Solution {
    public int fourSumCount(int[] A, int[] B, int[] C, int[] D) {
        Map<Integer,Integer> map=new HashMap<>();
        int count=0;
        for(int a:A){
            for(int b:B){
                map.put(a+b,map.getOrDefault(a+b,0)+1);  
            }
        }
        for(int c:C){
            for(int d:D){
                if(map.containsKey(-c-d)){
                    count+=map.get(-c-d);
                }
            }
        }
        return count;
    }
}

我们先将a、b两个数组的数相加,存到map中,如果有重复的就让value的值加一。之后让c、d两个数组的值相加,判断map中是否有-(c+d)的值,如果有就让次数加上value。

我们要找的是a+b+c+d=0,所以a+b=-(c+d),因此找-(c+d),又因为不需要去重,所以次数加的是value的。

15. 三数之和

这道题也可以用哈希来做,但比较复杂,我们可以使用双指针的方法。我们需要在一个数组里找出三个数相加等于0,且不能重复。

我们可以建立一个for循环,之后创建两个指针,不过前提是将他们升序排列。如果numsi>0,则直接退出循环。之后就看numsi+numsleft+numsright的值,如果大于0,就让right--,如果小于0,就让left++。又因为不能重复,所以numsi如果和numsi-1相等的话,则要跳过这一次循环,left和right也是一样。代码如下

java 复制代码
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        List<List<Integer>> ans=new ArrayList<List<Integer>>();
        for(int i=0;i<nums.length;i++){
            if(nums[i]>0)
            break;
            if(i>0&&nums[i]==nums[i-1])
            continue;
            int left=i+1;
            int right=nums.length-1;
            while(right>left){
                if(nums[i]+nums[left]+nums[right]>0){
                    right--;
                }else if(nums[i]+nums[left]+nums[right]<0){
                    left++;
                }else{
                    List<Integer> list=new ArrayList<Integer>();
                    list.add(nums[i]);
                    list.add(nums[left]);
                    list.add(nums[right]);
                    ans.add(list);
                    while(right>left&&nums[right]==nums[right-1]){
                    right--;
                }
                while(left<right&&nums[left]==nums[left+1]){
                    left++;
                }
                left++;
                right--;
                }
                
            }
        }
        return ans;
    }
}

18. 四数之和

这题跟三数之和很相似,只不过多了一个数,那我们就用两个循环。

代码如下。

java 复制代码
class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
          Arrays.sort(nums);
        List<List<Integer>> ans=new ArrayList<List<Integer>>();
        for(int i=0;i<nums.length;i++){
            for(int k=i+1;k<nums.length;k++){
            if((nums[i]>target&&target>0)||(nums[i]+nums[k]>target&&target>0))
            break;
            if((i>0&&nums[i]==nums[i-1])||(k>i+1&&nums[k]==nums[k-1]))
            continue;
            int left=k+1;
            int right=nums.length-1;
            while(right>left){
                if((long)nums[i]+nums[left]+nums[right]+nums[k]>target){
                    right--;
                }else if((long)nums[i]+nums[left]+nums[right]+nums[k]<target){
                    left++;
                }else{
                    List<Integer> list=new ArrayList<Integer>();
                    list.add(nums[i]);
                    list.add(nums[k]);
                    list.add(nums[left]);
                    list.add(nums[right]);
                    ans.add(list);
                    while(right>left&&nums[right]==nums[right-1]){
                    right--;
                }
                while(left<right&&nums[left]==nums[left+1]){
                    left++;
                }
                left++;
                right--;
                }
                
            }
        }
        }
        return ans;
    }
}
相关推荐
G.O.G.O.G4 分钟前
LeetCode SQL 从入门到精通(MySQL)06(上)
数据库·sql·mysql·leetcode
二炮手亮子13 分钟前
浅记java线程池
java·开发语言
一路向北North13 分钟前
Spring Security OAuth2.0(23):分布式系统授权-转发明文给微服务
java·spring·微服务
zephyr052 小时前
动态规划-最长上升子序列问题
算法·动态规划
闪电悠米2 小时前
力扣hot100-56.合并区间-排序详解
数据结构·算法·leetcode·贪心算法·排序算法
爱吃牛肉的大老虎2 小时前
rust基础之环境搭建
java·开发语言·rust
tellmewhoisi3 小时前
多版本共用redis的token有效期校验(过期重新登录)
java·redis·缓存
疯狂打码的少年3 小时前
【软件工程】结构化设计:模块独立性与耦合内聚
java·开发语言·笔记·软件工程
乐观的Terry3 小时前
3、数据库设计与领域实体
java·数据库·spring boot·spring cloud·ai编程
卡提西亚3 小时前
leetcode-1438. 绝对差不超过限制的最长连续子数组
算法·leetcode·职场和发展