【算法训练-数组 二】【元素组合】两数之和、三数之和

简介: 【算法训练-数组 二】【元素组合】两数之和、三数之和

废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇Blog的主题是两数之和和三数之和,使用哈希这个基本的数据结构来实现

两数之和【EASY】

照例先从简单往难搞

题干

输入:
[3,2,4],6
返回值:
[2,3]
说明:
因为 2+4=6 ,而 2的下标为2 , 4的下标为3 ,又因为 下标2 < 下标3 ,所以返回[2,3]
输入:
[20,70,110,150],90
返回值:
[1,2]
说明:
20+70=90

解题思路

哈希 实现。从题中给出的有效信息:找出下标对应的值相加为target,数组中存在唯一解,故此 可以使用 直接遍历或者 hash表来解答,直接双重循环遍历时间复杂度太高,

代码实现

基本数据结构数组

辅助数据结构哈希表

算法迭代

技巧哈希查找

import java.util.*;
public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param numbers int整型一维数组
     * @param target int整型
     * @return int整型一维数组
     */
    public int[] twoSum (int[] numbers, int target) {
        // 1 用哈希表记录出现过的数字,key为数字,value为下标
        Map<Integer, Integer> map = new HashMap<>();
        int[] result = new int[2];
        for (int i = 0; i < numbers.length; i++) {
            // 得出需要的差值是多少
            int needVal = target - numbers[i];
            if (map.containsKey(needVal)) {
                // 如果map存储了差值则记录两数
                result[0] = map.get(needVal);
                result[1] = i + 1;
            } else {
                // 如果map未存储差值则将当前值存储
                map.put(numbers[i], i + 1);
            }
        }
        return result;
    }
}

复杂度分析

时间复杂度O(N):遍历了数组;空间复杂度O(N),定义了哈希结构存储数据。相比于双重循环这种方式是典型的空间换时间

三数之和【MID】

好的,难度升级,进入三数之和:

题干

输入:
[0]
返回值:
[]
输入:
[-2,0,1,1,2]
返回值:
[[-2,0,2],[-2,1,1]]
输入:
[-10,0,10,20,-10,-40]
返回值:
[[-10,-10,20],[-10,0,10]]

解题思路

排序+双指针实现。关键点:三元组按照升序排列;不能出现重复三元组。值得注意的是,虽然这里可以继续用哈希+双重循环把两数之和转为三数之和,但没有必要,因为我们之所以用哈希主要是为了找下标,而题目没有要求给出下标,只要给出值的三元组即可,所以这里用哈希反而增加了空间复杂度,并且也没有降低时间复杂度。

代码实现

基本数据结构数组

辅助数据结构

算法迭代、快速排序

技巧双指针

使用Java实现,特别注意的是基准值、左指针和右指针都需要避免重复的情况

import java.util.*;
public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param num int整型一维数组
     * @return int整型ArrayList<ArrayList<>>
     */
    public ArrayList<ArrayList<Integer>> threeSum (int[] num) {
        // 1 定义返回结果
        ArrayList<ArrayList<Integer>> result = new ArrayList<>();
        // 排除不满足条件的num
        if (num == null || num.length < 3) {
            return result;
        }
        // 2 要求非降序排列,且为了应用左右指针及去重考虑,先对整个数组升序排列
        Arrays.sort(num);
        // 3 遍历数组,以其中一个数为基准,双指针寻找另外两个数
        for (int i = 0; i < num.length - 2; i++) {
            // 减少无效遍历,去掉无效情况,如果第一个数都大于0,那总和一定大于0
            if (num[i] > 0) {
                break;
            }
            // 排除基准数的重复值
            if (i > 0 && num[i] == num[i - 1]) {
                continue;
            }
            int left = i + 1, right = num.length - 1;
            int target = -num[i];
            while (left < right) {
                if (num[left] + num[right] == target) {
                    // 存放满足条件的三元组并移动指针
                    result.add(new ArrayList<>(Arrays.asList(num[i], num[left], num[right])));
                    // 基准数固定,指针移动,左指针向右,右指针必须向左【左+右】为固定值,如果左值不变,右值也不变就重复了,如果左值变,右值就不可能和原来一致,所以必须向左寻求新值。
                    left++;
                    right--;
                    // 由于数组已经排序,所以可能出现重复三元组的数据就在相邻位置,所以需要越过相邻位置的重复三元组
                    while (left < right && num[left] == num[left - 1]) {
                        left++;
                    }
                    while (left < right && num[right] == num[right + 1]) {
                        right--;
                    }
                } else if (num[left] + num[right] > target) {
                    // 大于目标值,右指针向左减小总值
                    right--;
                } else {
                    // 小于目标值,左指针向右扩大总值
                    left++;
                }
            }
        }
        return result;
    }
}

