LeetCode Hot100数据结构背景知识之字典(Dictionary)Python2026新版

专栏其他内容:

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

LeetCode Hot100数据结构背景知识之列表(List)Python2026新版

LeetCode Hot100数据结构背景知识之元组(Tuple)Python2026新版

LeetCode Hot100数据结构背景知识之集合(Set)Python2026新版

Python字典(Dictionary)核心特点、基础用法与常用函数

1. 字典的核心特点

字典(Dictionary)以键值对(key-value)存储数据,支持O(1)平均时间复杂度的增删改查。

  • 键值对存储:字典的基本结构是「key: value」,一个key对应一个value,key是唯一标识,value可重复、可存储任意数据类型(整数、字符串、列表、字典等)。

  • key的约束:key必须是「不可变数据类型」(如整数、字符串、元组),不可用列表、字典等可变类型(会报错);且key唯一,若重复赋值,后值会覆盖前值。

  • O(1)平均时间复杂度:增、删、改、查(判断key是否存在、获取value)的平均时间复杂度均为O(1),这是字典优于列表(O(n)查找)的核心原因,也是刷题中用字典优化效率的关键。

  • 有序性(Python3.7+):3.7及以上版本中,字典会保留键值对的插入顺序,遍历字典时会按插入顺序返回;3.6及以下版本无序(刷题时无需纠结版本,主流在线判题环境均为3.7+)。

  • 可变性:字典是可变数据类型,可动态添加、删除、修改键值对,无需提前定义长度(适配刷题中动态计数、映射的需求)。

2. 字典的基础用法

重点掌握「初始化」「增删改查」四大操作:

  1. 初始化:三种常用方式,按需选择

    1. 空字典(最常用):dict1 = {}dict1 = dict()

    2. 带初始键值对:dict2 = {"a":1, "b":2}(适合已知初始映射关系);

    3. 去重初始化:dict3 = dict.fromkeys([1,2,3], True)(key为列表元素,value统一,快速去重)。

      python 复制代码
      >>> nums = [100,4,200,1,3,2,2]
      >>> nums  # 原始数组
      [100, 4, 200, 1, 3, 2, 2]
      
      >>> num_dict = dict.fromkeys(nums, 1)
      >>> num_dict  # 去重后的字典
      {100: 1, 4: 1, 200: 1, 1: 1, 3: 1, 2: 1}
      
      >>> num_dict.keys()  # 字典的键视图(不是列表)
      dict_keys([100, 4, 200, 1, 3, 2])
      
      >>> unique_nums = list(num_dict.keys())
      >>> unique_nums  # 转换为列表后的结果
      [100, 4, 200, 1, 3, 2]
      
      >>> print(unique_nums)  # 最终打印输出
      [100, 4, 200, 1, 3, 2]
  2. 新增/修改键值对:同一语法,key存在则修改,不存在则新增

    1. 常规写法:dict1["c"] = 3(新增)、dict1["a"] = 5(修改);

    2. 批量新增:dict1.update({"d":4, "e":5})(适合一次性添加多个键值对)。

  3. 删除键值对:三种方式,刷题中常用前两种

    1. del语句:del dict1["a"](删除指定key,key不存在报错,需提前判断);

    2. pop()方法:dict1.pop("b")(删除指定key,返回对应的value,key不存在可设默认值避免报错:dict1.pop("f", 0));

    3. 清空字典:dict1.clear()(适合重复利用字典时清空数据)。

  4. 查找操作

    1. 判断key是否存在(最常用):if "a" in dict1:(O(1)时间,比列表in操作高效);

    2. 获取value:dict1["a"](key不存在报错)、dict1.get("a", 0)(key不存在返回默认值0)。

    3. get()的作用是安全地获取字典中指定键的值 ,避免直接通过 dict[key] 访问不存在的键时抛出 KeyError 异常。dict.get(key, default=None)

      python 复制代码
      # 示例字典
      score = {"Alice": 90, "Bob": 85}
      # 1. 直接访问不存在的键 → 报错 KeyError
      # print(score["Charlie"])  # 运行报错
      # 2. 使用get()访问不存在的键 → 返回默认值
      print(score.get("Charlie"))  # 输出 None(默认值)
      print(score.get("Charlie", 0))  # 输出 0(自定义默认值)
      print(score.get("Alice", 0))  # 输出 90(键存在,返回对应值)
  5. 遍历操作

    1. 遍历key(最常用):写法1(直接遍历):for key in dict1: 写法2(用keys()方法):for key in dict1.keys(): 遍历value:用values()方法,适合仅需获取计数结果、判断value是否符合条件的场景 写法:for val in dict1.values():

    2. 遍历key和val(常用):用items()方法,同时获取键值对,适配需联动key和value的场景 写法:for key, val in dict1.items():

3. 字典常用函数

