LeetCode Hot100 中 enumerate 函数的妙用(2026.2月版)

在刷 LeetCode Hot100 的过程中,处理数组(List)、字符串、矩阵等可迭代对象时,"同时获取索引和元素值" 是高频需求 ------ 比如找目标元素的位置、双指针遍历标记、矩阵行列定位等。Python 内置的 enumerate 函数正是用来解决这类问题的。本文结合 LeetCode Hot100 高频考题,拆解 enumerate 的核心用法、进阶技巧,以及在实际刷题中的落地场景。

一、enumerate 函数的核心基础

1. 什么是 enumerate?

enumerate 直译是 "枚举",是 Python 内置函数,核心作用是遍历可迭代对象时,同时返回元素的 "索引" 和 "值"。它底层由 C 实现,执行效率略高于手动维护索引的写法,是刷题时的首选。

2. 基础语法

python 复制代码
enumerate(iterable, start=0)
  • 参数
    • iterable:必需,可迭代对象(List、字符串、元组、矩阵等);
    • start:可选,索引起始值,默认 0(可根据题目需求设为 1、-1 等)。
  • 返回值 :枚举对象(迭代器),每次迭代返回 (索引, 元素值) 元组。

3. 告别手动索引

python 复制代码
# 传统写法
nums = [1, 3, 5, 7]
i = 0
for val in nums:
    print(f"索引 {i}:值 {val}")
    i += 1

# enumerate 写法
for idx, val in enumerate(nums):
    print(f"索引 {idx}:值 {val}")

# 自定义索引起始值(比如题目要求索引从 1 开始)
for idx, val in enumerate(nums, start=1):
    print(f"索引 {idx}:值 {val}")

二、LeetCode Hot100 中的高频应用场景

一、题目 1:两数之和(LeetCode 1,Hot100 长期在榜)

题目原文:

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那两个整数,并返回它们的数组下标。假设每种输入只会对应一个答案,数组中同一个元素在答案里不能重复出现,可按任意顺序返回答案。

传统暴力解法:

python 复制代码
class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        n=len(nums)
        for i in range(n):
            for j in range(i+1,n):
                if target == nums[i]+nums[j]:
                    return[i,j]

传统暴力解法需要两层循环(时间复杂度 O(n2)),而哈希表可以将「查找另一个数」的操作从 O(n) 降到 O(1),整体时间复杂度优化为 O(n),空间复杂度 O(n)(存储哈希表):

python 复制代码
from typing import List  # 导入List类型注解,用于指定参数和返回值类型

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        """
        给定一个整数数组 nums 和一个整数目标值 target,
        请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
        你可以假设每种输入只会对应一个答案,且同一个元素不能使用两遍。
        你可以按任意顺序返回答案。
        
        :param nums: 整数数组,存储待查找的数字
        :param target: 目标和,需要找到两个数相加等于该值
        :return: 包含两个数下标List[int],顺序无要求
        """
        # 初始化一个空字典(哈希表),用于存储「数字: 下标」的映射
        # 作用:将遍历过的数字和其下标记录下来,后续可以O(1)时间查询是否存在目标差值
        hashtable = dict()
        
        # 遍历数组,enumerate同时返回下标i和对应数字num
        for i, num in enumerate(nums):
            # 计算目标差值:target - 当前数字 = 需要找的另一个数
            complement = target - num
            
            # 检查哈希表中是否已经存在这个差值
            # 如果存在,说明之前遍历过的某个数字和当前数字相加等于target
            if complement in hashtable:
                # 返回「差值对应的下标」和「当前数字的下标」,即为答案
                return [hashtable[complement], i]
            
            # 如果不存在,将当前数字和其下标存入哈希表,供后续遍历查询
            # 注意:先检查再存入,避免同一个元素被重复使用(比如num=3, target=6时,不会匹配到自己)
            hashtable[nums[i]] = i
        
        # 题目保证有且仅有一个答案,理论上不会执行到这里,返回空列表作为兜底
        return []

核心场景:需要 "值 + 下标" 绑定且下标是答案的一部分

