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)

使用递归的方式,深度优先遍历嵌套列表。

关键点:

  • 使用递归函数处理嵌套结构
  • 记录当前深度
  • 区分整数和列表类型
  • 累加权重和

具体步骤:

  1. 定义递归函数,传入当前列表和深度
  2. 遍历列表中的每个元素
  3. 如果是整数,计算权重和
  4. 如果是列表,递归处理并增加深度
  5. 返回总和

时间复杂度: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 性能最优

代码亮点

  1. 🎯 优雅的递归实现
  2. 💡 清晰的BFS结构
  3. 🔍 高效的深度计算
  4. 🎨 灵活的数据结构使用

常见错误分析

  1. 🚫 忽略空列表处理
  2. 🚫 深度计算错误
  3. 🚫 递归终止条件不当
  4. 🚫 队列使用不当

解法对比

解法 时间复杂度 空间复杂度 优点 缺点
DFS O(n) O(d) 代码简洁 递归开销
BFS O(n) O(w) 直观清晰 空间较大

相关题目


📖 系列导航

🔥 算法专题合集 - 查看完整合集

📢 关注合集更新:点击上方合集链接,关注获取最新题解!目前已更新至第339题。


💬 互动交流

感谢大家耐心阅读到这里!希望这篇题解能够帮助你更好地理解和掌握这道算法题。

如果这篇文章对你有帮助,请:

  • 👍 点个赞,让更多人看到这篇文章
  • 📁 收藏文章,方便后续查阅复习
  • 🔔 关注作者,获取更多高质量算法题解
  • 💭 评论区留言,分享你的解题思路或提出疑问

你的支持是我持续分享的动力!

💡 一起进步:算法学习路上不孤单,欢迎一起交流学习!