加载中...
1-两数之和(Two Sum)
发表于:2021-12-03 | 分类: 简单
字数统计: 323 | 阅读时长: 1分钟 | 阅读量:

原文链接: https://leetcode-cn.com/problems/two-sum

英文原文

Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

You can return the answer in any order.

 

Example 1:

Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Output: Because nums[0] + nums[1] == 9, we return [0, 1].

Example 2:

Input: nums = [3,2,4], target = 6
Output: [1,2]

Example 3:

Input: nums = [3,3], target = 6
Output: [0,1]

 

Constraints:

  • 2 <= nums.length <= 104
  • -109 <= nums[i] <= 109
  • -109 <= target <= 109
  • Only one valid answer exists.

 

Follow-up: Can you come up with an algorithm that is less than O(n2time complexity?

中文题目

给定一个整数数组 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
  • 只会存在一个有效答案

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

通过代码

高赞题解

📺 视频题解

1.两数之和.mp4

📖 文字题解

方法一:暴力枚举

思路及算法

最容易想到的方法是枚举数组中的每一个数 x,寻找数组中是否存在 target - x

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

代码

[sol1-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]; } }
[sol1-C++]
class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { int n = nums.size(); for (int i = 0; i < n; ++i) { for (int j = i + 1; j < n; ++j) { if (nums[i] + nums[j] == target) { return {i, j}; } } } return {}; } };
[sol1-C]
int* twoSum(int* nums, int numsSize, int target, int* returnSize) { for (int i = 0; i < numsSize; ++i) { for (int j = i + 1; j < numsSize; ++j) { if (nums[i] + nums[j] == target) { int* ret = malloc(sizeof(int) * 2); ret[0] = i, ret[1] = j; *returnSize = 2; return ret; } } } *returnSize = 0; return NULL; }
[sol1-Python3]
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 []
[sol1-Golang]
func twoSum(nums []int, target int) []int { for i, x := range nums { for j := i + 1; j < len(nums); j++ { if x+nums[j] == target { return []int{i, j} } } } return nil }

复杂度分析

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

  • 空间复杂度:$O(1)$。

方法二:哈希表

思路及算法

注意到方法一的时间复杂度较高的原因是寻找 target - x 的时间复杂度过高。因此,我们需要一种更优秀的方法,能够快速寻找数组中是否存在目标元素。如果存在,我们需要找出它的索引。

使用哈希表,可以将寻找 target - x 的时间复杂度降低到从 $O(N)$ 降低到 $O(1)$。

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

代码

[sol2-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]; } }
[sol2-C++]
class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { unordered_map<int, int> hashtable; for (int i = 0; i < nums.size(); ++i) { auto it = hashtable.find(target - nums[i]); if (it != hashtable.end()) { return {it->second, i}; } hashtable[nums[i]] = i; } return {}; } };
[sol2-C]
struct hashTable { int key; int val; UT_hash_handle hh; }; struct hashTable* hashtable; struct hashTable* find(int ikey) { struct hashTable* tmp; HASH_FIND_INT(hashtable, &ikey, tmp); return tmp; } void insert(int ikey, int ival) { struct hashTable* it = find(ikey); if (it == NULL) { struct hashTable* tmp = malloc(sizeof(struct hashTable)); tmp->key = ikey, tmp->val = ival; HASH_ADD_INT(hashtable, key, tmp); } else { it->val = ival; } } int* twoSum(int* nums, int numsSize, int target, int* returnSize) { hashtable = NULL; for (int i = 0; i < numsSize; i++) { struct hashTable* it = find(target - nums[i]); if (it != NULL) { int* ret = malloc(sizeof(int) * 2); ret[0] = it->val, ret[1] = i; *returnSize = 2; return ret; } insert(nums[i], i); } *returnSize = 0; return NULL; }
[sol2-Python3]
class Solution: def twoSum(self, nums: List[int], target: int) -> List[int]: hashtable = dict() for i, num in enumerate(nums): if target - num in hashtable: return [hashtable[target - num], i] hashtable[nums[i]] = i return []
[sol2-Golang]
func twoSum(nums []int, target int) []int { hashTable := map[int]int{} for i, x := range nums { if p, ok := hashTable[target-x]; ok { return []int{p, i} } hashTable[x] = i } return nil }

复杂度分析

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

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

统计信息

通过次数 提交次数 AC比率
2735230 5240831 52.2%

提交历史

提交时间 提交结果 执行时间 内存消耗 语言

相似题目

题目 难度
三数之和 中等
四数之和 中等
两数之和 II - 输入有序数组 简单
两数之和 III - 数据结构设计 简单
和为 K 的子数组 中等
两数之和 IV - 输入 BST 简单
小于 K 的两数之和 简单
下一篇:
2-两数相加(Add Two Numbers)
本文目录
本文目录