【用python解LeetCode 热题100】【哈希】1、两数之和

一、题目描述:

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那两个整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素,比如[3,3]找和为6,不能返回结果[0,0]。
你可以按任意顺序返回答案。

示例 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
只会存在一个有效答案

解法1:暴力解法

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        goat_list = []
        for i in range(len(nums)):
            if target - nums[i] in nums[i+1:]:
                goat_list.append(i)
                goat_list.append(nums[i+1:].index(target - nums[i]) + (i + 1))#使用index函数时注意对象是切片数组,而不是原数组!
        return goat_list

解法2: 哈希表

思路:
1、创建哈希表(在python里也就是创建一个空字典)
2、从头到尾遍历数组
3、获取目标值减去遍历到的值(也就是补数)
4、如果补数不在哈希表里(not in字典里),则存放已经遍历的值和它的下标{遍历的值1:下标i1,… …};如果补数在哈希表里,则输出[补数下标,遍历到的值的下标]

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        hash_table = {}
        for i, num in enumerate(nums):
            if target - num in hash_table:
                return [i, hash_table[target - num]] 
                break
            else:
                hash_table[nums[i]] = i

二、补充知识点:

1、哈希表的英文‌
‌Hash Table‌(标准术语),有时也称作:
‌Hash Map‌(如Java中的HashMap)
‌Dictionary‌(如Python中的dict类型)

2、enumerate函数
是 Python 中一个非常实用的内置函数,用于在循环中同时获取元素的索引和值。

  1. 核心功能
    作用:为可迭代对象(如列表、元组、字符串等)添加索引,生成 (索引, 元素) 元组序列。
    语法:
    enumerate(iterable, start=0)
    iterable: 需要遍历的对象(如列表、字符串等)
    start (可选): 索引的起始值,默认为 0。
  2. 返回值类型
    返回一个 枚举对象(enumerate 对象),本质是一个迭代器。
    迭代器特性:惰性求值,不一次性生成所有数据,节省内存。
  3. 时间复杂度
    时间复杂度:O(n),与直接遍历可迭代对象相同。
    空间复杂度:O(1),迭代器本身不存储所有数据,仅在遍历时动态生成元组。
  4. 使用场景
# 场景 1:需要同时访问索引和元素
fruits = ["apple", "banana", "cherry"]
for index, fruit in enumerate(fruits):
    print(f"Index {index}: {fruit}")
# 输出:
# Index 0: apple
# Index 1: banana
# Index 2: cherry
# 场景 2:自定义索引起始值
for idx, char in enumerate("python", start=1):
    print(f"Position {idx}: {char}")
# 输出:
# Position 1: p
# Position 2: y
# Position 3: t
# Position 4: h
# Position 5: o
# Position 6: n
# 场景 3:结合条件判断快速定位元素
# 查找列表中第一个偶数的索引
numbers = [1, 3, 5, 8, 9]
for i, num in enumerate(numbers):
    if num % 2 == 0:
        print(f"First even number at index {i}")
        break
# 输出:First even number at index 3
  1. 与 range(len()) 的对比
    方法 可读性 内存效率 适用场景
    enumerate() 高 高 需要同时访问索引和元素
    range(len()) 低 中 仅需索引,不关心元素值
    示例对比:
# 使用 enumerate()
for i, num in enumerate(nums):
    print(i, num)

# 使用 range(len())
for i in range(len(nums)):
    print(i, nums[i])
  1. 底层实现原理
    enumerate 的等效 Python 伪代码实现:
def enumerate(sequence, start=0):
    n = start
    for elem in sequence:
        yield n, elem
        n += 1

通过生成器 (yield) 动态生成索引和元素的元组。
7. 常见问题
问题 1:enumerate() 能否用于字典?
可以,但遍历的是字典的键:

d = {"a": 1, "b": 2}
for i, key in enumerate(d):
    print(i, key, d[key])
# 输出:
# 0 a 1
# 1 b 2

问题 2:如何将 enumerate() 结果转为列表?
使用 list() 转换:

lst = list(enumerate(["a", "b", "c"]))
print(lst)  
# 输出:[(0, 'a'), (1, 'b'), (2, 'c')]
  1. 最佳实践
    优先使用 enumerate:替代 range(len()),代码更简洁且不易出错。
    避免不必要的转换:直接遍历 enumerate 对象,而非转换为列表。
    灵活使用 start 参数:处理非零起始索引的需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值