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

题目描述

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

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

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

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

示例 1

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

输出:[0,1]

解释:因为 nums[0] + nums[1] == 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 <= nums[i] <= 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 - num[i] 就可以了。

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

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

相关推荐
面试鸭4 分钟前
离谱!买个人信息买到网安公司头上???
java·开发语言·职场和发展
@小博的博客12 分钟前
C++初阶学习第十弹——深入讲解vector的迭代器失效
数据结构·c++·学习
南宫生1 小时前
贪心算法习题其四【力扣】【算法学习day.21】
学习·算法·leetcode·链表·贪心算法
懒惰才能让科技进步2 小时前
从零学习大模型(十二)-----基于梯度的重要性剪枝(Gradient-based Pruning)
人工智能·深度学习·学习·算法·chatgpt·transformer·剪枝
Ni-Guvara2 小时前
函数对象笔记
c++·算法
测试19982 小时前
2024软件测试面试热点问题
自动化测试·软件测试·python·测试工具·面试·职场和发展·压力测试
泉崎2 小时前
11.7比赛总结
数据结构·算法
你好helloworld2 小时前
滑动窗口最大值
数据结构·算法·leetcode
AI街潜水的八角3 小时前
基于C++的决策树C4.5机器学习算法(不调包)
c++·算法·决策树·机器学习
白榆maple3 小时前
(蓝桥杯C/C++)——基础算法(下)
算法