掘金刷题之路 Day 13 | 豆包MarsCode AI刷题

133 阅读5分钟

在编程学习的过程中,刷题是一个必不可少的环节,它不仅帮助我们巩固基础知识,还能提升解题思维与算法能力。在这方面,豆包AI刷题平台通过其丰富的功能设计,为学习者提供了极大的便利和帮助。 云端编辑器,豆包AI刷题平台内置了云端编程编辑器,可以在线编写、调试和提交代码,免去了本地环境配置的烦恼。

1. 功能亮点:精选真题

豆包AI刷题平台提供了精选的真题库,这些题目来自各种真实的面试和竞赛,覆盖了从基础到高级的各类问题,极大地提升了学习的针对性与实用性。

题解:判断数据表依赖关系是否正常

问题分析

在离线数据仓库的建设过程中,各个表之间往往存在着依赖关系。某些表的数据产出依赖于其他表的数据,如果依赖关系存在循环,那么这些表的数据将无法顺利产出,这在实际的数据处理过程中是不可接受的。

我们需要判断给定的一组数据表依赖关系中是否存在循环依赖。如果存在循环依赖,则数据无法产出,返回 false;否则返回 true

关键问题

这是一个典型的 有向图 问题,其中每个数据表都可以看作一个图的节点,而每一条依赖关系则是一个有向边。我们要判断图中是否存在环,环的存在意味着存在循环依赖,无法顺利产出数据。

我的思路

  1. 图的构建:首先,我们可以把每个数据表视为图的节点,依赖关系作为有向边构建图。

  2. 检测有向图是否有环:使用深度优先搜索(DFS)检测图中是否存在环。具体地,使用颜色标记法来追踪节点的状态:

    • 白色:节点未访问。
    • 灰色:节点正在访问(即在当前的递归路径中)。
    • 黑色:节点已完全访问过,不再检查。

    如果在递归过程中遇到灰色节点,说明存在环,返回 false。如果所有节点都能完成DFS遍历而没有遇到环,返回 true

  3. 图的表示:可以使用邻接表的方式表示图,关系中每一行表示一个节点及其依赖的其他节点。

实现代码

import java.util.*;

public class Main {
    
    public static boolean solution(String[][] relations) {
        // Step 1: Build the graph
        Map<String, List<String>> graph = new HashMap<>();
        for (String[] relation : relations) {
            String node = relation[0];
            for (int i = 1; i < relation.length; i++) {
                graph.computeIfAbsent(relation[i], k -> new ArrayList<>()).add(node);
            }
        }

        // Step 2: Set up tracking for DFS (visited states)
        Map<String, Integer> state = new HashMap<>();
        // 0 = unvisited, 1 = visiting, 2 = visited

        // Step 3: DFS to detect cycle
        for (String node : graph.keySet()) {
            if (state.getOrDefault(node, 0) == 0) {
                if (hasCycle(node, graph, state)) {
                    return false;
                }
            }
        }

        return true;
    }

    // DFS to check for cycles
    private static boolean hasCycle(String node, Map<String, List<String>> graph, Map<String, Integer> state) {
        state.put(node, 1); // mark as visiting (gray)
        
        if (graph.containsKey(node)) {
            for (String neighbor : graph.get(node)) {
                if (state.getOrDefault(neighbor, 0) == 1) {
                    return true; // cycle found
                }
                if (state.getOrDefault(neighbor, 0) == 0 && hasCycle(neighbor, graph, state)) {
                    return true;
                }
            }
        }
        
        state.put(node, 2); // mark as visited (black)
        return false;
    }

    public static void main(String[] args) {
        // Test cases
        System.out.println(solution(new String[][] {
            {"A", "B", "C"}, 
            {"B", "D"}, 
            {"C", "E"}, 
            {"D", "A"}
        }) == false); // Cycle exists: A -> B -> D -> A

        System.out.println(solution(new String[][] {
            {"A", "B", "C", "D", "E"},
            {"F", "G", "H", "I"},
            {"J", "K", "L", "M", "A"},
            {"N", "O", "P", "Q"},
            {"E", "H", "I", "J"},
            {"R", "S", "T", "U"},
            {"V", "W", "X"},
            {"Y", "Z"}
        }) == false); // No cycle, data will be generated

        System.out.println(solution(new String[][] {
            {"A", "B", "C"}, 
            {"B", "C"}, 
            {"C", "A"}
        }) == false); // Cycle exists: A -> B -> C -> A
    }
}

题解分析

  1. 图构建:我们将数据表的依赖关系转化为有向图。在这个图中,每个数据表是一个节点,依赖关系是从被依赖表指向依赖表的有向边。例如,A,B,C 表示 A 表依赖 B 和 C,我们将 B 和 C 都作为 A 的父节点。

  2. DFS 检测环:我们使用深度优先搜索(DFS)来遍历图,同时利用状态数组记录节点的访问状态:

    • 0 表示未访问。
    • 1 表示正在访问(即当前递归路径中的节点)。
    • 2 表示已访问(即已经完成了该节点及其所有子节点的遍历)。

    在 DFS 遍历过程中,如果我们发现某个节点处于“正在访问”状态,则说明图中存在环,即存在循环依赖。

  3. 时间复杂度:图的构建和DFS遍历的时间复杂度都是 O(V + E),其中 V 是节点数(数据表数量),E 是边的数量(依赖关系数量)。由于数据表的数量小于 10000,算法能够高效处理。

结合刷题实践

在刷题过程中,我们不仅要掌握如何解决特定的算法问题,还要理解问题背后的深层次概念。在本题中,图的遍历环的检测是一个经典的算法问题,而它的解决方案——DFS 检测有向图中的环——也能帮助我们理解如何在复杂的系统中判断是否存在死锁或循环依赖。这对于设计数据仓库和数据管道中的依赖关系尤为重要。

豆包AI 刷题

平台提供了针对算法和编程基础的精选真题,并通过云端编辑器帮助我们在真实环境中实践这些算法。通过不断刷题,我们能够提高问题分解能力和解决复杂问题的思维方式,这在数据工程、系统设计等实际项目中非常有价值。

总结

通过这道题的解决,我们学习了如何通过图的遍历来检测依赖关系中的循环问题,这一思路不仅适用于数据仓库中的依赖管理,也能帮助我们解决更广泛的编程问题。刷题不仅能帮助我们掌握解题技巧,还能深入理解问题本质,提升问题分析与解决能力,尤其是在学习平台提供的真题中,每道题目都能带给我们新的思维启发。