LeetCode每日一题:1. 两数之和

147 阅读2分钟

1. 前言

开启刷题之旅,只为了提升自己的算法能力,很多同学都问过我这个问题,毕竟,在实际工作中,我们几乎根本不可能从底层实现一遍经典算法。我在别的平台中说过,如果真的以工作内容为导向,算法还真可能对绝大部分同学来说没什么用。

但是,算法却是大厂面试考察的重点。甚至,极端一些,国外一些大厂只考算法。 所以,从今天开始,培养自己的算法思维,多从一些力扣题中找寻刷题思维。

2. 正文

今天我们从力扣1两数之和做起,看起来非常的简单,但是对于一个新手而言,能直接白板提交通过就非常棒了,这里我们先来解读下题意。

2.1 题目描述

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

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

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

2.2 示例

示例 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 <= 10^4 -10^9 <= nums[i] <= 10^9 -10^9 <= target <= 10^9 只会存在一个有效答案  

进阶:你可以想出一个时间复杂度小于 O(n^2) 的算法吗?

3. 思路分析

思路1-暴力枚举

最容易想到的解题思路其实就是暴力破解,枚举数组中的每一个数 num,寻找数组中是否存在 target-num 。

当遍历整个数组寻找 target - num 时,需要注意的是每一个位于 num 之前的元素都已经被匹配过了,因此不需要再进行匹配。而每一个元素不能被使用两次,所以我们只需要在 num 后面的元素中寻找 target - num 即可。

思路2-哈希表

思路2其实可以借助哈希表的特性,我们可以发现思路1的时间复杂度高,原因是寻找 target - num 的时间复杂度过高。因此,我们需要一种更优雅的方法,能够快速从数组中找出是否存在目标元素。如果存在,找出它的索引。

使用哈希表,优化的过程就是从寻找 target - num 的时间复杂度降低到从 O(N) 降低到 O(1)。

我们可以直接创建一个哈希表,对于每一个 num,我们首先查询哈希表中是否存在 target - num,然后将 num 插入到哈希表中,即可保证不会让 num 和自己匹配。

4. Coding

4.1 思路1代码实现

func twoSum(nums []int, target int) []int {
  var list []int
	for i := 0; i < len(nums); i++ {
		for j := i+1; j < len(nums); j++ {
			if nums[i]+nums[j] == target {
				return append(list, i, j)
			}
		}

	}
	return nil
}

4.2 思路2代码实现

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> hashMap = new HashMap<Integer, Integer>();
        for (int i = 0; i < nums.length; ++i) {
            //若存在则该key
            if (hashMap.containsKey(target - nums[i])) {
                return new int[]{hashMap.get(target - nums[i]), i};
            }
            //否则直接添加进map表中
            hashMap.put(nums[i], i);
        }
        return new int[0];
    }

}

5. 总结

5.1 思路1复杂度分析

时间复杂度:O(N^2),其中 N 是数组中的元素数量。最坏情况下数组中任意两个数都要被匹配一次。 空间复杂度:O(1)

5.2 思路2复杂度分析

时间复杂度:O(N),其中 N 是数组中的元素数量。对于每一个元素 num,我们可以 O(1) 地寻找 target - num。

空间复杂度:O(N),其中 N 是数组中的元素数量。主要为哈希表的开销。

5.3 小结

解题不能一直都依赖暴力破解,更多的是培养自己的算法思维,养成用算法思维去解决算法题,虽然暴力破解有的题都可通过,但是对自己的算法能力是么有半点提升,我们可以先用暴力破解,然后再思考优化一下,这才是刷题的正确方式,而不是为了量而不顾质量,否则这一切都是徒劳。