docs: 改进LeetCode二叉树题目解题思路
按照改进方案,为以下6个二叉树题目增强了解题思路的详细程度: 1. 二叉树的中序遍历 - 增加"思路推导"部分,解释递归到迭代的转换 - 详细说明迭代法的每个步骤 - 增加执行过程演示和多种解法 2. 二叉树的最大深度 - 增加"思路推导",对比DFS和BFS - 详细解释递归的基准情况 - 增加多种解法和变体问题 3. 从前序与中序遍历序列构造二叉树 - 详细解释前序和中序的特点 - 增加"思路推导",说明如何分治 - 详细说明切片边界计算 4. 对称二叉树 - 解释镜像对称的定义 - 详细说明递归比较的逻辑 - 增加迭代解法和变体问题 5. 翻转二叉树 - 解释翻转的定义和过程 - 详细说明多值赋值的执行顺序 - 增加多种解法和有趣的故事 6. 路径总和 - 详细解释路径和叶子节点的定义 - 说明为什么使用递减而非累加 - 增加多种解法和变体问题 每个文件都包含: - 完整的示例和边界条件分析 - 详细的算法流程和图解 - 关键细节说明 - 常见错误分析 - 复杂度分析(详细版) - 执行过程演示 - 多种解法 - 变体问题 - 总结 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,44 +1,705 @@
|
||||
# 最长连续序列 (Longest Consecutive Sequence)
|
||||
|
||||
LeetCode 128. Medium
|
||||
|
||||
## 题目描述
|
||||
|
||||
给定一个未排序的整数数组 nums,找出数字连续的最长序列的长度。
|
||||
给定一个未排序的整数数组 `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, 1, 2, 3, 4, 5, 6, 7, 8]。
|
||||
```
|
||||
|
||||
## 思路推导
|
||||
|
||||
### 暴力解法分析
|
||||
|
||||
**最直观的思路**:排序后遍历,找到最长的连续序列。
|
||||
|
||||
```python
|
||||
def longestConsecutive(nums):
|
||||
if not nums:
|
||||
return 0
|
||||
|
||||
nums.sort()
|
||||
max_len = 1
|
||||
current_len = 1
|
||||
|
||||
for i in range(1, len(nums)):
|
||||
if nums[i] == nums[i-1] + 1:
|
||||
current_len += 1
|
||||
elif nums[i] != nums[i-1]: # 跳过重复
|
||||
current_len = 1
|
||||
|
||||
max_len = max(max_len, current_len)
|
||||
|
||||
return max_len
|
||||
```
|
||||
|
||||
**时间复杂度**:O(n log n)
|
||||
- 排序:O(n log n)
|
||||
- 遍历:O(n)
|
||||
- 总计:O(n log n) + O(n) = O(n log n)
|
||||
|
||||
**空间复杂度**:O(1) 或 O(n),取决于排序算法
|
||||
|
||||
**问题分析**:
|
||||
1. 不满足题目要求:题目要求 O(n)
|
||||
2. 排序是最快的,但仍不够快
|
||||
3. 需要寻找不排序的解法
|
||||
|
||||
### 优化思考 - 第一步:哈希表查找
|
||||
|
||||
**观察**:连续序列的特点是相邻元素相差 1
|
||||
|
||||
**问题**:如何快速判断一个数是否存在?
|
||||
|
||||
**解决方案**:使用哈希表(Set)
|
||||
|
||||
```python
|
||||
num_set = set(nums)
|
||||
|
||||
for num in nums:
|
||||
# 检查 num+1 是否在集合中
|
||||
if num + 1 in num_set:
|
||||
# 继续检查 num+2, num+3, ...
|
||||
```
|
||||
|
||||
**为什么这样思考?**
|
||||
- 哈希表查找:O(1)
|
||||
- 可以快速判断一个数是否存在
|
||||
- 不需要排序
|
||||
|
||||
### 优化思考 - 第二步:寻找序列起点
|
||||
|
||||
**关键优化**:如何避免重复计算同一个序列?
|
||||
|
||||
**观察**:只有当一个数是序列的起点时,才需要计算
|
||||
|
||||
```python
|
||||
# num 是序列起点
|
||||
if num - 1 not in num_set:
|
||||
# 从 num 开始向后查找
|
||||
current_num = num
|
||||
current_len = 1
|
||||
|
||||
while current_num + 1 in num_set:
|
||||
current_num += 1
|
||||
current_len += 1
|
||||
```
|
||||
|
||||
**为什么这样思考?**
|
||||
- 如果 `num-1` 存在,说明 `num` 不是起点
|
||||
- 只有起点才需要计算,避免重复
|
||||
- 每个序列只被计算一次
|
||||
|
||||
**时间复杂度**:O(n)
|
||||
- 外层循环:O(n)
|
||||
- 内层 while:总计 O(n)(每个元素只访问一次)
|
||||
- 总计:O(n) + O(n) = O(n)
|
||||
|
||||
### 优化思考 - 第三步:空间换时间
|
||||
|
||||
**权衡**:
|
||||
- 时间复杂度:O(n)
|
||||
- 空间复杂度:O(n)
|
||||
- 用空间换取时间
|
||||
|
||||
**为什么可以接受?**
|
||||
- 题目要求 O(n) 时间
|
||||
- O(n) 空间是可接受的
|
||||
- 哈希表是实现 O(n) 的必要条件
|
||||
|
||||
## 解题思路
|
||||
|
||||
### 哈希表
|
||||
### 核心思想
|
||||
|
||||
将数字存入哈希表,对于每个数字,如果它是序列的起点(num-1 不在集合中),则向后查找。
|
||||
**哈希表 + 序列起点判断**:用哈希表存储所有数字,只从序列起点开始计算长度。
|
||||
|
||||
## Go 代码
|
||||
**为什么这样思考?**
|
||||
|
||||
1. **哈希表的优势**:
|
||||
- O(1) 时间查找元素是否存在
|
||||
- 无需排序,保持原始数据
|
||||
|
||||
2. **序列起点判断**:
|
||||
- 如果 `num-1` 不在集合中,`num` 是起点
|
||||
- 只有起点才需要计算
|
||||
- 避免重复计算同一个序列
|
||||
|
||||
3. **时间复杂度保证**:
|
||||
- 每个元素最多被访问 2 次
|
||||
- 一次在哈希表中
|
||||
- 一次在 while 循环中
|
||||
|
||||
### 详细算法流程
|
||||
|
||||
**步骤1:构建哈希表**
|
||||
|
||||
```python
|
||||
num_set = set(nums)
|
||||
```
|
||||
|
||||
**作用**:
|
||||
- 快速判断元素是否存在
|
||||
- O(1) 时间复杂度
|
||||
|
||||
**步骤2:遍历所有数字**
|
||||
|
||||
```python
|
||||
longest = 0
|
||||
|
||||
for num in num_set:
|
||||
# 判断是否为序列起点
|
||||
if num - 1 not in num_set:
|
||||
# 从起点开始计算序列长度
|
||||
current_num = num
|
||||
current_len = 1
|
||||
|
||||
# 向后查找连续数字
|
||||
while current_num + 1 in num_set:
|
||||
current_num += 1
|
||||
current_len += 1
|
||||
|
||||
# 更新最大长度
|
||||
longest = max(longest, current_len)
|
||||
```
|
||||
|
||||
**关键点详解**:
|
||||
|
||||
1. **为什么判断 `num - 1 not in num_set`?**
|
||||
- 如果 `num-1` 存在,说明 `num` 不是起点
|
||||
- 只有起点才需要计算
|
||||
- 避免重复计算
|
||||
|
||||
**示例**:
|
||||
```
|
||||
nums = [1, 2, 3, 4]
|
||||
|
||||
num=1: 1-1=0 不在集合中 → 起点,计算 [1,2,3,4]
|
||||
num=2: 2-1=1 在集合中 → 不是起点,跳过
|
||||
num=3: 3-1=2 在集合中 → 不是起点,跳过
|
||||
num=4: 4-1=3 在集合中 → 不是起点,跳过
|
||||
```
|
||||
|
||||
2. **为什么用 `while` 而不是 `for`?**
|
||||
- 不知道序列有多长
|
||||
- 需要动态判断下一个数字是否存在
|
||||
- `while` 更灵活
|
||||
|
||||
3. **为什么可以保证 O(n)?**
|
||||
- 外层 for 循环:O(n)
|
||||
- 内层 while 循环:总计 O(n)
|
||||
- 每个元素只在 while 中被访问一次
|
||||
- 因为只有起点才会进入 while
|
||||
- 总计:O(n) + O(n) = O(n)
|
||||
|
||||
### 关键细节说明
|
||||
|
||||
**细节1:为什么用 `set` 而不是 `list`?**
|
||||
|
||||
```python
|
||||
# 推荐:使用 set
|
||||
num_set = set(nums)
|
||||
if num - 1 in num_set: # O(1)
|
||||
|
||||
# 不推荐:使用 list
|
||||
if num - 1 in nums: # O(n)
|
||||
```
|
||||
|
||||
**原因**:
|
||||
- `set` 的查找是 O(1)
|
||||
- `list` 的查找是 O(n)
|
||||
- 总复杂度会变成 O(n²)
|
||||
|
||||
**细节2:为什么遍历 `num_set` 而不是 `nums`?**
|
||||
|
||||
```python
|
||||
# 推荐:遍历 num_set
|
||||
for num in num_set: # 自动去重
|
||||
|
||||
# 不推荐:遍历 nums
|
||||
for num in nums: # 可能有重复
|
||||
```
|
||||
|
||||
**原因**:
|
||||
- `nums` 可能有重复元素
|
||||
- 重复元素会导致重复计算
|
||||
- `num_set` 自动去重
|
||||
|
||||
**细节3:为什么需要 `longest` 变量?**
|
||||
|
||||
```python
|
||||
longest = 0
|
||||
|
||||
for num in num_set:
|
||||
current_len = ...
|
||||
longest = max(longest, current_len)
|
||||
```
|
||||
|
||||
**原因**:
|
||||
- 需要记录全局最大值
|
||||
- 每次计算完一个序列后更新
|
||||
- 最终返回 `longest`
|
||||
|
||||
### 边界条件分析
|
||||
|
||||
**边界1:空数组**
|
||||
|
||||
```
|
||||
输入:nums = []
|
||||
输出:0
|
||||
处理:
|
||||
num_set = set()
|
||||
for 循环不执行
|
||||
longest = 0
|
||||
```
|
||||
|
||||
**边界2:单个元素**
|
||||
|
||||
```
|
||||
输入:nums = [1]
|
||||
输出:1
|
||||
过程:
|
||||
num_set = {1}
|
||||
|
||||
num=1: 1-1=0 不在集合中 → 起点
|
||||
current_num=1, current_len=1
|
||||
1+1=2 不在集合中 → 退出
|
||||
longest = max(0, 1) = 1
|
||||
|
||||
输出:1
|
||||
```
|
||||
|
||||
**边界3:全部重复**
|
||||
|
||||
```
|
||||
输入:nums = [1, 1, 1, 1]
|
||||
输出:1
|
||||
过程:
|
||||
num_set = {1}
|
||||
|
||||
num=1: 1-1=0 不在集合中 → 起点
|
||||
current_num=1, current_len=1
|
||||
1+1=2 不在集合中 → 退出
|
||||
longest = 1
|
||||
|
||||
输出:1
|
||||
```
|
||||
|
||||
**边界4:多个连续序列**
|
||||
|
||||
```
|
||||
输入:nums = [100, 4, 200, 1, 3, 2]
|
||||
输出:4
|
||||
过程:
|
||||
num_set = {100, 4, 200, 1, 3, 2}
|
||||
|
||||
num=100: 100-1=99 不在集合中 → 起点
|
||||
current_num=100, current_len=1
|
||||
101 不在集合中 → 退出
|
||||
longest = 1
|
||||
|
||||
num=4: 4-1=3 在集合中 → 不是起点,跳过
|
||||
|
||||
num=200: 200-1=199 不在集合中 → 起点
|
||||
current_num=200, current_len=1
|
||||
201 不在集合中 → 退出
|
||||
longest = max(1, 1) = 1
|
||||
|
||||
num=1: 1-1=0 不在集合中 → 起点
|
||||
current_num=1, current_len=1
|
||||
2 在集合中 → current_len=2
|
||||
3 在集合中 → current_len=3
|
||||
4 在集合中 → current_len=4
|
||||
5 不在集合中 → 退出
|
||||
longest = max(1, 4) = 4
|
||||
|
||||
num=3: 3-1=2 在集合中 → 不是起点,跳过
|
||||
|
||||
num=2: 2-1=1 在集合中 → 不是起点,跳过
|
||||
|
||||
输出:4
|
||||
```
|
||||
|
||||
**边界5:负数**
|
||||
|
||||
```
|
||||
输入:nums = [-1, -2, 0, 1]
|
||||
输出:4
|
||||
过程:
|
||||
num_set = {-1, -2, 0, 1}
|
||||
|
||||
num=-1: -1-1=-2 在集合中 → 不是起点,跳过
|
||||
|
||||
num=-2: -2-1=-3 不在集合中 → 起点
|
||||
current_num=-2, current_len=1
|
||||
-1 在集合中 → current_len=2
|
||||
0 在集合中 → current_len=3
|
||||
1 在集合中 → current_len=4
|
||||
2 不在集合中 → 退出
|
||||
longest = 4
|
||||
|
||||
num=0: 0-1=-1 在集合中 → 不是起点,跳过
|
||||
|
||||
num=1: 1-1=0 在集合中 → 不是起点,跳过
|
||||
|
||||
输出:4
|
||||
```
|
||||
|
||||
### 复杂度分析(详细版)
|
||||
|
||||
**时间复杂度**:
|
||||
```
|
||||
- 构建哈希表:O(n)
|
||||
- 外层循环:O(n),遍历所有元素
|
||||
- 内层 while:总计 O(n)
|
||||
- 每个元素只在 while 中被访问一次
|
||||
- 因为只有起点才会进入 while
|
||||
- 总计:O(n) + O(n) + O(n) = O(n)
|
||||
|
||||
为什么是 O(n)?
|
||||
- 虽然有嵌套循环,但每个元素最多被访问 2 次
|
||||
- 一次在哈希表中
|
||||
- 一次在 while 循环中
|
||||
- 总操作次数 = 2n = O(n)
|
||||
```
|
||||
|
||||
**空间复杂度**:
|
||||
```
|
||||
- 哈希表:O(n),存储所有元素
|
||||
- 变量:O(1)
|
||||
- 总计:O(n)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 图解过程
|
||||
|
||||
```
|
||||
nums = [100, 4, 200, 1, 3, 2]
|
||||
|
||||
构建哈希表:
|
||||
num_set = {100, 4, 200, 1, 3, 2}
|
||||
|
||||
遍历:
|
||||
|
||||
步骤1: num = 100
|
||||
100-1=99 不在集合中 → 起点
|
||||
序列:[100]
|
||||
101 不在集合中 → 退出
|
||||
longest = 1
|
||||
|
||||
步骤2: num = 4
|
||||
4-1=3 在集合中 → 不是起点,跳过
|
||||
|
||||
步骤3: num = 200
|
||||
200-1=199 不在集合中 → 起点
|
||||
序列:[200]
|
||||
201 不在集合中 → 退出
|
||||
longest = 1
|
||||
|
||||
步骤4: num = 1
|
||||
1-1=0 不在集合中 → 起点
|
||||
序列:[1, 2, 3, 4]
|
||||
5 不在集合中 → 退出
|
||||
longest = 4
|
||||
|
||||
步骤5: num = 3
|
||||
3-1=2 在集合中 → 不是起点,跳过
|
||||
|
||||
步骤6: num = 2
|
||||
2-1=1 在集合中 → 不是起点,跳过
|
||||
|
||||
结果:longest = 4
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 代码实现
|
||||
|
||||
```go
|
||||
func longestConsecutive(nums []int) int {
|
||||
// 构建哈希表
|
||||
numSet := make(map[int]bool)
|
||||
for _, num := range nums {
|
||||
numSet[num] = true
|
||||
}
|
||||
|
||||
|
||||
longest := 0
|
||||
|
||||
|
||||
// 遍历所有数字
|
||||
for num := range numSet {
|
||||
if !numSet[num-1] { // 是序列起点
|
||||
// 判断是否为序列起点
|
||||
if !numSet[num-1] {
|
||||
currentNum := num
|
||||
current := 1
|
||||
|
||||
|
||||
// 向后查找连续数字
|
||||
for numSet[currentNum+1] {
|
||||
currentNum++
|
||||
current++
|
||||
}
|
||||
|
||||
|
||||
// 更新最大长度
|
||||
if current > longest {
|
||||
longest = current
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return longest
|
||||
}
|
||||
```
|
||||
|
||||
**复杂度:** O(n) 时间,O(n) 空间
|
||||
**关键点**:
|
||||
1. 使用 map 实现 Set
|
||||
2. 判断 `num-1` 是否存在
|
||||
3. 只有起点才计算序列长度
|
||||
|
||||
---
|
||||
|
||||
## 执行过程演示
|
||||
|
||||
**输入**:nums = [100, 4, 200, 1, 3, 2]
|
||||
|
||||
```
|
||||
初始化:numSet = {}, longest = 0
|
||||
|
||||
步骤1:构建哈希表
|
||||
numSet = {
|
||||
100: true,
|
||||
4: true,
|
||||
200: true,
|
||||
1: true,
|
||||
3: true,
|
||||
2: true
|
||||
}
|
||||
|
||||
步骤2:遍历哈希表
|
||||
|
||||
num=100:
|
||||
100-1=99 不在 numSet 中 → 起点
|
||||
currentNum=100, current=1
|
||||
101 不在 numSet 中 → 退出
|
||||
longest = max(0, 1) = 1
|
||||
|
||||
num=4:
|
||||
4-1=3 在 numSet 中 → 不是起点,跳过
|
||||
|
||||
num=200:
|
||||
200-1=199 不在 numSet 中 → 起点
|
||||
currentNum=200, current=1
|
||||
201 不在 numSet 中 → 退出
|
||||
longest = max(1, 1) = 1
|
||||
|
||||
num=1:
|
||||
1-1=0 不在 numSet 中 → 起点
|
||||
currentNum=1, current=1
|
||||
2 在 numSet 中 → currentNum=2, current=2
|
||||
3 在 numSet 中 → currentNum=3, current=3
|
||||
4 在 numSet 中 → currentNum=4, current=4
|
||||
5 不在 numSet 中 → 退出
|
||||
longest = max(1, 4) = 4
|
||||
|
||||
num=3:
|
||||
3-1=2 在 numSet 中 → 不是起点,跳过
|
||||
|
||||
num=2:
|
||||
2-1=1 在 numSet 中 → 不是起点,跳过
|
||||
|
||||
结果:longest = 4
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 常见错误
|
||||
|
||||
### 错误1:忘记去重
|
||||
|
||||
❌ **错误代码**:
|
||||
```go
|
||||
// 直接遍历 nums,可能有重复
|
||||
for _, num := range nums {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
✅ **正确代码**:
|
||||
```go
|
||||
// 先构建 Set,自动去重
|
||||
numSet := make(map[int]bool)
|
||||
for _, num := range nums {
|
||||
numSet[num] = true
|
||||
}
|
||||
|
||||
for num := range numSet {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**原因**:
|
||||
- `nums` 可能有重复元素
|
||||
- 重复元素会导致重复计算
|
||||
- 影响时间复杂度
|
||||
|
||||
---
|
||||
|
||||
### 错误2:没有判断序列起点
|
||||
|
||||
❌ **错误代码**:
|
||||
```go
|
||||
// 对每个数字都计算序列长度
|
||||
for num := range numSet {
|
||||
current := 1
|
||||
for numSet[currentNum+1] {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
✅ **正确代码**:
|
||||
```go
|
||||
// 只对起点计算序列长度
|
||||
for num := range numSet {
|
||||
if !numSet[num-1] { // 判断是否为起点
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**原因**:
|
||||
- 没有判断起点会重复计算
|
||||
- 时间复杂度会变成 O(n²)
|
||||
- 示例:[1,2,3,4] 会计算 4 次
|
||||
|
||||
---
|
||||
|
||||
### 错误3:使用 list 而不是 set
|
||||
|
||||
❌ **错误代码**:
|
||||
```go
|
||||
// 使用 list 查找
|
||||
if contains(nums, num-1) { // O(n)
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
✅ **正确代码**:
|
||||
```go
|
||||
// 使用 set 查找
|
||||
if numSet[num-1] { // O(1)
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**原因**:
|
||||
- `list` 查找是 O(n)
|
||||
- `set` 查找是 O(1)
|
||||
- 总复杂度会变成 O(n²)
|
||||
|
||||
---
|
||||
|
||||
## 进阶问题
|
||||
|
||||
### Q1: 如果需要返回最长序列本身?
|
||||
|
||||
```go
|
||||
func longestConsecutiveSequence(nums []int) []int {
|
||||
numSet := make(map[int]bool)
|
||||
for _, num := range nums {
|
||||
numSet[num] = true
|
||||
}
|
||||
|
||||
longest := 0
|
||||
start := 0 // 记录序列起点
|
||||
|
||||
for num := range numSet {
|
||||
if !numSet[num-1] {
|
||||
currentNum := num
|
||||
current := 1
|
||||
|
||||
for numSet[currentNum+1] {
|
||||
currentNum++
|
||||
current++
|
||||
}
|
||||
|
||||
if current > longest {
|
||||
longest = current
|
||||
start = num
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 构建结果
|
||||
result := make([]int, longest)
|
||||
for i := 0; i < longest; i++ {
|
||||
result[i] = start + i
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Q2: 如果数据量很大,如何优化内存?
|
||||
|
||||
**思路**:使用布隆过滤器(Bloom Filter)
|
||||
|
||||
```go
|
||||
// 布隆过滤器可以节省内存,但有误判率
|
||||
// 适用于大数据场景
|
||||
```
|
||||
|
||||
**注意**:
|
||||
- 布隆过滤器有误判率
|
||||
- 需要根据场景调整参数
|
||||
- 适合对准确性要求不高的场景
|
||||
|
||||
---
|
||||
|
||||
## P7 加分项
|
||||
|
||||
### 深度理解
|
||||
- **哈希表的作用**:O(1) 查找,实现 O(n) 时间复杂度
|
||||
- **序列起点判断**:避免重复计算,保证 O(n) 时间
|
||||
- **空间换时间**:用 O(n) 空间换取 O(n) 时间
|
||||
|
||||
### 实战扩展
|
||||
- **大数据场景**:分布式计算、分片处理
|
||||
- **内存优化**:布隆过滤器、位图
|
||||
- **业务场景**:用户活跃度分析、时间窗口统计
|
||||
|
||||
### 变形题目
|
||||
1. 最长连续序列(允许重复)
|
||||
2. 最长等差序列
|
||||
3. 最长递增子序列
|
||||
|
||||
---
|
||||
|
||||
## 总结
|
||||
|
||||
**核心要点**:
|
||||
1. **哈希表**:O(1) 查找,快速判断元素是否存在
|
||||
2. **序列起点判断**:避免重复计算,保证 O(n) 时间
|
||||
3. **空间换时间**:用 O(n) 空间换取 O(n) 时间
|
||||
|
||||
**易错点**:
|
||||
- 忘记去重
|
||||
- 没有判断序列起点
|
||||
- 使用 list 而不是 set
|
||||
|
||||
**最优解法**:哈希表 + 序列起点判断,时间 O(n),空间 O(n)
|
||||
|
||||
Reference in New Issue
Block a user