当前位置: 首页 > news >正文

【最长连续序列】

一、题目

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

设计并实现时间复杂度为 O(n) 的算法解决此问题。

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

示例 2:
输入:nums = [0,3,7,2,5,8,4,6,0,1]
输出:9

提示:

  • 0 <= nums.length <= 105
  • -109 <= nums[i] <= 109

二、语法知识

2.1 集合set()

2.1.1 什么是集合 (set)?

集合 (set) 是 Python 中的一种内置数据类型,用于存储无序且不重复的元素集合。它类似于数学中的集合概念。

2.1.2 主要特性

  • 无序性: 集合中的元素没有固定的顺序。每次打印或遍历集合时,元素的顺序可能不同。
  • 唯一性: 集合会自动去除重复的元素。同一个元素在集合中只会出现一次。
  • 元素要求: 集合中的元素必须是可哈希的。这通常意味着它们必须是不可变类型,如数字(整数、浮点数)、字符串、元组(仅包含不可变元素)等。列表和字典(可变类型)不能作为集合的元素。
  • 可变性: set 本身是可变类型,可以添加或删除元素。Python 也提供了不可变的集合类型 frozenset

2.1.3 创建集合

  • 使用花括号 {}
    my_set = {1, 2, 3}
    print(my_set)  # 输出可能是 {1, 2, 3}, {2, 1, 3} 等,顺序不确定
    
  • 使用 set() 构造函数:
    empty_set = set()  # 创建空集合,注意 {} 创建的是空字典
    from_list = set([1, 2, 2, 3])  # 从列表创建,去重后为 {1, 2, 3}
    from_string = set("hello")  # 结果为 {'h', 'e', 'l', 'o'} (注意 'l' 只出现一次)
    

2.1.4 常用操作

  • 添加元素:
    my_set.add(4)  # 添加元素 4
    my_set.add(2)  # 添加元素 2,但集合中已有,无变化
    
  • 移除元素:
    my_set.remove(3)  # 移除元素 3。如果元素不存在,会引发 KeyError
    my_set.discard(3)  # 移除元素 3。如果元素不存在,不报错
    popped_element = my_set.pop()  # 随机移除并返回一个元素。空集合会报错
    my_set.clear()    # 清空集合
    
  • 成员检测:
    if 2 in my_set:print("2 is in the set")
    
  • 集合大小:
    size = len(my_set)
    

2.1.5 集合运算 (类比数学集合运算)

设两个集合 A={1,2,3}A = \{1, 2, 3\}A={1,2,3}B={3,4,5}B = \{3, 4, 5\}B={3,4,5}

  • 并集 (union()|): 返回包含 AAABBB中所有唯一元素的新集合。
    A∪B={1,2,3,4,5}A \cup B = \{1, 2, 3, 4, 5\}AB={1,2,3,4,5}
    union_set = A.union(B)  # 或 A | B
    
  • 交集 (intersection()&): 返回同时存在于 AAABBB 中的元素的新集合。
    A∩B={3}A \cap B = \{3\}AB={3}
    intersection_set = A.intersection(B)  # 或 A & B
    
  • 差集 (difference()-): 返回在 AAA 中但不在 BBB 中的元素的新集合。
    A−B={1,2}A - B = \{1, 2\}AB={1,2}
    diff_set = A.difference(B)  # 或 A - B
    
  • 对称差集 (symmetric_difference()^): 返回在 AAABBB 中,但不同时在两者中的元素的新集合。
    A△B=(A−B)∪(B−A)={1,2,4,5}A \triangle B = (A - B) \cup (B - A) = \{1, 2, 4, 5\}AB=(AB)(BA)={1,2,4,5}
    sym_diff_set = A.symmetric_difference(B)  # 或 A ^ B
    
  • 子集/超集判断:
    C = {1, 2}
    is_subset = C.issubset(A)   # 或 C <= A, 检查 C 是否是 A 的子集
    is_superset = A.issuperset(C) # 或 A >= C,检查 A 是否是 C 的超集
    is_proper_subset = C < A   # 检查 C 是否是 A 的真子集 (C != A)
    

2.1.6 集合推导式

类似于列表推导式,用于从可迭代对象创建集合:

squares_set = {x**2 for x in range(10)}  # {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}

