1.两数之和(Two Sum)E
英文题目
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9, Because nums[0] + nums[1] = 2 + 7 = 9, return [0, 1].
中文题目
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1]
暴力解法
直接枚举数组中的每一个数 num,寻找数组中 num 后面的元素是否存在 target-num
时间复杂度O(n^2),空间复杂度O(1)
# python: 时间 2668 ms, 击败 33.69%; 内存 16.8 MB, 击败 36.80% class Solution: def twoSum(self, nums: List[int], target: int) -> List[int]: n = len(nums) for i in range(n): for j in range(i+1, n): if nums[i] + nums[j] == target: return [i, j] return []
// C++: 时间 304 ms, 击败 24.16%; 内存 10 MB, 击败 63.62% class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { for (int i = 0; i < nums.size(); ++i) { for (int j = i+1; j < nums.size(); ++j) { if (nums[i] + nums[j] == target) { return {i, j}; } } } return {}; } };
// java: 时间 54 ms, 击败 26.90%; 内存 42.6 MB, 击败 28.40% class Solution { public int[] twoSum(int[] nums, int target) { for (int i = 0; i < nums.length; ++i) { for (int j = i+1; j < nums.length; ++j) { if (nums[i] + nums[j] == target) { return new int[]{i, j}; } } } return new int[0]; } }
// go: 时间 20 ms, 击败 27.87%; 内存 3.5 MB, 击败 99.24% func twoSum(nums []int, target int) []int { for i, _ := range nums { for j := i+1; j < len(nums); j++ { // 注意go没有++j的写法 if nums[i] + nums[j] == target { return []int{i, j} } } // 注意,下面不能这样用range,因为会重置j的索引 // 如i=1时,nums[2]的对应索引 j=0 // for j, _ := range nums[i+1:] { // if nums[i] + nums[j] == target { // return []int{i, j} // } // } } return []int{} }
// rust: 时间 28 ms, 击败 23.92%; 内存 2.16 MB, 击败 78.25% impl Solution { pub fn two_sum(nums: Vec<i32>, target: i32) -> Vec<i32> { for i in 0..nums.len() { for j in i+1..nums.len() { if nums[i] + nums[j] == target { return vec![i as i32, j as i32]; } } } vec![] } }
// javascript: 时间 112 ms, 击败 27.51%; 内存 41.4 MB, 击败 68.65% /** * @param {number[]} nums * @param {number} target * @return {number[]} */ var twoSum = function(nums, target) { for (let i = 0; i < nums.length; ++i) { for (let j = i+1; j < nums.length; ++j) { if (nums[i] + nums[j] == target) { return [i, j]; } } } return []; };
// typescript: 时间 128 ms, 击败 16.08%; 内存 50.87 MB, 击败 9.04% function twoSum(nums: number[], target: number): number[] { for (let i = 0; i < nums.length; ++i) { for (let j = i+1; j < nums.length; ++j) { if (nums[i] + nums[j] == target) { return [i, j]; } } } return []; };
// scala: 时间 580 ms, 击败 46.58%; 内存 55.56 MB, 击败 46.57% object Solution { def twoSum(nums: Array[Int], target: Int): Array[Int] = { for (i <- nums.indices; j <- i + 1 until nums.length) { if (nums(i) + nums(j) == target) { return Array(i, j) } } Array() } }
一次哈希
使用哈希表,对每一个 num,先查询哈希表中是否存在 target - num,若存在,返回结果,若不存在,将 key=num,value=index 插入哈希表中
时间复杂度O(n),空间复杂度O(n),这里n是哈希表的开销
# python: 时间 40 ms, 击败 86.10%; 内存 17.5 MB, 击败 5.11% class Solution: def twoSum(self, nums: List[int], target: int) -> List[int]: numDict = {} for i, num in enumerate(nums): if target - num in numDict: return [i, numDict[target - num]] numDict[num] = i return []
// C++: 时间 4 ms, 击败 99.31%; 内存 10.6 MB, 击败 26.78% class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { unordered_map<int, int> numDict; for (int i = 0; i < nums.size(); ++i) { auto mit = numDict.find(target - nums[i]); if (mit != numDict.end()) { return {i, mit->second}; } numDict[nums[i]] = i; } return {}; } };
// java: 时间 1 ms, 击败 98.17%; 内存 42.2 MB, 击败 47.86% class Solution { public int[] twoSum(int[] nums, int target) { Map<Integer, Integer> numDict = new HashMap<>(); for (int i = 0; i < nums.length; ++i) { if (numDict.containsKey(target - nums[i])) { return new int[]{i, numDict.get(target - nums[i])}; } numDict.put(nums[i], i); } return new int[0]; } }
// go: 时间 4 ms, 击败 95.47%; 内存 4.1 MB, 击败 44.28% func twoSum(nums []int, target int) []int { numDict := map[int]int{} for i, num := range nums { if j, ok := numDict[target - num]; ok { return []int{i, j} } numDict[num] = i } return []int{} }
// rust: 时间 0 ms, 击败 100%; 内存 2.15 MB, 击败 78.59% use std::collections::HashMap; impl Solution { pub fn two_sum(nums: Vec<i32>, target: i32) -> Vec<i32> { let mut numDict = HashMap::with_capacity(nums.len()); for (i, &num) in nums.iter().enumerate() { if let Some(&j) = numDict.get(&(target - num)) { return vec![i as i32, j]; } numDict.insert(num, i as i32); } vec![] } }
// javascript: 时间 72 ms, 击败 60.99%; 内存 42.2 MB, 击败 36.23% /** * @param {number[]} nums * @param {number} target * @return {number[]} */ var twoSum = function(nums, target) { const numDict = new Map(); for (let i = 0; i < nums.length; ++i) { if (numDict.has(target - nums[i])) { return [i, numDict.get(target - nums[i])]; } numDict.set(nums[i], i); } return []; };
// typescript: 时间 100 ms, 击败 31.45%; 内存 51.14 MB, 击败 7.86% function twoSum(nums: number[], target: number): number[] { const numDict: Record<number, number> = {}; for (let i = 0; i < nums.length; ++i) { if (target - nums[i] in numDict) { return [i, numDict[target - nums[i]]]; } numDict[nums[i]] = i; } return []; };
// scala: 时间 512 ms, 击败 97.26%; 内存 55.53 MB, 击败 50.86% object Solution { def twoSum(nums: Array[Int], target: Int): Array[Int] = { val numDict = scala.collection.mutable.Map[Int, Int]() for (i <- nums.indices) { val num = nums(i) numDict.get(target - num) match { case Some(j) => return Array(j, i) case None => numDict(num) = i } } Array() } }