复杂度分析

时间复杂度:O(n log n) 【排序】+ O(n^2)【外层for循环和内层while循环】

空间复杂度:O(1),排除结果的数据结构

相关文章
|
20天前
|
存储 算法 Java
解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用
在Java中,Set接口以其独特的“无重复”特性脱颖而出。本文通过解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用。
38 3
|
1月前
|
算法
Leetcode 初级算法 --- 数组篇
Leetcode 初级算法 --- 数组篇
37 0
|
27天前
|
存储 机器学习/深度学习 算法
蓝桥杯练习题(三):Python组之算法训练提高综合五十题
蓝桥杯Python编程练习题的集合,涵盖了从基础到提高的多个算法题目及其解答。
50 3
蓝桥杯练习题(三):Python组之算法训练提高综合五十题
|
28天前
|
算法 程序员 索引
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
栈的基本概念、应用场景以及如何使用数组和单链表模拟栈,并展示了如何利用栈和中缀表达式实现一个综合计算器。
26 1
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
|
7天前
|
分布式计算 Java 开发工具
阿里云MaxCompute-XGBoost on Spark 极限梯度提升算法的分布式训练与模型持久化oss的实现与代码浅析
本文介绍了XGBoost在MaxCompute+OSS架构下模型持久化遇到的问题及其解决方案。首先简要介绍了XGBoost的特点和应用场景,随后详细描述了客户在将XGBoost on Spark任务从HDFS迁移到OSS时遇到的异常情况。通过分析异常堆栈和源代码,发现使用的`nativeBooster.saveModel`方法不支持OSS路径,而使用`write.overwrite().save`方法则能成功保存模型。最后提供了完整的Scala代码示例、Maven配置和提交命令,帮助用户顺利迁移模型存储路径。
|
21天前
|
存储 算法 Java
Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性
Java Set因其“无重复”特性在集合框架中独树一帜。本文解析了Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性,并提供了最佳实践建议,包括选择合适的Set实现类和正确实现自定义对象的hashCode()与equals()方法。
31 4
|
1月前
|
机器学习/深度学习 算法 决策智能
【机器学习】揭秘深度学习优化算法:加速训练与提升性能
【机器学习】揭秘深度学习优化算法:加速训练与提升性能
|
28天前
|
存储 算法 定位技术
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列
这篇文章主要介绍了稀疏数组和队列的概念、应用实例以及如何使用数组模拟队列和环形队列的实现方法。
20 0
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列
|
15天前
|
算法 安全 数据安全/隐私保护
基于game-based算法的动态频谱访问matlab仿真
本算法展示了在认知无线电网络中,通过游戏理论优化动态频谱访问,提高频谱利用率和物理层安全性。程序运行效果包括负载因子、传输功率、信噪比对用户效用和保密率的影响分析。软件版本:Matlab 2022a。完整代码包含详细中文注释和操作视频。
|
1天前
|
算法 调度
基于遗传模拟退火混合优化算法的车间作业最优调度matlab仿真,输出甘特图
车间作业调度问题(JSSP)通过遗传算法(GA)和模拟退火算法(SA)优化多个作业在并行工作中心上的加工顺序和时间,以最小化总完成时间和机器闲置时间。MATLAB2022a版本运行测试,展示了有效性和可行性。核心程序采用作业列表表示法,结合遗传操作和模拟退火过程,提高算法性能。