2.1.7 不可变集合 (frozenset)

frozenset 是集合的不可变版本。创建后无法修改。它可以作为字典的键或另一个集合的元素。

immutable_set = frozenset([1, 2, 3])

2.1.8 应用场景

  • 去重: 快速去除列表、字符串等中的重复元素。
    unique_list = list(set(duplicate_list))
    
  • 成员测试: 检查元素是否存在非常高效(平均时间复杂度接近 O(1)O(1)O(1))。
  • 集合运算: 方便地进行并集、交集、差集等数学集合运算。
  • 字典键的替代: frozenset 可以作为字典的键。

2.2 排序

2.2.1 使用内置的sorted()函数

sorted()函数可以对任何可迭代对象进行排序,返回一个新的已排序列表,不改变原数组。适用于列表、元组等数据类型。
示例代码:

arr = [3, 1, 4, 1, 5, 9, 2]
sorted_arr = sorted(arr)
print(sorted_arr)  # 输出:[1, 1, 2, 3, 4, 5, 9]

2.2.2 使用列表的sort()方法

列表对象自带的sort()方法会直接修改原列表,不返回新列表,效率比sorted()更高。
示例代码:

arr = [3, 1, 4, 1, 5, 9, 2]
arr.sort()
print(arr)  # 输出:[1, 1, 2, 3, 4, 5, 9]

2.2.3 降序排序

通过参数reverse=True可实现从大到小排序。
sorted()示例:

sorted_arr = sorted(arr, reverse=True)

sort()示例:

arr.sort(reverse=True)

2.2.4 对多维数组按特定条件排序

使用key参数指定排序依据。例如按子数组第二个元素排序:

arr = [[1, 4], [2, 3], [3, 2]]
sorted_arr = sorted(arr, key=lambda x: x[1])  # 输出:[[3, 2], [2, 3], [1, 4]]

2.2.5 使用NumPy库的sort()方法

对于NumPy数组,np.sort()返回排序后的新数组,而ndarray.sort()会原地修改数组。
示例代码:

import numpy as np
arr = np.array([3, 1, 4, 1, 5])
sorted_arr = np.sort(arr)  # 返回新数组
arr.sort()  # 原地排序

性能注意事项

  • 对于纯Python列表,sort()方法比sorted()更快,尤其适合大数组。
  • NumPy的排序算法在数值型数据上效率显著高于纯Python方法。

2.3 获得字典中最大的值

方法一:使用max()函数直接获取值
通过max()函数结合字典的values()方法直接获取最大值:

my_dict = {'a': 10, 'b': 25, 'c': 5}
max_value = max(my_dict.values())
print(max_value)  # 输出25

方法二:获取最大值对应的键值对
使用max()函数结合字典的items()方法,通过比较值来获取完整键值对:

max_pair = max(my_dict.items(), key=lambda x: x[1])
print(max_pair)  # 输出('b', 25)

方法三:遍历字典比较值
手动遍历字典记录最大值,适合需要额外逻辑处理的场景:

max_val = float('-inf')
for value in my_dict.values():if value > max_val:max_val = value
print(max_val)

注意事项

  • 字典值为非数字类型时需自定义比较逻辑(例如字符串按长度比较)。
  • 空字典使用max()会触发ValueError,需提前检查字典是否为空。

三、题解

3.1 题解一

思路:首先对列表进行从小到大排序,然后依次遍历每个元素,计算到该元素n(包括该元素)存在的最长连续序列长度记为L(n),采用字典记录(键为数n,值为L(n)),采用递归方法计算元素n+1的最长连续序列长度L(n=1)=L(n)+1,最后找到字典中最大的值LmaxL_{max}Lmax

class Solution:def longestConsecutive(self, nums: List[int]) -> int:if not nums:  # 处理空数组return 0num_set = set(nums) # 使用集合提高查找效率counts_dict = {}nums.sort() # 排序数组,确保顺序处理for n in nums:counts_dict[n]=1if n-1 in num_set:counts_dict[n]+=counts_dict[n-1] #累加前一个数的值(如果存在)return max(counts_dict.values())