函数/方法 用法示例 功能说明
get() dict.get(key, default=0) 获取key对应的value,不存在则返回default
fromkeys() dict.fromkeys(iterable, value) 用可迭代对象生成字典,key为迭代元素,value统一
update() dict.update(other_dict) 批量添加/修改键值对,other_dict为字典
pop() dict.pop(key, default) 删除key,返回value,不存在则返回default
keys() dict.keys() 返回字典中所有key的可迭代对象
values() dict.values() 返回字典中所有value的可迭代对象
items() dict.items() 返回字典中所有(key, value)元组的可迭代对象

一、LeetCode中字典的核心优势与适用场景

在算法题中,字典的核心价值是「快速建立映射关系」,替代列表的O(n)查找,从而优化整体时间复杂度。

  1. 计数统计:统计数组/字符串中元素出现的次数(如字符计数、数字频次),替代暴力遍历计数(时间复杂度从O(n²)降至O(n));

  2. 键值映射:存储「目标值-索引」「元素-对应满足条件的元素」等关系(如两数之和、两数之和II),快速定位所需元素;

  3. 去重与筛选:利用字典的key唯一特性,实现高效去重,或筛选符合条件的元素组合(如最长连续序列)。

二、Hot100真题实战

真题1:两数之和(Easy,Hot100 Top5)------ 键值映射的基础应用

题干:

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。

你可以按任意顺序返回答案。

示例 1:

复制代码
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

字典解法思路(最优解)

核心需求:快速找到「target - 当前元素」是否在数组中,且获取其下标。

用字典存储「元素值 → 元素下标」,遍历数组时,对每个元素nums[i]:

  1. 计算互补值 complement = target - nums[i];

  2. 判断complement是否在字典的key中:若在,直接返回[字典[complement], i];

  3. 若不在,将当前元素nums[i]及其下标i存入字典(避免重复使用同一元素);

  4. 遍历结束后,必能找到答案(题干保证有解)。

字典代码实现(Python)

python 复制代码
class Solution(object):
    def twoSum(self, nums, target):
    # 初始化空字典,存储键:元素值,值:元素下标
        num_map = {}
        for i in range(len(nums)):
            complement = target - nums[i]
            # 关键:判断互补值是否已在字典中(O(1)查找)
            if complement in num_map:
                return [num_map[complement], i]
            # 注意:先判断再存入,避免同一元素被重复使用
            num_map[nums[i]] = i
    # 题干保证有解,此处可省略return

非字典代码实现:

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

避坑点

  • 不能先存入字典再判断:若先存,当nums[i] = target/2时(如target=6,nums[i]=3),会误判自己与自己求和,导致错误;

  • 字典的key是元素值,不是下标:避免搞反键值对,否则无法通过互补值快速获取下标。

复杂度分析:时间O(n)(仅遍历一次数组),空间O(n)(最坏情况存储所有元素),是本题的最优解。

真题2:多数元素(Easy,Hot100 Top20)------ 计数统计的基础应用

题干:

给定一个大小为 n的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。你可以假设数组是非空的,并且给定的数组总是存在多数元素。

示例 1:

复制代码
输入:nums = [3,2,3]
输出:3

示例 2:

复制代码
输入:nums = [2,2,1,1,1,2,2]
输出:2

字典解法思路

核心需求:统计每个元素的出现次数,找到次数大于n/2的元素。

用字典存储「元素 → 出现次数」,遍历数组时完成计数,之后遍历字典,返回次数最大(且满足条件)的元素。

优化点:遍历数组时,可实时判断当前元素的次数是否已超过n/2,若超过直接返回,无需遍历完整个数组和字典。

代码实现(Python)

python 复制代码
class Solution(object):
    def majorityElement(self, nums):
        count_map = {}
        n = len(nums)
        half = n // 2
        for num in nums:
        # 简洁写法:若num在字典中,次数+1;否则设为1
            count_map[num] = count_map.get(num, 0) + 1
        # 优化:实时判断,提前返回
            if count_map[num] > half:
                return num
        # 题干保证有解,此处可省略return

哈希表实现:

python 复制代码
class Solution:
    def majorityElement(self, nums: List[int]) -> int:
        counts = collections.Counter(nums)
        return max(counts.keys(), key=counts.get)

排序实现:

