Java强连通分量知识点(含面试大厂题和源码)

在大厂面试中,与拓扑排序相关的问题通常涉及到对图的处理和算法设计。以下是三道可能出现在大厂面试中的编程题目,以及相应的Java源码实现。

题目 1:课程依赖关系

描述
给定一个课程列表和课程之间的依赖关系,为所有课程安排一个上课时间表。每个课程都有一个先修课程列表,如果课程 A 依赖于课程 B,则 B 必须在 A 之前上课。返回一个按时间顺序排列的课程列表,如果无法安排,则返回空列表。

示例

输入: [["a", "b"], ["b", "c"], ["a", "c"]]
输出: ["a", "b", "c"]

Java 源码

import java.util.*;

public class CourseSchedule {
    private Map<String, List<String>> graph;
    private Set<String> visited;
    private List<String> order;

    public List<String> findOrder(String[] courses) {
        graph = new HashMap<>();
        visited = new HashSet<>();
        order = new ArrayList<>();
        for (String course : courses) {
            String[] coursePair = course.split(", ");
            if (!graph.containsKey(coursePair[1])) {
                graph.put(coursePair[1], new ArrayList<>());
            }
            graph.get(coursePair[1]).add(coursePair[0]);
        }

        for (String course : graph.keySet()) {
            if (!visited.contains(course)) {
                dfs(course);
            }
        }

        return order.isEmpty() ? new ArrayList<>() : order;
    }

    private void dfs(String course) {
        visited.add(course);
        for (String preCourse : graph.get(course)) {
            if (!visited.contains(preCourse)) {
                dfs(preCourse);
            }
        }
        order.add(0, course); // 逆序添加到列表中以保持拓扑顺序
    }

    public static void main(String[] args) {
        CourseSchedule solution = new CourseSchedule();
        String[] courses = {"a, b", "b, c", "a, c"};
        List<String> result = solution.findOrder(courses);
        System.out.println("Course order: " + result);
    }
}

题目 2:项目任务调度

描述
给定一个项目任务列表和任务之间的依赖关系,每个任务都有一个唯一的标识符和一个任务完成时间。如果任务 A 依赖于任务 B,则 B 必须在 A 之前完成。返回一个按完成时间顺序排列的任务列表,如果无法调度,则返回空列表。

示例

输入: tasks = ["a(2)", "b(1)", "c(5)", "d(3)", "e(2)"], dependencies = ["a(b)", "e(c)"]
输出: ["b", "e", "a", "d", "c"]

Java 源码

import java.util.*;

public class TaskScheduler {
    private Map<String, Integer> taskTime;
    private Map<String, List<String>> dependencies;
    private Queue<String> queue;

    public List<String> scheduleTasks(String[] tasks, String[] dependencies) {
        taskTime = new HashMap<>();
        for (String task : tasks) {
            String[] parts = task.split("\\(");
            taskTime.put(parts[0], Integer.parseInt(parts[1]));
        }
        this.dependencies = new HashMap<>();
        for (String dep : dependencies) {
            String[] parts = dep.split("(?=\\()");
            this.dependencies.put(parts[0], parts[1]);
        }
        queue = new LinkedList<>();

        for (String task : taskTime.keySet()) {
            if (!dependencies.containsKey(task)) {
                queue.add(task);
            }
        }

        while (!queue.isEmpty()) {
            String task = queue.poll();
            if (taskTime.containsKey(task)) {
                for (String nextTask : taskTime.keySet()) {
                    if (dependencies.get(nextTask).equals(task)) {
                        taskTime.remove(nextTask);
                        if (taskTime.size() == 1) {
                            return Arrays.asList(task);
                        }
                        for (String t : taskTime.keySet()) {
                            if (!queue.contains(t)) {
                                queue.add(t);
                            }
                        }
                    }
                }
            }
        }
        return Collections.emptyList();
    }