输入:[100,4,200,1,3,2]
排序:[1,2,3,4,100,200]
集合:[1,2,3,4,100,200]
字典:{ }
对元素1:L(1)=1;
对元素2:L(2)=1+L(1)=2;
对元素3:L(3)=1+L(2)=3;

要点:

  • 需单独处理空数组,否则寻找最大值max(counts_dict.values()出错;
  • 使用集合set()查找(in)元素是否存在,以实现O(1)O(1)O(1)的查找,如果使用列表查找则时间复杂度为O(n)O(n)O(n)
  • 当数组中有重复元素时,counts_dict[n] = 1会覆盖之前的值,然后重复计算元素n的L,虽然结果正确,但浪费了时间和空间;

3.2 题解二(力扣官方题解)

思路:哈希表。

枚举数组中的每个数 xxx,考虑以其为起点,不断尝试匹配 x+1x+1x+1,x+2x+2x+2,⋯\cdots 是否存在,假设最长匹配到了 x+yx+yx+y,那么以 xxx 为起点的最长连续序列即为 xxx,x+1x+1x+1,x+2x+2x+2,⋯\cdots,x+yx+yx+y,其长度为 y+1y+1y+1,不断枚举并更新答案即可。

匹配过程,暴力的方法是 O(n)O(n)O(n) 遍历数组去看是否存在这个数,更高效的方法是用一个哈希表存储数组中的数,这样查看一个数是否存在即能优化至 O(1)O(1)O(1) 的时间复杂度。

如果已知有一个 x,x+1,x+2,⋯,x+yx, x+1, x+2, \cdots, x+yx,x+1,x+2,,x+y 的连续序列,而从 x+1x+1x+1x+2x+2x+2x+yx+yx+y处开始尝试匹配,得到的结果不会优于枚举 xxx为起点的答案。因此在外层循环时遇到这种情况可直接跳过。

由于我们要枚举的数 xxx 一定是在数组中不存在前驱数 x−1x−1x1 的,不然会从 x−1x−1x1 开始尝试匹配,因此每次在哈希表中检查是否存在 x−1x−1x1 即能判断是否需要跳过了。

class Solution:def longestConsecutive(self, nums: List[int]) -> int:Max_L=0 #最大连续序列长度nums_set = set(nums) #去重for n in nums_set:if n-1 not in nums_set: #如果没有前驱数字n-1Current_L = 1 #当前元素为起点的最长连续序列长度Current_n = nwhile(Current_n+1 in nums_set):Current_L+=1Current_n+=1Max_L = max(Current_L,Max_L)return Max_L
http://www.dtcms.com/a/589190.html

相关文章:

  • FreeRTOS抢占调度与时间片调度
  • AI 编程翻车实录 - 智谱 GLM 4.6 给的自信
  • Anygrasp_sdk本地部署和使用
  • 系统设计 --- 多节点中按顺序处理消息
  • 深圳高端企业官方网站建设海创网站建设
  • 【C#】何时用ref?
  • STM32中ADC + DMA自动采集系统
  • 读书之《架构师的自我修炼》_个人笔记
  • 什么网站可以快速做3d效果图php网站维护
  • 迅速提高网站排名帮别人做网站收多少钱合适
  • 怎么做网站上的模拟动画做网站四百全包
  • 利用短整数类型和部分字符串优化DuckDB利用数组求解数独SQL
  • 营销型网站四大功能模版网站有源代码吗
  • 力扣81. 搜索旋转排序数组 II
  • WampServer安装教程(图文步骤)+ 下载+配置+解决图标红橙绿问题【附安装包】
  • 使用 dash 构建 mvvm 整洁架构应用
  • 跨时钟域处理
  • 2025制品管理工具选型,jfrog vs nexus vs hadess哪一款更好用?
  • 北京校园网站建设wordpress新建页面是
  • 【1.7】基于FPGA的costas环开发1——发射端信号产生模块
  • Postman 工具实现签名校验:完整操作指南与代码解析
  • AQS介绍
  • reshape的共享内存
  • 数据结构之,栈与队列
  • 【数据结构】基于哈夫曼树的数据压缩算法
  • SQLAlchemy2.0使用
  • 利用binlog2sql数据闪回实战
  • 东莞网站建设曼哈顿信科网站建设的总体设计概图
  • 算法:矩形区域不超过k的数值和
  • 算法30.0