enumerate的核心作用:遍历数组时,既要获取元素值(计算补数target-num),又要记录该值对应的下标(最终需要返回下标作为答案)。

适用细节:

  • 题目要求返回 "满足条件的元素下标",而非元素值,因此必须把 "值" 和 "其原始下标" 绑定;
  • enumerate省去了 "手动维护下标变量i+i+=1" 的操作,且让 "值 - 下标" 的映射在循环中直接可用,避免先存所有 "值 - 下标" 再二次遍历的冗余。

二、题目 2:移动零(LeetCode 283,Hot100 高频数组题)

题目原文:

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。要求原地操作,不拷贝额外数组,尽量减少操作次数。

非enumerate解法:

python 复制代码
class Solution(object):
    def moveZeroes(self, nums):
        n=len(nums)
        left = right = 0
        while right<n:
            if nums[right]!=0:
                nums[left],nums[right]=nums[right],nums[left]
                left+=1
            right+=1

enumerate解法:

python 复制代码
class Solution(object):
    def moveZeroes(self, nums):
        slow = 0  # 慢指针:记录非零元素应存放的位置,初始为0
    # enumerate的fast_idx作为快指针,遍历数组筛选非零元素
        for fast_idx, val in enumerate(nums):
            if val != 0:  # 遇到非零元素,与慢指针位置交换并后移慢指针
                nums[slow], nums[fast_idx] = nums[fast_idx], nums[slow]
                slow += 1

核心场景:双指针遍历,快指针需同时获取 "索引 + 值" 做筛选

enumerate的核心作用:快指针遍历数组时,既要通过val判断 "是否为 0"(筛选非零元素),又要通过fast_idx(enumerate 的索引)与慢指针交换元素(原地修改数组)。

适用细节:

  • 题目要求 "原地修改数组",需要通过索引定位元素位置进行交换;
  • enumerate让快指针的 "索引(交换位置)" 和 "值(筛选条件)" 在同一循环变量中,无需单独通过nums[i]取值,逻辑更紧凑。

三、题目 3:找到字符串中所有字母异位词(LeetCode 438,Hot100 滑动窗口题)

题目原文

给定两个字符串 sp,找到 s 中所有 p字母异位词 的子串,返回这些子串的起始索引。字母异位词指由相同字母重排列形成的字符串(包括相同字符串),不考虑答案输出的顺序。

非enumerate写法:

python 复制代码
class Solution(object):
    def findAnagrams(self, s, p):
        """
        :type s: str  # 原字符串
        :type p: str  # 目标异位词的基准字符串
        :rtype: List[int]  # 返回所有异位词在s中的起始索引
        """
        # 初始化结果列表
        result = []
        # 获取p和s的长度
        len_p, len_s = len(p), len(s)
        
        # 边界条件:如果p比s长,不可能有异位词,直接返回空列表
        if len_p > len_s:
            return result
        
        # 初始化两个数组,统计26个小写字母的出现次数(ASCII码映射)
        # ord('a') = 97,所以用 ord(c) - ord('a') 得到0-25的索引
        count_p = [0] * 26
        count_window = [0] * 26
        
        # 第一步:统计p的字符计数,同时初始化滑动窗口的初始状态(前len_p个字符)
        for i in range(len_p):
            # 统计p的字符
            count_p[ord(p[i]) - ord('a')] += 1
            # 统计s前len_p个字符(初始窗口)
            count_window[ord(s[i]) - ord('a')] += 1
        
        # 检查初始窗口是否匹配
        if count_p == count_window:
            result.append(0)
        
        # 第二步:滑动窗口遍历s的剩余部分(从len_p到len_s-1)
        # 窗口起始索引从1开始,结束索引从len_p开始
        for right in range(len_p, len_s):
            # 移出窗口左侧的字符(窗口起始索引是 right - len_p)
            left_char = s[right - len_p]
            count_window[ord(left_char) - ord('a')] -= 1
            
            # 移入窗口右侧的新字符
            right_char = s[right]
            count_window[ord(right_char) - ord('a')] += 1
            
            # 检查当前窗口是否匹配p的字符计数
            if count_p == count_window:
                # 记录当前窗口的起始索引
                result.append(right - len_p + 1)
        
        return result

