【几数之和系列】四数之和都不会做,面试官让我回去看力扣第一题(上)

简介: 今天为大家讲解的是力扣经典的几数之和系列。有句话说得好——有人夜里看海,有人力扣第一题都做不出来。大家应该都知道力扣的第一题是两数之和。但其实两数之和只是一个起始,在进阶的还有三数之和,四数之和以及四数相加等等。今天我为大家将这一系列从易到难为大家整合好,其中详细解析各种方法,帮助大家总结其中规律,以达到举一反三的效果。建议大家收藏,方便训练。

🍋1.刷题与观看须知


       几数几何系列是力扣最经典的系列套题之一,它的每道题解法都非常多样化。用到了各种各样的算法知识,比如暴力枚举、哈希、排序+双指针等等。但是,虽然很多人能做出来,但是却只会一种朴素的解法,这就感到沾沾自喜了。这类题一定要会做到举一反三触类旁通,希望大家每道题都能多样化解题,同时总结出这类题的规律。


🍋2.逐步训练,鏖战力扣


🐱 1.两数之和


给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标。


你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。


你可以按任意顺序返回答案。


题目链接:两数之和https://leetcode-cn.com/problems/two-sum/


作为力扣的第一题,它是很多人成神的起点,这道题也有着自己的美丽。


        题目分析:第一个想到肯定是暴力遍历,其次是利用哈希表。哈希表的解法也有不同类型,这里我们用的是Hashmap,用key存放值,value存放下标,在遍历数组nums[i]的同时寻找哈希表内是否有符合的数,有则返回两个下标,无则将nums[i]放入哈希表中。


1.暴力遍历


       时间复杂度O(N^2):使用两层for循环,最坏的情况每两个数都要被遍历几次


       空间复杂度O(1):常数级的数组空间


class Solution {
    public int[] twoSum(int[] nums, int target) {
        int n = nums.length;
        for (int i = 0; i < n; ++i) {
            for (int j = i + 1; j < n; ++j) {
                if (nums[i] + nums[j] == target) {
                    return new int[]{i, j};
                }
            }
        }
        return new int[0];
    }
 }


2.利用HashMap


       时间复杂度O(N) :只遍历了一次数组


       空间复杂度O(N):主要为哈希表的开销


class Solution {
    public int[] twoSum(int[] nums, int target) {
        int n=nums.length;
        //key存放值,value存放下标
        Map<Integer,Integer> map=new HashMap<>();
        for(int i=0;i<n;i++){
            //找到了
            if(map.containsKey(target-nums[i])){
                //返回下标
                return new int[]{map.get(target-nums[i]),i};
            }
            //没找到放入map中
            map.put(nums[i],i);
        }
        //遍历结束仍然未找到
        return new int[0];
    }
}


🐭2.两数之和||——输入有序数组


给定一个已按照 非递减顺序排列  的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target 。


函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 1 开始计数 ,所以答案数组应当满足 1 <= answer[0] < answer[1] <= numbers.length 。


你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。


题目链接:两数之和||——输入有序数组https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/


           思路分析:这道题可以同上一道一样使用暴力求解以及哈希表,但那是针对与无序数组的。因为是一个排好序的数组,我们自然要想到双指针,从两头开始遍历。当两指针相加的元素大于target,右指针向左移动,当小于target时,让左指针右移。


          时间复杂度:O(n),其中n是数组的长度,两个指针移动最多一共n次


          空间复杂度:O(1)


class Solution {
    public int[] twoSum(int[] numbers, int target) {
         int n=numbers.length;
         int left=0;
         int right=n-1;
         while(left<right){
             int count=numbers[left]+numbers[right];
             //找到了,但是下标要加1,因为题目要求
             if(count==target){
                 return new int[]{left+1,right+1};
             //加起来太大了,right--,这样count会变小
             }else if(count>target){
                 right--;
             //加起来太小了,left++,这样count会变大
             }else{
                 left++;
             }
         }
         return new int[0];
    }
}


🐸3.两数之和IV——输入BST


给定一个二叉搜索树 root 和一个目标结果 k,如果树中存在两个元素且它们的和等于给定的目标结果,则返回 true。          


