两数之和
两数之和
题目来源
解题思路
方法一:暴力破解
个人解
关键点:用两层循环进行解题
代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
result = []
loop = False
for i, num in enumerate(nums):
for j, v in enumerate(nums):
if i != j:
if num + v == target:
result.append(i)
result.append(j)
loop = True
break
if loop:
break
return result1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20func twoSum(nums []int, target int) []int {
resultSlice := make([]int, 0, 2)
Loop:
// 1. 循环遍历 nums
for i, num := range nums {
// 2. 循环遍历 nums
for j, v := range nums {
// 3. 判断元素是否重复
if i != j {
// 4. 两数之和等于目标值
if num + v == target {
resultSlice = append(resultSlice, i)
resultSlice = append(resultSlice, j)
break Loop
}
}
}
}
return resultSlice
}个人总结:
- Python3 版本提交结果 ✅ ,执行用时 6524 ms,内存消耗 15.5 MB。
- Golang 版本提交结果 ✅ ,执行用时 48 ms,内存消耗 3.4 MB。
- 可改进点:第二次遍历的时候,应该从 i + 1 元素开始。
官方解
关键点:
- 最容易想到的方法是枚举数组中的每一个数 x ,寻找数组中是否存在 target - x 。
- 当我们使用遍历整个数组的方式寻找 target - x 时,需要注意到每一个位于 x 之前的元素都已经和 x 匹配过,因此不需要再进行匹配。
- 而每一个元素不能被使用两次,所以我们只需要在 x 后面的元素中寻找 target - x 。
代码实现
1
2
3
4
5
6
7
8class 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 []1
2
3
4
5
6
7
8
9
10func 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)。
方法二:哈希表
个人解
关键点:用哈希表进行解题
代码实现
1
2
3
4
5
6
7
8
9class 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] # 如果存在就返回字典记录索引和当前索引1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19func twoSum(nums []int, target int) []int {
resultSlice := make([]int, 0, 2)
sliceMap := make(map[int]int)
for i, num := range nums {
sliceMap[num] = i
}
for j, v := range nums {
if _, ok := sliceMap[target - v]; ok {
if j == sliceMap[target - v] {
continue
}
resultSlice = append(resultSlice, j)
resultSlice = append(resultSlice, sliceMap[target - v])
break
}
continue
}
return resultSlice
}个人总结:
- Python3 版本提交结果 ✅ ,执行用时 28 ms,内存消耗 16 MB。
- Golang 版本提交结果 ✅ ,执行用时 8 ms,内存消耗 5.4 MB。
- 可改进点:哈希表添加元素和匹配可以同时进行。
官方解
关键点:
- 注意到方法一的时间复杂度较高的原因是寻找 target - x 的时间复杂度过高。
- 因此,我们需要一种更优秀的方法,能够快速寻找数组中是否存在目标元素。如果存在,我们需要找出它的索引。
- 使用哈希表,可以将寻找 target - x 的时间复杂度降低到从 O(N^2) 降低到 O(1)。
- 这样我们创建一个哈希表,对于每一个 x ,我们首先查询哈希表中是否存在 target - x ,然后将 x 插入到哈希表中,即可保证不会让 x 和自己匹配。
代码实现
1
2
3
4
5
6
7
8class 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 []1
2
3
4
5
6
7
8
9
10func 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 是数组中的元素数量。主要为哈希表的开销。
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Comment
TwikooGitalk