1、两数之和
题目描述
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标
题目分析与实现
难度:【简单】
数据结构:数组
基本实现方法:
- 暴力枚举法
- 双指针法
- 哈希表法等
实现一:暴力枚举
- 枚举数组中的每一个数
x
,寻找数组中是否存在target - x
- 每一个元素不能被使用两次,所以只需要在
x
后面的元素中寻找target - x
# Use Python to solve
def two_sum(nums: List[int], target:int) -> List[int]:
'''
使用暴力枚举法求两数之和
参数:
nums (list[int]): 包含整数的列表
target(int): 目标和
返回值:
list[int]: 包含两个索引的列表,这两个索引对应的元素之和等于目标和target如果没有找到符合条件的索引对,返回空列表[]
'''
arr_length = len(nums)
if not nums or arr_length < 2:
return []
# 使用暴力枚举法来一一确认符合条件的元素索引
for i in range(arr_length):
for j in range(i + 1, arr_length):
if nums[i] = target - nums[j]
return [i, j]
时间复杂度分析:
- 最好情况:如果在第一次遍历中就找到了符合条件的索引对,则时间复杂度为 O ( 1 ) O(1) O(1)
- 最坏情况:如果没有找到符合条件的索引对,需要完整地遍历两层循环,时间复杂度为
O
(
n
2
)
O(n^2)
O(n2),其中n是
nums
列表的长度 - 平均情况:平均情况下,需要遍历两层循环,时间复杂度为 O ( n 2 ) O(n^2) O(n2)
空间复杂度分析:
- 没有使用额外的空间,只使用了常数级别的变量存储数据,所以空间复杂度: O ( 1 ) O(1) O(1)
实现二:双指针法
- 创建一个列表(List)按元组方式存放数组的值和索引,并对其进行排序(按值)
- 定义左右指针,当左指针小于右指针时,进行循环判断
- 如果左右指针值的和等于目标值,则将其索引添加到一个新列表当中(num_list)
# Use Python to solve
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
'''
使用双指针方法解决两数之和
参数:
nums (list[int]): 整数数组
target(int): 目标值
返回值:
nums_list(list[int]): 和为目标值的两个整数的数组下标
'''
arr_length = len(nums)
if not nums or arr_length < 2:
return []
# 存放最终结果
num_list = []
# 创建一个列表按(num, index)格式存放
nums_with_index = [(num, index) for index, num in enumerate(nums)]
# 对nums_with_index按照数字大小进行排序
nums_with_index.sort()
# 定义左右两个指针
left, right = 0, arr_length - 1
# 当左指针小于右指针时,进行循环
while left < right:
# 如果左指针和右指针所指数字的和等于目标值
if nums_with_index[left][0] + nums_with_index[right][0] == target:
num_list.append(nums_with_index[left][1])
num_list.append(nums_with_index[right][1])
break
# 如果左指针和右指针所指数字的和小于目标值
elif nums_with_index[left][0] + nums_with_index[right][0] < target:
# 左指针右移
left += 1
else:
# 右指针左移
right -= 1
return num_list
时间复杂度分析:
- 最好情况:如果在第一次循环中就找到了符合条件的数字对,时间复杂度为 O ( 1 ) O(1) O(1)
- 最坏情况:如果没有找到符合条件的数字对,需要遍历整个列表,时间复杂度为
O
(
n
)
O(n)
O(n),其中n是列表
nums_with_index
的长度 - 平均情况:平均情况下,需要遍历整个列表,时间复杂度为 O ( n ) O(n) O(n)
空间复杂度分析:
- 创建了额外空间:
nums_with_index
,所以空间复杂度均为 O ( n ) O(n) O(n)
实现三:哈希表
- 为数组创建一个哈希表
- 对于每一个
x
,我们首先查询哈希表中是否存在target - x
,然后将x
插入到哈希表中,即可保证不会让x
和自己匹配
# Use Python to solve
def two_sum(nums: List[int], target: int) -> List[int]:
'''
使用哈希表方法解决两数之和问题
参数:
nums (list[int]): 包含整数的列表
target (int): 目标和值
返回值:
List[int]: 包含两个索引的列表,这两个索引对应的元素之和等于目标和target如果没有找到符合条件的索引对,返回空列表[]
'''
arr_length = len(nums)
if not nums or arr_length < 2:
return []
nums_map = {} # 创建一个空的哈希表,用于存储数字和索引的映射关系
for i, num in enumerate(nums): # 遍历列表,同时获取数字的索引
if target - num in nums_map: # 如果target - num在哈希表中存在,说明之前出现过一个数字与当前num之和等于target
return [nums_map[target - num], i] # 返回之前记录的索引和当前索引
nums_map[num] = i # 将当前数字和索引添加到哈希表中
return [] # 如果没有找到符合条件的索引对,返回空列表[]
时间复杂度分析:
- 最好情况:如果在遍历列表时的第一个元素就找到了符合条件的数字对,时间复杂度为 O ( 1 ) O(1) O(1)
- 最坏情况:如果没有找到符合条件的数字对,需要完整地遍历整个列表,时间复杂度为
O
(
n
)
O(n)
O(n),其中n是列表
nums
的长度 - 平均情况:平均情况下,需要遍历整个列表,时间复杂度为 O ( n ) O(n) O(n)
空间复杂度分析:
- O ( n ) O(n) O(n)