算法小白刷力扣 1 - 两数之和

题目描述

原题链接:https://leetcode.cn/problems/two-sum/description/

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

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

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

示例 1:

输入:nums = 2,7,11,15, target = 9

输出:0,1

解释:因为 nums0 + nums1 == 9 ,返回 0, 1 。

示例 2:

输入:nums = 3,2,4, target = 6

输出:1,2

示例 3:

输入:nums = 3,3, target = 6

输出:0,1

提示:

  • 2 <= nums.length <= 104
  • -109 <= numsi <= 109
  • -109 <= target <= 109
  • 只会存在一个有效答案

2. 我的解法

毫无疑问,算法小白首先想到的肯定是暴力破解。什么是暴力破解?众所周知,凡是用了双层循环导致算法复杂度为 O(n^2) 的肯定不算最优解,是暴力破解,来看看我的暴力破解。

java 复制代码
class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] result = new int[2];
        for(int i = 0; i < nums.length; i++) {
            boolean found = false;
            // 这里是关键,由于是从前往后挨个找,那第 i 个元素之前的元素已经找过了,就不需要再算了,因此每次从第 i + 1 个元素开始找
            for(int j = i + 1; j < nums.length; j++) {
                if(nums[i] + nums[j] == target) {
                    result[0] = i;
                    result[1] = j;
                    found = true;
                    break;
                }
            }
            if(found) {
                break;
            }
        }
        return result;
    }
}

因为题目明确说明只有一个有效答案,所以找到第一组解时就应该停止循环,所以用了一个 flag 标志,如果找到就 break,但看了官方解法,这一步纯属多余,找到直接 return 不就行了,我哭~

这里贴一下官方提供的暴力破解法以供参考:

java 复制代码
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];
    }
}

3. 正确解法

照例先贴代码,因为我没想到,所以没思路可说:

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

只有一层循环,显然时间复杂度降为了 O(n)。但没想到的是它竟然用了哈希表!我以为不能直接用现成的数据结构呢,还寻思有啥特殊技能,原来是用了大杀器,那不还是用空间换时间的套路嘛,害,所以所谓更优来来回回也就这点儿事儿,理解了这一点,思路就打开了。

那他是怎么用一层循环加哈希表就搞定的呢?重点就是用了哈希表,给遍历过程赋予了记忆的能力,即已经遍历过哪些元素会在哈希表中单独存一份以备后续使用,且哈希表的查找复杂度为 O(1),很容易就能判断一个元素是否存在,有了这两个能力,就很简单了。每次遍历到元素num[i]时,target - num[i] 就是我们要找的元素,所以我们只要判断在哈希表中有没有 target - numi 就可以了。

但记忆能力还不是用哈希表的唯一原因,如果我们只需要将遍历过的元素记下来并判断是否需要,那用 HashSet 就可以了,但很显然,HashSet 只能存单个元素,不能存键值对,当我们想获取目标元素的索引时就不行了,所以将目标元素的索引存为哈希节点的 value 中就能轻易拿到了。

谈到哈希表,其查找能力在算法题解中用到的最多,此外还可借助映射特性汇总一组数据中每个 Key 对应的统计值。

相关推荐
启观川3 小时前
数据结构与算法 -第 3 章 常用算法-动态规划
数据结构·笔记·python·算法
码爸3 小时前
排序算法介绍
python·算法·排序算法
Interview Aid1124 小时前
SoFi 面试流程全解析:技术面试、OA 与备考指南
面试·职场和发展
动词ing5 小时前
【题目练习】算法 组合总和||
算法
longlongzihan5 小时前
链表找环:Floyd 判圈算法(LeetCode 141 & 142 )
c++·算法·leetcode·链表
专业程序开发源5 小时前
flask家电故障预测系统92491-计算机课程设计/毕业设计
vscode·python·sql·算法·flask·课程设计
Logic1015 小时前
C语言/数据结构欧几里得算法题解:长方形切割最大正方形——贪心划分计数
c语言·数据结构·算法·贪心算法·时间复杂度·空间复杂度·欧几里得算法
yi0115 小时前
LeetCode 643. 子数组最大平均数 I|从暴力枚举到滑动窗口
人工智能·笔记·python·算法·leetcode·滑动窗口
YangYang9YangYan6 小时前
2027数学与应用数学转产品经理:面试解释与项目准备
面试·职场和发展·产品经理
极光通讯6 小时前
服务器内存来料检验(IQC)实操:批次追溯、外观判定与上机验证
java·服务器·算法