python 复制代码
class Solution:
    def majorityElement(self, nums: List[int]) -> int:
        nums.sort()
        return nums[len(nums) // 2]

避坑点

  • 使用get()方法简化计数逻辑:避免先判断num是否在字典中,再手动赋值,代码更简洁;

  • 无需遍历完字典:多数元素的次数一定超过n/2,遍历数组时一旦满足条件,直接返回,提升效率(最坏情况仍遍历一次数组)。

真题3:最长连续序列(Medium,Hot100 Top30)------ (去重+映射)

题干:

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。请你设计并实现时间复杂度为 O(n)的算法解决此问题。

示例 1:

复制代码
输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。

字典解法思路(O(n)最优解)

核心难点:未排序数组,要求O(n)时间,无法用排序(排序时间O(nlogn)),需用字典快速定位连续序列的边界。

思路拆解:

  1. 去重:将数组元素存入字典(key为元素,value可设为布尔值或长度,此处用布尔值标记元素是否已处理,避免重复计算);

  2. 遍历字典的每个key(即数组中的每个唯一元素):

    1. 判断当前元素是否是连续序列的「起点」:即当前元素-1不在字典中(说明没有比它小1的元素,它是序列的第一个元素);

    2. 若为起点,开始向后计数:依次判断当前元素+1、+2...是否在字典中,统计序列长度;

    3. 更新最长序列长度,遍历结束后返回最大值。

关键:每个元素仅被处理一次(处理起点时,会一次性遍历整个连续序列,后续遍历到序列中的其他元素时,因不是起点,直接跳过),保证时间复杂度O(n)。

字典代码实现(Python)

python 复制代码
class Solution(object):
    def longestConsecutive(self, nums):
        """
        利用哈希表(字典)求解最长连续序列
        :type nums: List[int]
        :rtype: int
        """
        # 1. 去重:将数字存入字典,键为数字,值为该数字所在连续序列的长度
        # 去重是为了避免重复处理相同数字,比如 nums = [1,2,0,1] 中的 1 只处理一次
        num_dict = {}
        max_length = 0  # 记录最长连续序列的长度
        
        for num in nums:
            # 2. 只处理未在字典中的数字(去重)
            if num not in num_dict:
                # 3. 获取当前数字左右相邻数字的连续序列长度
                # left_len:num-1 所在连续序列的长度(如果不存在则为0)
                left_len = num_dict.get(num - 1, 0)
                # right_len:num+1 所在连续序列的长度(如果不存在则为0)
                right_len = num_dict.get(num + 1, 0)
                
                # 4. 当前数字所在连续序列的总长度 = 左长度 + 右长度 + 1(自身)
                current_len = left_len + right_len + 1
                
                # 5. 更新最长长度
                if current_len > max_length:
                    max_length = current_len
                
                # 6. 更新字典:只需更新连续序列的「边界」值即可
                # 因为后续只会查询边界数字的长度,中间数字不会再被用到
                num_dict[num] = current_len  # 更新当前数字的长度
                num_dict[num - left_len] = current_len  # 更新左边界的长度
                num_dict[num + right_len] = current_len  # 更新右边界的长度
        
        return max_length

集合代码实现(Python)

python 复制代码
from typing import List

class Solution:
    def longestConsecutive(self, nums: List[int]) -> int:
        longest_streak = 0  # 记录最长连续序列长度
        num_set = set(nums)  # 转集合:去重 + O(1)时间查找

        # 遍历去重后的每个数字
        for num in num_set:
            # 关键:只有当num是连续序列的「起点」(num-1不存在)时,才开始统计
            if num - 1 not in num_set:
                current_num = num  # 当前遍历的数字
                current_streak = 1  # 当前连续序列长度

                # 向后查找连续数字(current_num+1是否存在)
                while current_num + 1 in num_set:
                    current_num += 1
                    current_streak += 1

                # 更新最长长度
                longest_streak = max(longest_streak, current_streak)

        return longest_streak

避坑点

  • 去重是关键:数组中可能有重复元素(如示例2中的0),用字典去重后,避免重复处理同一元素,降低时间复杂度;

  • 仅处理起点:若不判断num-1是否在字典中,会对每个元素都向后计数,导致时间复杂度升至O(n²)(如序列[1,2,3,4],会对1、2、3、4分别计数);

  • 边界条件:空数组返回0,避免遍历字典时出错。

相关推荐
蜡笔小马2 小时前
10.Boost.Geometry R-tree 空间索引详解
开发语言·c++·算法·r-tree
我是咸鱼不闲呀2 小时前
力扣Hot100系列20(Java)——[动态规划]总结(下)( 单词拆分,最大递增子序列,乘积最大子数组 ,分割等和子集,最长有效括号)
java·leetcode·动态规划
程序媛徐师姐2 小时前
Python基于爬虫的网络小说数据分析系统【附源码、文档说明】
爬虫·python·python爬虫·网络小说数据分析系统·pytho网络小说数据分析系统·python爬虫网络小说·python爬虫的网络小说数据
唐梓航-求职中2 小时前
编程-技术-算法-leetcode-288. 单词的唯一缩写
算法·leetcode·c#
仟濹2 小时前
【算法打卡day3 | 2026-02-08 周日 | 算法: BFS】3_卡码网99_计数孤岛_BFS | 4_卡码网100_最大岛屿的面积DFS
算法·深度优先·宽度优先
清水白石0082 小时前
深入解析 LRU 缓存:从 `@lru_cache` 到手动实现的完整指南
java·python·spring·缓存
Ll13045252982 小时前
Leetcode二叉树part4
算法·leetcode·职场和发展
JaydenAI2 小时前
[LangChain之链]LangChain的Chain——由Runnable构建的管道
python·langchain
kali-Myon2 小时前
2025春秋杯网络安全联赛冬季赛-day3
python·安全·web安全·ai·php·web·ctf