enumerate写法:

python 复制代码
class Solution(object):
    def findAnagrams(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: List[int]
        """
        result = []
        len_p, len_s = len(p), len(s)
        
        # 边界条件:p比s长直接返回空
        if len_p > len_s:
            return result
        
        # 初始化26字母计数数组
        count_p = [0] * 26
        count_window = [0] * 26
        
        # 第一步:统计p的字符,同时初始化窗口前len_p个字符(用enumerate遍历)
        # 遍历p的字符,统计计数
        for idx, char in enumerate(p):
            count_p[ord(char) - ord('a')] += 1
        # 遍历s前len_p个字符,初始化窗口(用enumerate更清晰)
        for idx, char in enumerate(s[:len_p]):
            count_window[ord(char) - ord('a')] += 1
        
        # 检查初始窗口是否匹配
        if count_p == count_window:
            result.append(0)
        
        # 第二步:滑动窗口(用enumerate遍历s中从len_p开始的部分)
        # 遍历的是s[len_p:],enumerate的start参数指定索引从len_p开始(对应原s的索引)
        for right_idx, right_char in enumerate(s[len_p:], start=len_p):
            # 计算要移出窗口的左侧字符的索引
            left_idx = right_idx - len_p
            left_char = s[left_idx]
            
            # 移出左侧字符:计数-1
            count_window[ord(left_char) - ord('a')] -= 1
            # 移入右侧新字符:计数+1
            count_window[ord(right_char) - ord('a')] += 1
            
            # 检查当前窗口是否匹配,匹配则记录起始索引(left_idx + 1)
            if count_p == count_window:
                result.append(left_idx + 1)
        
        return result

核心场景:滑动窗口遍历,需索引计算窗口边界 + 值维护窗口状态

enumerate的核心作用:遍历字符串时,既要通过char(值)更新窗口字符计数,又要通过idx(索引)计算窗口左边界(idx - p_len + 1)、判断窗口长度是否达标。

适用细节:

  • 题目要求返回 "异位词子串的起始索引",需要通过索引定位窗口位置;
  • enumerate让 "当前字符" 和 "当前位置" 直接绑定,避免手动计算索引时的错位(比如窗口左边界计算错误)。

四、题目4:矩阵置零(LeetCode 73)

题目原文

给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用 原地 算法。

进阶:能否使用 O (1) 额外空间?

非enumerate解法:

python 复制代码
class Solution(object):
    def setZeroes(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: None Do not return anything, modify matrix in-place instead.
        """
            # 初始化两个集合,分别存储需要置零的行和列
        rows = set()
        cols = set()
    
    # 第一步:遍历矩阵,标记需要置零的行和列
        m = len(matrix)       # 矩阵的行数
        if m == 0:
            return
        n = len(matrix[0])    # 矩阵的列数
    
        for i in range(m):
            for j in range(n):
                if matrix[i][j] == 0:
                    rows.add(i)
                    cols.add(j)
    
    # 第二步:根据标记的行和列,将对应位置置零
        for i in range(m):
            for j in range(n):
                if i in rows or j in cols:
                    matrix[i][j] = 0

enumerate解法:

python 复制代码
class Solution(object):
    def setZeroes(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: None Do not return anything, modify matrix in-place instead.
        """
        # 初始化两个集合,分别存储需要置零的行和列
        rows = set()
        cols = set()
    
        # 第一步:遍历矩阵,用enumerate获取行索引+行数据,标记需要置零的行和列
        # 外层enumerate:i是行索引,row是当前行的所有元素
        for i, row in enumerate(matrix):
            # 内层enumerate:j是列索引,val是当前位置的元素值
            for j, val in enumerate(row):
                if val == 0:
                    rows.add(i)   # 标记需要置零的行
                    cols.add(j)   # 标记需要置零的列
    
        # 第二步:再次遍历矩阵,根据标记置零(同样用enumerate)
        for i, row in enumerate(matrix):
            for j, _ in enumerate(row):  # 只需要列索引j,元素值用_占位即可
                if i in rows or j in cols:
                    matrix[i][j] = 0
  • 遍历需同时用 "索引 + 值"

    • 外层enumerate(matrix)i是行索引(用于标记首列matrix[i][0]),row是行元素(用于内层遍历);

    • 内层enumerate(row)j是列索引(用于标记首行matrix[0][j]),val是元素值(判断是否为 0);两者缺一不可,完全符合 "要值也要索引" 的核心场景。

  • 原地修改依赖索引定位 :题目要求 "原地算法",置零操作需要通过行索引i、列索引j精准定位元素位置(如matrix[i][j] = 0),enumerate省去了手动维护i/j自增的麻烦。

三、enumerate 进阶技巧

1. 与列表推导式结合:一行生成 "值 - 索引" 映射

刷题中常需要快速查找元素的位置,用 enumerate + 字典推导式可一键生成映射表:

python 复制代码
# 生成"元素值: 作为字典的"键"(适用于无重复元素的数组)
nums = [2, 7, 11, 15]
# 字典推导式 + enumerate:键是元素值,值是对应索引
val2idx = {val: idx for idx, val in enumerate(nums)}
print(val2idx[7])  # 输出:1(快速找到7的索引)

适用场景:Hot100 两数之和(快速通过值找索引,时间复杂度从 O (n²) 降为 O (n))。

2. 转换为列表:查看枚举结果(调试 / 验证用)

enumerate 返回的是迭代器,只能遍历一次;若需多次使用,可转为列表:

python 复制代码
nums = [10, 20, 30]
# 将枚举对象转为列表,方便查看所有(索引,值)对
enum_list = list(enumerate(nums))
print(enum_list)  # 输出:[(0, 10), (1, 20), (2, 30)]

3. 自定义 start:适配题目索引要求

部分题目要求索引从 1 开始(如 "第 k 个元素"),只需设置 start=1

python 复制代码
nums = [5, 3, 8]
# start=1 让索引从1开始,符合题目"第k个元素"的表述习惯
for idx, val in enumerate(nums, start=1):
    print(f"第 {idx} 个元素:{val}")  # 输出:第1个元素:5,第2个元素:3...

四、使用 enumerate 的注意事项

  1. 索引是 "遍历顺序" 而非 "原数组实际索引" :若遍历的是切片 / 过滤后的数组,索引是相对索引,而非原数组索引:

    python 复制代码
    nums = [1, 2, 3, 4]
    # 遍历切片 nums[2:](元素是3、4),enumerate 的索引从0开始,而非原数组的2
    for idx, val in enumerate(nums[2:]):
        print(idx, val)  # 输出:0 3;1 4
  2. 不要遍历中修改原对象:与普通 for 循环同理,遍历 List / 矩阵时增删元素,会导致枚举异常;

  3. 多维数组注意索引层级 :嵌套 enumerate 时,外层 i 是行索引,内层 j 是列索引,避免混淆。

相关推荐
毕设源码-赖学姐9 小时前
【开题答辩全过程】以 基于python的电影推荐系统为例,包含答辩的问题和答案
开发语言·python
敲键盘的生活9 小时前
MoneyPrinter重构之一:用nicegui调用大模型生成视频文案
python·重构·aigc·ai编程·ai写作
小邓睡不饱耶9 小时前
2026 CSDN榜单封神!3大热门技术+5个大厂案例,新手也能直接抄作业
python·ai
墨有6669 小时前
哈希表从入门到实现,一篇吃透!
数据结构·算法·哈希算法
南极星10059 小时前
我的创作纪念日--128天
java·python·opencv·职场和发展
码界筑梦坊9 小时前
327-基于Django的兰州空气质量大数据可视化分析系统
python·信息可视化·数据分析·django·毕业设计·数据可视化
Highcharts.js9 小时前
如何使用Highcharts SVG渲染器?
开发语言·javascript·python·svg·highcharts·渲染器
We་ct9 小时前
LeetCode 228. 汇总区间:解题思路+代码详解
前端·算法·leetcode·typescript
AIpanda8889 小时前
如何借助AI销冠系统提升数字员工在销售中的成效?
算法