    public static void main(String[] args) {
        TaskScheduler solution = new TaskScheduler();
        String[] tasks = {"a(2)", "b(1)", "c(5)", "d(3)", "e(2)"};
        String[] dependencies = {"a(b)", "e(c)"};
        List<String> result = solution.scheduleTasks(tasks, dependencies);
        System.out.println("Task order: " + result);
    }
}

题目 3:活动选择问题

描述
给定一系列活动和它们的开始时间及结束时间,选择最大的活动集合,其中活动之间不会相互重叠。每次选择一个活动时,都必须在开始时间早于结束时间的前提下,选择结束时间最早的活动。

示例

输入: [[1, 2], [3, 4], [2, 6]]
输出: [2, 3] 或 [3, 4]

Java 源码

import java.util.*;

public class ActivitySelection {
    public int[][] maxActivities(int[][]活动时间) {
        Arrays.sort(活动时间, (a, b) -> a[1] - b[1]); // 按结束时间排序
        int n =活动时间.length;
        int[] dp = new int[n];
        int[] prev = new int[n];
        int count = 1;

        dp[0] = 1;
        prev[0] = -1;

        for (int i = 1; i < n; i++) {
            if (活动时间[i][0] >= dp[i - 1]) {
                // 如果当前活动的开始时间大于等于上一个活动的结束时间,则选择
                dp[i] = dp[i - 1] + 1;
                prev[i] = i - 1;
            } else {
                dp[i] = dp[i - 1];
                prev[i] = prev[i - 1];
            }
            if (dp[i] > count) {
                count = dp[i];
            }
        }

        int[] result = new int[count];
        for (int i = 0; i < count; i++) {
            result[i] =活动时间[prev[n - 1 - i]][0];
        }
        return new int[][]{{result[0], dp[n - 1]}, {活动时间[prev[n - 1]][0], dp[n - 1]}};
    }

    public static void main(String[] args) {
        ActivitySelection solution = new ActivitySelection();
        int[][] 活动时间 = {{1, 2}, {3, 4}, {2, 6}};
        int[][] result = solution.maxActivities(活动时间);
        System.out.println("Max activities: " + Arrays.deepToString(result));
    }
}

这些题目和源码展示了拓扑排序在解决实际问题中的应用。在面试中,能够根据问题的特点选择合适的算法并实现其解决方案是非常重要的。希望这些示例能够帮助你更好地准备面试!在大厂面试中,与强连通分量(SCC)相关的问题通常涉及到图论和算法设计。以下是三道可能出现在大厂面试中的编程题目,以及相应的Java源码实现。

题目 1:课程完成顺序

描述
给定一个课程之间的先修课程列表,每个课程都有一个先修课程和对应的课程编号。如果学生要完成所有课程,确定一个课程完成的顺序。如果不可能完成所有课程,则返回空列表。

示例

输入: [["a", "b"], ["c", "d"], ["b", "c"], ["d", "a"]]
输出: ["d", "c", "b", "a"] 或其他有效的顺序

Java 源码

import java.util.*;

public class CourseCompletionOrder {
    private Map<String, List<String>> prerequisites;
    private Set<String> visited;
    private List<String> order;

    public List<String> findOrder(String[] courses, String[][] prerequisites) {
        this.prerequisites = new HashMap<>();
        this.visited = new HashSet<>();
        this.order = new ArrayList<>();
        for (String[] course : prerequisites) {
            this.prerequisites.put(course[1], new ArrayList<>());
        }
        for (String[] course : prerequisites) {
            this.prerequisites.get(course[1]).add(course[0]);
        }
        for (String course : courses) {
            if (!visited.contains(course)) {
                dfs(course);
            }
        }
        return order.isEmpty() ? Collections.emptyList() : order;
    }

    private void dfs(String course) {
        visited.add(course);
        for (String preCourse : prerequisites.get(course)) {
            if (!visited.contains(preCourse)) {
                dfs(preCourse);
            }
        }
        order.add(0, course); // 逆序添加到列表中以保持完成顺序
    }

