返回顶部
分享到

Python中enumerate函数的巧妙用法

python 来源:互联网 作者:佚名 发布时间:2026-02-13 20:10:25 人浏览
摘要

在算法题目中,处理数组(List)、字符串、矩阵等可迭代对象时,同时获取索引和元素值 是高频需求 比如找目标元素的位置、双指针遍历标记、矩阵行列定位等。Python 内置的enumerate函数正是

在算法题目中,处理数组(List)、字符串、矩阵等可迭代对象时,“同时获取索引和元素值” 是高频需求 —— 比如找目标元素的位置、双指针遍历标记、矩阵行列定位等。Python 内置的 enumerate 函数正是用来解决这类问题的。

一、enumerate 函数的核心基础

1. 什么是 enumerate?

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

2. 基础语法

1

enumerate(iterable, start=0)

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

3. 告别手动索引

1

2

3

4

5

6

7

8

9

10

11

12

# 传统写法

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 的那两个整数,并返回它们的数组下标。假设每种输入只会对应一个答案,数组中同一个元素在答案里不能重复出现,可按任意顺序返回答案。

传统暴力解法:

1

2

3

4

5

6

7

8

9

10

11

12

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)(存储哈希表):

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

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解法:

1

2

3

4

5

6

7

8

9

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解法:

1

2

3

4

5

6

7

8

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 滑动窗口题)

题目原文

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

非enumerate写法:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

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写法:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

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解法:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

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解法:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

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 + 字典推导式可一键生成映射表:

1

2

3

4

5

# 生成“元素值: 作为字典的“键”(适用于无重复元素的数组)

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 返回的是迭代器,只能遍历一次;若需多次使用,可转为列表:

1

2

3

4

nums = [10, 20, 30]

# 将枚举对象转为列表,方便查看所有(索引,值)对

enum_list = list(enumerate(nums))

print(enum_list)  # 输出:[(0, 10), (1, 20), (2, 30)]

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

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

1

2

3

4

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. 索引是 “遍历顺序” 而非 “原数组实际索引”:若遍历的是切片 / 过滤后的数组,索引是相对索引,而非原数组索引:

    1

    2

    3

    4

    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 是列索引,避免混淆。

版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 :
相关文章
  • Python中enumerate函数的巧妙用法
    在算法题目中,处理数组(List)、字符串、矩阵等可迭代对象时,同时获取索引和元素值 是高频需求 比如找目标元素的位置、双指针遍历
  • Python中的断言机制的介绍
    想象你正在开发一个电商系统,有个计算商品折扣的函数。正常情况下,折扣率应该在0到1之间,但某天测试时发现某个商品折扣变成了1.
  • Python使用MySQL数据库进行事务处理示例
    一、事务核心概念(先理解再实操) 事务(Transaction)是数据库操作的最小逻辑单元,遵循ACID 原则: 原子性(Atomicity):要么全部执行成
  • Python多进程与多线程适用场景案例
    你想明确多进程和多线程各自的适用场景,核心是要结合任务类型、资源需求、数据共享等维度来判断简单来说,IO密集型任务优先用多线程
  • 使用Python实现一个自动整理音乐文件脚本
    一、音乐文件管理的痛点与解决方案 现代音乐收藏常面临杂乱无章的问题:同一艺术家的歌曲散落在不同文件夹,专辑被错误命名,甚至文
  • Python中as关键字的作用实例介绍
    在 Python 中,as是一个关键字,核心语义是将某个对象绑定到指定的变量(或给对象起别名),从而简化代码操作、访问对象属性。它主要应
  • Python使用urllib和requests发送HTTP请求的方法
    本文通过天气API示例演示了实际应用,并提供了超时设置、错误处理和JSON解析等实用技巧。推荐大多数场景使用requests库,同时强调了异常
  • 在Mac上安装最新版本Python的方法

    在Mac上安装最新版本Python的方法
    所有最新的 MacOS(从 macOS 12.3 开始)都预装了 Python 版本(通常是 Python 2.x),但它已经过时并且不再受支持。要充分利用 Python 的功能,您
  • python serial模块使用方法
    在Python中实现串口通信,最常用且功能强大的库是pySerial(通常通过import serial导入) 。它支持跨平台操作(Windows、Linux、macOS),提供了完
  • pytorch中torch.cat和torch.stack的区别

    pytorch中torch.cat和torch.stack的区别
    torch.cat和torch.stack是 PyTorch 中用于组合张量的两个常用函数,它们的核心区别在于输入张量的维度和输出张量的维度变化。以下是详细对比:
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计