算法面试真题详解: 四数之和

简介: 算法面试真题详解: 四数之和

描述
给一个包含n个数的整数数组S,在S中找到所有使得和为给定整数target的四元组(a, b, c, d)。
四元组(a, b, c, d)中,需要满足a <= b <= c <= d
答案中不可以包含重复的四元组。

在线评测地址:领扣题库官网

样例 1:
输入:[2,7,11,15],3
输出:[]
样例2:
输入:[1,0,-1,0,-2,2],0
输出:
[[-1, 0, 0, 1]
,[-2, -1, 1, 2]
,[-2, 0, 0, 2]]

算法:DFS / 双指针

DFS:
朴素DFS,对排序后的队列进行搜索每次选取当前数后的比当前值大的数压入List,当List大小为4的时候判断是否四个元素的和为taeget
对数组排序
用List记录选取的元素
由于已经升序排列,只需要要去找上个元素的后面的位置的元素作为下一个元素
若List大小为4,且和为target的时候记录一次答案

复杂度分析

时间复杂度O(n^3)
最差情况搜索为n^3
空间复杂度O(n*n)
存储答案的大小
双指针:
虽然题目是四数之和,但是我们可以将他转换为三数之和,再进一步就是二数之和,先进行稳定排序,然后我们准备用四个指针
先用将问题看待为三数之和,即一个指针和三个指针
再将这三个指针看成二数之和,即一个指针和两个指针
那么问题就被化简了,先框定两个指针,再在这个基础上,用双指针解决问题,当头指针和尾指针的元素之和大于new_target,尾指针-1(因为头指针+1的结果肯定大于new_target),同理当头指针和尾指针的元素之和小于new_target,头指针+1。
对序列排序,用一个set存储答案,因为有可能存在相同的答案
用两个for循环嵌套,代表第一二个指针
然后用一对双指针从第二个指针后面的位置向右和末尾向左进行移动
如果四个指针的和等于target,将这组答案添加,如果小于的话左指针右移,反之右指针左移
将set中的答案输出

复杂度分析

时间复杂度O(n^3)
最差情况搜索为n3n3
空间复杂度 O(n^2)
存储答案的大小
//DFS

public class Solution {
    /**
     * @param numbers: Give an array
     * @param target: An integer
     * @return: Find all unique quadruplets in the array which gives the sum of zero
     */
    public List<List<Integer>> fourSum(int[] numbers, int target) {
        List<List<Integer>> ans = new ArrayList<>();
        //排序
        Arrays.sort(numbers);
        //DFS
        dfs(numbers, new ArrayList<Integer>(), target, ans, 0);
        return ans;
    }

    private void dfs(int[] numbers, List<Integer> list, int target, List<List<Integer>> ans, int index) {
        //判断值是否符合要求
        if (list.size() == 4) {
            if (target == 0) {
                ans.add(new ArrayList<Integer>(list));
            }
            return;
        }
        for (int i = index; i < numbers.length; i++) {
            if (i != index && numbers[i] == numbers[i-1]) {
                continue;
            }
            //选取当前元素
            list.add(numbers[i]);
            dfs(numbers, list, target-numbers[i], ans, i+1);
            list.remove(list.size() - 1);
        }
    }
}
//双指针
public class Solution {
    /**
     * @param numbers: Give an array
     * @param target: An integer
     * @return: Find all unique quadruplets in the array which gives the sum of zero
     */
    public List<List<Integer>> fourSum(int[] numbers, int target) {
        Set<List<Integer>> res = new HashSet<List<Integer>>();//用set可以避免出现重复答案
        Arrays.sort(numbers);
        int size = numbers.length;
        List<List<Integer>> ans=new ArrayList<List<Integer>>();
        for (int i = 0; i < size - 3; i++) {//第一个指针
            for (int j = i + 1;j < size - 2;j++) {//第二个指针
                if (j > i + 1 && numbers[j] == numbers[j-1]) {
                    continue;
                }
                int left = j + 1,right = size - 1;//第三第四个指针
                while (left < right) {
                    int sum = numbers[i] + numbers[j] + numbers[left] + numbers[right];
                    if (sum == target) {//如果序列和=target,将序列添加到set中
                        List<Integer> tmp = new ArrayList<>();
                        tmp.add(numbers[i]);
                        tmp.add(numbers[j]);
                        tmp.add(numbers[left]);
                        tmp.add(numbers[right]);
                        res.add(tmp);
                        left++; //左指针向右
                        right--;//右指针向左
                    }
                    else if (sum < target) {//如果序列和比target小,左指针向右
                        left++;   
                    }     
                    else {//如果序列和比target大,右指针向左
                        right--;
                    } 
                }
            }
        }
        for (List<Integer> tmp:res) {//输出结果
            ans.add(tmp);
        }
        return ans;
    }
}

更多题解参考:九章官网solution

相关文章
|
1月前
|
负载均衡 NoSQL 算法
一天五道Java面试题----第十天(简述Redis事务实现--------->负载均衡算法、类型)
这篇文章是关于Java面试中Redis相关问题的笔记,包括Redis事务实现、集群方案、主从复制原理、CAP和BASE理论以及负载均衡算法和类型。
一天五道Java面试题----第十天(简述Redis事务实现--------->负载均衡算法、类型)
|
1月前
|
算法 Go
[go 面试] 雪花算法与分布式ID生成
[go 面试] 雪花算法与分布式ID生成
|
1月前
|
JavaScript 算法 索引
【Vue面试题二十三】、你了解vue的diff算法吗?说说看
这篇文章深入分析了Vue中的diff算法,解释了其在新旧虚拟DOM节点比较中的工作机制,包括同层节点比较、循环向中间收拢的策略,并通过实例演示了diff算法的执行过程,同时提供了源码层面的解析,说明了当数据变化时,如何通过Watcher触发patch函数来更新DOM。
【Vue面试题二十三】、你了解vue的diff算法吗?说说看
|
1月前
|
算法
聊聊一个面试中经常出现的算法题:组合运算及其实际应用例子
聊聊一个面试中经常出现的算法题:组合运算及其实际应用例子
|
1月前
|
机器学习/深度学习 算法 数据中心
【机器学习】面试问答:PCA算法介绍?PCA算法过程?PCA为什么要中心化处理?PCA为什么要做正交变化?PCA与线性判别分析LDA降维的区别?
本文介绍了主成分分析(PCA)算法,包括PCA的基本概念、算法过程、中心化处理的必要性、正交变换的目的,以及PCA与线性判别分析(LDA)在降维上的区别。
44 4
|
1月前
|
算法
突击面试:解密面试官的算法题集合
突击面试:解密面试官的算法题集合
|
1月前
|
机器学习/深度学习 算法
【机器学习】解释对偶的概念及SVM中的对偶算法?(面试回答)
解释了对偶的概念,指出对偶性在优化问题中的重要性,尤其是在强对偶性成立时可以提供主问题的最优下界,并且详细阐述了支持向量机(SVM)中对偶算法的应用,包括如何将原始的最大间隔优化问题转换为对偶问题来求解。
47 2
|
1月前
|
机器学习/深度学习 算法 数据挖掘
|
1月前
|
消息中间件 存储 算法
这些年背过的面试题——实战算法篇
本文是技术人面试系列实战算法篇,面试中关于实战算法都需要了解哪些内容?一文带你详细了解,欢迎收藏!
|
1月前
|
算法
分享几道大厂面试算法题
分享几道大厂面试算法题