    public static void main(String[] args) {
        CourseCompletionOrder solution = new CourseCompletionOrder();
        String[] courses = {"a", "b", "c", "d"};
        String[][] prerequisites = {{"a", "b"}, {"c", "d"}, {"b", "c"}, {"d", "a"}};
        List<String> result = solution.findOrder(courses, prerequisites);
        System.out.println("Course completion order: " + result);
    }
}

题目 2:社交网络中的强关系

描述
给定一个社交网络的联系列表,每个用户都有一个或多个朋友。定义一个强关系为如果 A 是 B 的朋友,B 也是 A 的朋友。找出社交网络中的所有强关系组。

示例

输入: friendships = [["alice", "bob"], ["bob", "carol"], ["alice", "carol"]]
输出: [["alice", "bob", "carol"]]

Java 源码

import java.util.*;

public class StrongRelationships {
    private Map<String, List<String>> friendships;

    public List<List<String>> findStrongRelationships(String[][] friendships) {
        this.friendships = new HashMap<>();
        for (String[] friendship : friendships) {
            if (!this.friendships.containsKey(friendship[0])) {
                this.friendships.put(friendship[0], new ArrayList<>());
            }
            this.friendships.get(friendship[0]).add(friendship[1]);
            if (!this.friendships.containsKey(friendship[1])) {
                this.friendships.put(friendship[1], new ArrayList<>());
            }
            this.friendships.get(friendship[1]).add(friendship[0]);
        }
        List<List<String>> strongRelationships = new ArrayList<>();
        for (List<String> group : friendships.values()) {
            if (group.size() > 1) {
                strongRelationships.add(new ArrayList<>(group));
            }
        }
        return strongRelationships;
    }

    public static void main(String[] args) {
        StrongRelationships solution = new StrongRelationships();
        String[][] friendships = {{"alice", "bob"}, {"bob", "carol"}, {"alice", "carol"}};
        List<List<String>> result = solution.findStrongRelationships(friendships);
        System.out.println("Strong relationships: " + result);
    }
}

题目 3:网络中的强连通区域

描述
给定一个网络的连接列表,网络中的每个节点都可能存在多个连接。找出网络中的所有强连通区域。

示例

输入: connections = [[1, 2], [2, 3], [3, 1], [4, 5]]
输出: [[1, 2, 3], [4, 5]]

Java 源码

import java.util.*;

public class StronglyConnectedRegions {
    private class Node {
        int value;
        List<Node> neighbors;

        public Node(int value) {
            this.value = value;
            this.neighbors = new ArrayList<>();
        }
    }

    public List<List<Integer>> findStronglyConnectedRegions(int[][] connections) {
        Map<Integer, Node> nodes = new HashMap<>();
        List<List<Integer>> regions = new ArrayList<>();
        for (int[] connection : connections) {
            Node u = nodes.getOrDefault(connection[0], new Node(connection[0]));
            Node v = nodes.getOrDefault(connection[1], new Node(connection[1]));
            u.neighbors.add(v);
            nodes.put(u.value, u);
            nodes.put(v.value, v);
        }
        Set<Integer> visited = new HashSet<>();
        for (Node node : nodes.values()) {
            if (!visited.contains(node.value)) {
                dfs(node, regions);
            }
        }
        return regions;
    }

    private void dfs(Node node, List<List<Integer>> regions) {
        visited.add(node.value);
        List<Integer> region = new ArrayList<>();
        region.add(node.value);
        for (Node neighbor : node.neighbors) {
            if (!visited.contains(neighbor.value)) {
                dfs(neighbor, regions);
            }
        }
        if (!region.isEmpty()) {
            regions.add(region);
        }
    }

    public static void main(String[] args) {
        StronglyConnectedRegions solution = new StronglyConnectedRegions();
        int[][] connections = {{1, 2}, {2, 3}, {3, 1}, {4, 5}};
        List<List<Integer>> result = solution.findStronglyConnectedRegions(connections);
        System.out.println("Strongly connected regions: " + result);
    }
}

这些题目和源码展示了强连通分量在不同场景下的应用。在面试中,能够根据问题的特点选择合适的算法并实现其解决方案是非常重要的。希望这些示例能够帮助你更好地准备面试!

  • 16
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值