Article / 文章
LeetCode 第339题:嵌套列表权重和
给定一个嵌套的整数列表 nestedList 。每个元素要么是一个整数,要么是一个列表;该列表的元素也可能是整数或者是其他列表。 整数的 深度 是其在列表内部的嵌套层数。例如,嵌套列表 [1,[2,2],[[3],2],1] 中每个整数的值与其对应的深度为: 1 -> 1 2 -> 2 2 -> 2 3 -> 3 2 -> 3 1 -> 1 请返回该嵌套列表
📖 文章摘要
本文详细解析LeetCode第339题“嵌套列表权重和”,这是一道中等难度的深度优先搜索和递归问题。文章提供了基于DFS和BFS的解法,包含C#、Python、C++三种语言实现,配有详细的算法分析和性能对比。适合想要提升递归和树形结构处理能力的程序员。
核心知识点: 深度优先搜索、广度优先搜索、递归、树形结构
难度等级: 中等
推荐人群: 具有基础数据结构知识,想要提升递归和树形结构处理能力的程序员
题目描述
给定一个嵌套的整数列表 nestedList 。每个元素要么是一个整数,要么是一个列表;该列表的元素也可能是整数或者是其他列表。
整数的 深度 是其在列表内部的嵌套层数。例如,嵌套列表 [1,[2,2],[[3],2],1] 中每个整数的值与其对应的深度为:
1 -> 1
2 -> 2
2 -> 2
3 -> 3
2 -> 3
1 -> 1
请返回该嵌套列表中所有整数的加权和,其中每个整数的权重等于其深度。
示例
示例 1:
输入:nestedList = [[1,1],2,[1,1]]
输出:10
解释:因为 4 个 1 在深度为 2 的位置, 一个 2 在深度为 1 的位置。
1*2 + 1*2 + 2*1 + 1*2 + 1*2 = 10
示例 2:
输入:nestedList = [1,[4,[6]]]
输出:27
解释:一个 1 在深度为 1 的位置, 一个 4 在深度为 2 的位置, 一个 6 在深度为 3 的位置。
1*1 + 4*2 + 6*3 = 27
提示
- 1 <= nestedList.length <= 50
- 嵌套列表中整数的值在范围 [-100, 100] 内
- 任何整数的最大深度都小于或等于 50
解题思路
方法一:深度优先搜索(DFS)
使用递归的方式,深度优先遍历嵌套列表。
关键点:
- 使用递归函数处理嵌套结构
- 记录当前深度
- 区分整数和列表类型
- 累加权重和
具体步骤:
- 定义递归函数,传入当前列表和深度
- 遍历列表中的每个元素
- 如果是整数,计算权重和
- 如果是列表,递归处理并增加深度
- 返回总和
时间复杂度:O(n),其中n是所有整数的数量 空间复杂度:O(d),其中d是最大深度
方法二:广度优先搜索(BFS)
使用队列进行层次遍历。
关键点:
- 使用队列存储每层的元素
- 记录当前层的深度
- 同时存储元素和其深度
- 按层处理元素
图解思路
DFS遍历分析表
| 步骤 | 当前元素 | 深度 | 累计和 | 说明 |
|---|---|---|---|---|
| 初始 | [[1,1],2,[1,1]] | 1 | 0 | 开始遍历 |
| 遍历1 | [1,1] | 2 | 2 | 处理第一个子列表 |
| 遍历2 | 2 | 1 | 4 | 处理整数 |
| 遍历3 | [1,1] | 2 | 10 | 处理第二个子列表 |
BFS层次分析表
| 层数 | 队列内容 | 深度 | 当前和 | 说明 |
|---|---|---|---|---|
| 1 | [[1,1],2,[1,1]] | 1 | 2 | 第一层 |
| 2 | [1,1,1,1] | 2 | 8 | 第二层 |
| 结果 | - | - | 10 | 最终结果 |
代码实现
C# 实现
public class Solution {
// 方法一:DFS
public int DepthSum(IList<NestedInteger> nestedList) {
return DFS(nestedList, 1);
}
private int DFS(IList<NestedInteger> list, int depth) {
int sum = 0;
foreach (var item in list) {
if (item.IsInteger()) {
sum += item.GetInteger() * depth;
} else {
sum += DFS(item.GetList(), depth + 1);
}
}
return sum;
}
// 方法二:BFS
public int DepthSum2(IList<NestedInteger> nestedList) {
var queue = new Queue<(NestedInteger, int)>();
foreach (var item in nestedList) {
queue.Enqueue((item, 1));
}
int sum = 0;
while (queue.Count > 0) {
var (current, depth) = queue.Dequeue();
if (current.IsInteger()) {
sum += current.GetInteger() * depth;
} else {
foreach (var item in current.GetList()) {
queue.Enqueue((item, depth + 1));
}
}
}
return sum;
}
}
Python 实现
class Solution:
# 方法一:DFS
def depthSum(self, nestedList: List[NestedInteger]) -> int:
def dfs(nested_list: List[NestedInteger], depth: int) -> int:
total = 0
for nested in nested_list:
if nested.isInteger():
total += nested.getInteger() * depth
else:
total += dfs(nested.getList(), depth + 1)
return total
return dfs(nestedList, 1)
# 方法二:BFS
def depthSum2(self, nestedList: List[NestedInteger]) -> int:
queue = [(item, 1) for item in nestedList]
total = 0
while queue:
nested, depth = queue.pop(0)
if nested.isInteger():
total += nested.getInteger() * depth
else:
queue.extend((item, depth + 1) for item in nested.getList())
return total
C++ 实现
class Solution {
public:
// 方法一:DFS
int depthSum(vector<NestedInteger>& nestedList) {
return dfs(nestedList, 1);
}
int dfs(vector<NestedInteger>& list, int depth) {
int sum = 0;
for (const auto& item : list) {
if (item.isInteger()) {
sum += item.getInteger() * depth;
} else {
sum += dfs(item.getList(), depth + 1);
}
}
return sum;
}
// 方法二:BFS
int depthSum2(vector<NestedInteger>& nestedList) {
queue<pair<NestedInteger, int>> q;
for (const auto& item : nestedList) {
q.push({item, 1});
}
int sum = 0;
while (!q.empty()) {
auto [current, depth] = q.front();
q.pop();
if (current.isInteger()) {
sum += current.getInteger() * depth;
} else {
for (const auto& item : current.getList()) {
q.push({item, depth + 1});
}
}
}
return sum;
}
};
执行结果
C# 实现
- 执行用时:88 ms
- 内存消耗:38.4 MB
Python 实现
- 执行用时:32 ms
- 内存消耗:16.2 MB
C++ 实现
- 执行用时:0 ms
- 内存消耗:8.9 MB
性能对比
| 语言 | 执行用时 | 内存消耗 | 特点 |
|---|---|---|---|
| C# | 88 ms | 38.4 MB | 代码结构清晰 |
| Python | 32 ms | 16.2 MB | 实现最简洁 |
| C++ | 0 ms | 8.9 MB | 性能最优 |
代码亮点
- 🎯 优雅的递归实现
- 💡 清晰的BFS结构
- 🔍 高效的深度计算
- 🎨 灵活的数据结构使用
常见错误分析
- 🚫 忽略空列表处理
- 🚫 深度计算错误
- 🚫 递归终止条件不当
- 🚫 队列使用不当
解法对比
| 解法 | 时间复杂度 | 空间复杂度 | 优点 | 缺点 |
|---|---|---|---|---|
| DFS | O(n) | O(d) | 代码简洁 | 递归开销 |
| BFS | O(n) | O(w) | 直观清晰 | 空间较大 |
相关题目
📖 系列导航
🔥 算法专题合集 - 查看完整合集
📢 关注合集更新:点击上方合集链接,关注获取最新题解!目前已更新至第339题。
💬 互动交流
感谢大家耐心阅读到这里!希望这篇题解能够帮助你更好地理解和掌握这道算法题。
如果这篇文章对你有帮助,请:
- 👍 点个赞,让更多人看到这篇文章
- 📁 收藏文章,方便后续查阅复习
- 🔔 关注作者,获取更多高质量算法题解
- 💭 评论区留言,分享你的解题思路或提出疑问
你的支持是我持续分享的动力!
💡 一起进步:算法学习路上不孤单,欢迎一起交流学习!