面试官问我:"如何实现你项目中的这块代码."我说:"看好了."

首先假设传进来一个json结构比如

js 复制代码
   {node1:node2;
    node2:node3;
    node2:node4;
    node3:node5;
    node4;node5;}       

那现在要实现三个功能第一你要解析这个json结构,第二你要解析后来找到json结构的一个头节点,第三你需要找到任意一个节点的后继节点.

那我们现在来思考第一个功能解析,我期望的一个结构是

js 复制代码
{
    node1=[node2],
    node2=[node3, node4],
    node3=[node5],
    node4=[node5],
    node5=[nodeend],
    nodeend=[]
}

他本质上其实是一个邻接表Map<String, List<String>>他非常适合

  • 图遍历
  • 找路径
  • 拓扑排序
  • 检测环
  • 找入度/出度

来我们把具体代码实现一下

js 复制代码
public static Map<String, List<String>> parseGraph(String input) {
    Map<String, List<String>> graph = new HashMap<>();

    // 去掉首尾的 {}
    String content = input.substring(1, input.length() - 1);

    // 按 ; 切分每条边
    String[] relations = content.split(";");
    //form和to节点

    for (String relation : relations) {
        String[] pair = relation.split(":");
        String from = pair[0];
        String to = pair[1];

        // 如果 from 还没在 map 里,先放一个空列表
        if (!graph.containsKey(from)) {
            graph.put(from, new ArrayList<>());
        }
        graph.get(from).add(to);

        // 保证 to 节点也在 map 里
        if (!graph.containsKey(to)) {
            graph.put(to, new ArrayList<>());
        }
    }

    return graph;
}

上面我们对json结构进行了一个解析接下来呢我们来找到他的头节点

头节点是什么

在这张图里,头节点可以理解为:

没有任何前驱节点的节点,也就是入度为 0 的节点。

比如这里:

  • node2node1 指向
  • node3node2 指向
  • node4node2 指向
  • node5node3node4 指向
  • nodeendnode5 指向

只有 node1 没有被任何节点指向,所以它就是头节点。 接下来我们写一下代码

js 复制代码
//找头节点

public static List<String> findHeadNodes(Map<String, List<String>> graph) {
    List<String> result = new ArrayList<>();

    // 记录所有出现过的节点
    Set<String> allNodes = new HashSet<>();

    // 记录"被别人指向过"的节点
    Set<String> pointedNodes = new HashSet<>();

    // 遍历图
    for (String from : graph.keySet()) {
        // 当前 key 本身也是一个节点
        allNodes.add(from);

        // 当前节点的所有后继节点
        List<String> nextNodes = graph.get(from);

        for (String to : nextNodes) {
            // 后继节点也属于图中的节点
            allNodes.add(to);

            // to 被 from 指向过,说明它不是头节点
            pointedNodes.add(to);
        }
    }

    // 如果一个节点从来没有被指向过,那它就是头节点
    for (String node : allNodes) {
        if (!pointedNodes.contains(node)) {
            result.add(node);
        }
    }

    return result;
}

那最后一个问题的就非常简单了找到一个节点的后继节点

js 复制代码
public static List<String> findSuccessors(Map<String, List<String>> graph, String node) {
if (graph == null || node == null) {
return Collections.emptyList();
}
return graph.getOrDefault(node, Collections.emptyList());

}

就这样我们完美的解决了面试官的问题以及类似的问题都可以这样解决

相关推荐
ltl1 天前
Transformer 整体架构:一张图看懂
后端
ltl1 天前
Decoder 详解:为什么它天生适合生成
后端
ltl1 天前
Encoder 详解:6 层堆叠到底在做什么
后端
程序员cxuan1 天前
微信读书官方发了 skills,把我给秀麻了。
人工智能·后端·程序员
未若君雅裁1 天前
Spring AOP、日志切面与声明式事务原理
java·后端·spring
zhangxingchao1 天前
AI应用开发六:企业知识库
前端·人工智能·后端
红尘散仙1 天前
一个 `#[uniffi::export]`,把 Rust 接进 React Native
前端·后端·rust
红尘散仙1 天前
一行 `#[specta::specta]`,让 Tauri IPC 有类型
前端·后端·rust
XinZong1 天前
OpenClaw 中最经典的 6 款skill,真正能进工作流的 skills
javascript·后端
zhangxingchao1 天前
AI Agent 基础问题系统整理:从 LangChain、LangGraph、MCP 到 Agent 架构、记忆、工具调用与评估体系
前端·人工智能·后端