题目链接:两数之和 IV - 输入 BSThttps://leetcode-cn.com/problems/two-sum-iv-input-is-a-bst/        


            题目分析:这道题与前面的两数之和类似,只不过是元素存放的形式变成了树,我们同样可以利用Hashset来遍历树。


           方法:Hashset加遍历树。判断当前root时,set中是否存在k-root.val,如果存在直接返回true。不存在的话将此时的root.val存放进set中,同时去左子树和右子树中继续查找。


           时间复杂度O(n),n为节点的数量,最坏的情况下,整棵树被遍历一次


            空间复杂度O(n),最坏的情况下,set存储n个节点的值。


class Solution {
    public boolean findTarget(TreeNode root, int k) {
        Set<Integer> set=new HashSet<>();
        return find(root,k,set);
    }
    public boolean find(TreeNode root,int k,Set set){
        //如果root为空直接返回false
        if(root==null) return false;
        if(set.contains(k-root.val)){
            return true;
        }
        //这个没找到就加入到set集合中
        set.add(root.val);
        //同时去左子树和右子树查找
        return find(root.left,k,set)||find(root.right,k,set);
    }
}


🐶4.三数之和


给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。


注意:答案中不可以包含重复的三元组。


题目链接:三数之和https://leetcode-cn.com/problems/3sum/        


        题目分析:这道题和两数之和看上去类似,但做法却不相同,难度也不在一个档次,朴素暴力的做法再最后几个例子会超时


方法1:朴素暴力(超时)


       时间复杂度O(N^3)


class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        int n=nums.length;
        List<List<Integer>> list=new ArrayList<>();
        for(int i=0;i<n-2;i++){
            for(int j=n-1;j>i+1;j--){
                int x=i+1;
                while(x<j){
                int count=nums[i]+nums[x]+nums[j];
                if(count==0){
                    List<Integer> arr=new ArrayList<>();
                    arr.add(nums[i]);
                    arr.add(nums[x]);
                    arr.add(nums[j]);
                    if(!list.contains(arr)){
                        list.add(arr);
                    }
                    x++;
                }else if(count>0){
                    break;
                }else{
                    x++;
                }
            }
            }
        }
        return list;
    }
}

 

相关文章
|
7月前
|
存储 算法 数据挖掘
深入解析力扣168题:Excel表列名称(进制转换法详解及模拟面试问答)
深入解析力扣168题:Excel表列名称(进制转换法详解及模拟面试问答)
|
7月前
|
存储 算法 数据挖掘
深入解析力扣166题:分数到小数(模拟长除法与字符串操作详解及模拟面试问答)
深入解析力扣166题:分数到小数(模拟长除法与字符串操作详解及模拟面试问答)
|
7月前
|
存储 算法 数据可视化
【模拟面试问答】深入解析力扣163题:缺失的区间(线性扫描与双指针法详解)
【模拟面试问答】深入解析力扣163题:缺失的区间(线性扫描与双指针法详解)
|
7月前
|
存储 算法 数据可视化
【模拟面试问答】深入解析力扣164题:最大间距(桶排序与排序方法详解)
【模拟面试问答】深入解析力扣164题:最大间距(桶排序与排序方法详解)
|
7月前
|
SQL 算法 大数据
深入解析力扣176题:第二高的薪水(子查询与LIMIT详解及模拟面试问答)
深入解析力扣176题:第二高的薪水(子查询与LIMIT详解及模拟面试问答)
|
7月前
|
算法 数据挖掘 大数据
深入解析力扣172题:阶乘后的零(计算因子5的方法详解及模拟面试问答)
深入解析力扣172题:阶乘后的零(计算因子5的方法详解及模拟面试问答)
|
7月前
|
算法 数据挖掘 大数据
深入解析力扣171题:Excel表列序号(进制转换法详解及模拟面试问答)
深入解析力扣171题:Excel表列序号(进制转换法详解及模拟面试问答)
|
7月前
|
算法 数据挖掘 Java
深入解析力扣167题:两数之和 II(双指针法详解及模拟面试问答)
深入解析力扣167题:两数之和 II(双指针法详解及模拟面试问答)
|
7月前
|
存储 算法 数据挖掘
【模拟面试问答】力扣165题:比较版本号(逐个比较与双指针法详解及模拟面试问答)
【模拟面试问答】力扣165题:比较版本号(逐个比较与双指针法详解及模拟面试问答)
|
6月前
|
Python
155. 最小栈 力扣 python 空间换时间 o(1) 腾讯面试题
155. 最小栈 力扣 python 空间换时间 o(1) 腾讯面试题

热门文章

最新文章