参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

## 1. 两数之和 [力扣题目链接](https://leetcode-cn.com/problems/two-sum/) 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。 **示例:** 给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1] ## 思路 很明显暴力的解法是两层for循环查找,时间复杂度是$O(n^2)$。 建议大家做这道题目之前,先做一下这两道 * [242. 有效的字母异位词](https://www.programmercarl.com/0242.有效的字母异位词.html) * [349. 两个数组的交集](https://www.programmercarl.com/0349.两个数组的交集.html) [242. 有效的字母异位词](https://www.programmercarl.com/0242.有效的字母异位词.html) 这道题目是用数组作为哈希表来解决哈希问题,[349. 两个数组的交集](https://www.programmercarl.com/0349.两个数组的交集.html)这道题目是通过set作为哈希表来解决哈希问题。 本题呢,则要使用map,那么来看一下使用数组和set来做哈希法的局限。 * 数组的大小是受限制的,而且如果元素很少,而哈希值太大会造成内存空间的浪费。 * set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,不仅要判断y是否存在而且还要记录y的下标位置,因为要返回x 和 y的下标。所以set 也不能用。 此时就要选择另一种数据结构:map ,map是一种key value的存储结构,可以用key保存数值,用value在保存数值所在的下标。 C++中map,有三种类型: |映射 |底层实现 | 是否有序 |数值是否可以重复 | 能否更改数值|查询效率 |增删效率| |---|---| --- |---| --- | --- | ---| |std::map |红黑树 |key有序 |key不可重复 |key不可修改 | $O(\log n)$|$O(\log n)$ | |std::multimap | 红黑树|key有序 | key可重复 | key不可修改|$O(\log n)$ |$O(\log n)$ | |std::unordered_map |哈希表 | key无序 |key不可重复 |key不可修改 |$O(1)$ | $O(1)$| std::unordered_map 底层实现为哈希表,std::map 和std::multimap 的底层实现是红黑树。 同理,std::map 和std::multimap 的key也是有序的(这个问题也经常作为面试题,考察对语言容器底层的理解)。 更多哈希表的理论知识请看[关于哈希表,你该了解这些!](https://www.programmercarl.com/哈希表理论基础.html)。 **这道题目中并不需要key有序,选择std::unordered_map 效率更高!** 解题思路动画如下: ![](https://code-thinking.cdn.bcebos.com/gifs/1.两数之和.gif) C++代码: ```CPP class Solution { public: vector twoSum(vector& nums, int target) { std::unordered_map map; for(int i = 0; i < nums.size(); i++) { auto iter = map.find(target - nums[i]); if(iter != map.end()) { return {iter->second, i}; } map.insert(pair(nums[i], i)); } return {}; } }; ``` ## 其他语言版本 Java: ```java public int[] twoSum(int[] nums, int target) { int[] res = new int[2]; if(nums == null || nums.length == 0){ return res; } Map map = new HashMap<>(); for(int i = 0; i < nums.length; i++){ int temp = target - nums[i]; if(map.containsKey(temp)){ res[1] = i; res[0] = map.get(temp); } map.put(nums[i], i); } return res; } ``` Python: ```python class Solution: def twoSum(self, nums: List[int], target: int) -> List[int]: records = dict() # 用枚举更方便,就不需要通过索引再去取当前位置的值 for idx, val in enumerate(nums): if target - val not in records: records[val] = idx else: return [records[target - val], idx] # 如果存在就返回字典记录索引和当前索引 ``` Go: ```go func twoSum(nums []int, target int) []int { for k1, _ := range nums { for k2 := k1 + 1; k2 < len(nums); k2++ { if target == nums[k1] + nums[k2] { return []int{k1, k2} } } } return []int{} } ``` ```go // 使用map方式解题,降低时间复杂度 func twoSum(nums []int, target int) []int { m := make(map[int]int) for index, val := range nums { if preIndex, ok := m[target-val]; ok { return []int{preIndex, index} } else { m[val] = index } } return []int{} } ``` Rust ```rust use std::collections::HashMap; impl Solution { pub fn two_sum(nums: Vec, target: i32) -> Vec { let mut map = HashMap::with_capacity(nums.len()); for i in 0..nums.len() { if let Some(k) = map.get(&(target - nums[i])) { if *k != i { return vec![*k as i32, i as i32]; } } map.insert(nums[i], i); } panic!("not found") } } ``` Javascript ```javascript var twoSum = function (nums, target) { let hash = {}; for (let i = 0; i < nums.length; i++) { if (hash[target - nums[i]] !== undefined) { return [i, hash[target - nums[i]]]; } hash[nums[i]] = i; } return []; }; ``` TypeScript: ```typescript function twoSum(nums: number[], target: number): number[] { let helperMap: Map = new Map(); let index: number | undefined; let resArr: number[] = []; for (let i = 0, length = nums.length; i < length; i++) { index = helperMap.get(target - nums[i]); if (index !== undefined) { resArr = [i, index]; } helperMap.set(nums[i], i); } return resArr; }; ``` php ```php function twoSum(array $nums, int $target): array { for ($i = 0; $i < count($nums);$i++) { // 计算剩下的数 $residue = $target - $nums[$i]; // 匹配的index,有则返回index, 无则返回false $match_index = array_search($residue, $nums); if ($match_index !== false && $match_index != $i) { return array($i, $match_index); } } return []; } ``` Swift: ```swift func twoSum(_ nums: [Int], _ target: Int) -> [Int] { // 值: 下标 var map = [Int: Int]() for (i, e) in nums.enumerated() { if let v = map[target - e] { return [v, i] } else { map[e] = i } } return [] } ``` PHP: ```php class Solution { /** * @param Integer[] $nums * @param Integer $target * @return Integer[] */ function twoSum($nums, $target) { if (count($nums) == 0) { return []; } $table = []; for ($i = 0; $i < count($nums); $i++) { $temp = $target - $nums[$i]; if (isset($table[$temp])) { return [$table[$temp], $i]; } $table[$nums[$i]] = $i; } return []; } } ``` -----------------------