赞
踩
并查集(Union-Find)是一种用于处理一些不交集合合并及集合间元素查找问题的数据结构。它提供了两个主要的操作:查找(Find)和合并(Union)。查找操作用于确定某个元素属于哪个集合,而合并操作用于将两个集合合并为一个集合。
public class UnionFind { private int[] parent; private int[] rank; public UnionFind(int n) { parent = new int[n]; rank = new int[n]; for (int i = 0; i < n; i++) { parent[i] = i; rank[i] = 0; } } public int find(int x) { if (x != parent[x]) { parent[x] = find(parent[x]); // 路径压缩 } return parent[x]; } public boolean union(int x, int y) { int rootX = find(x); int rootY = find(y); if (rootX == rootY) { return false; // 已经在同一集合中 } if (rank[rootX] > rank[rootY]) { parent[rootY] = rootX; } else if (rank[rootX] < rank[rootY]) { parent[rootX] = rootY; } else { parent[rootY] = rootX; rank[rootX]++; } return true; } public static void main(String[] args) { UnionFind uf = new UnionFind(5); uf.union(0, 1); uf.union(1, 2); System.out.println("Find 0: " + uf.find(0)); // 输出 0 System.out.println("Find 1: " + uf.find(1)); // 输出 0 System.out.println("Find 2: " + uf.find(2)); // 输出 0 } }
岛屿数量:
描述:给定一个由 ‘1’(陆地)和 ‘0’(水)组成的二维网格,每次移动都只能从陆地移动到相邻的陆地,计算网格中的岛屿数量。
示例:
输入: grid = [
["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","0","1","0"],
["0","0","0","1","1"]
]
输出: 3
Java 源码:使用并查集的查找和合并操作来计算岛屿数量。
课程选修:
描述:给定一个课程列表和课程之间的先修课程关系,判断是否可能完成所有课程的学习。
示例:
输入: courses = ["a", "b", "c", "d"], prerequisites = [["a", "b"], ["c", "d"]]
输出: true
Java 源码:使用并查集来检测是否存在环,如果存在环则无法完成所有课程。
社交网络好友关系:
描述:给定一个社交网络中的好友关系列表,判断任意两个人是否是朋友(直接或间接)。
示例:
输入: friendships = [["alice", "bob"], ["bob", "carol"], ["alice", "carol"]]
输出: true(alice 和 carol 是朋友)
Java 源码:使用并查集来处理好友关系的查询,判断两个用户是否在同一个集合中。
这些题目和源码展示了并查集在解决实际问题中的应用。在面试中,能够根据问题的特点选择合适的算法并实现其解决方案是非常重要的。希望这些示例能够帮助你更好地准备面试!
描述:
在一个社交网络中,每个用户都可能被恶意软件感染。编写一个程序,确定在最佳情况下,最少需要多少个用户来防止恶意软件的传播。每个用户可以选择感染0个、1个或无限多个其他用户。用户按照给定的顺序进行操作,每个用户的操作是独立的。
示例:
输入:
users = [
["a", 1],
["b", 2],
["c", 3],
["d", 4],
["e", 5]
],
ops = [
["a", "b"],
["c", "a"],
["d", "e"],
["e", "a"]
]
输出: 2
Java 源码:
public class MinMalwareSpread { public int minMalwareSpread(int[][] users, int[][] ops) { int n = users.length; int[] parent = new int[n + 1]; for (int i = 0; i <= n; i++) { parent[i] = i; } for (int[] op : ops) { int a = find(parent, op[0]); int b = find(parent, op[1]); if (a != b) { parent[a] = b; } } int max = 0; for (int i = 0; i < ops.length; i++) { int a = find(parent, users[ops[i][0]][0]); int b = find(parent, users[ops[i][1]][0]); if (a == b) { return 1; } max = Math.max(max, Math.max(users[ops[i][0]][1], users[ops[i][1]][1])); } return Math.max(1, max); } private int find(int[] parent, int x) { if (parent[x] != x) { parent[x] = find(parent, parent[x]); } return parent[x]; } public static void main(String[] args) { MinMalwareSpread solution = new MinMalwareSpread(); int[][] users = { {1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5} }; int[][] ops = { {1, 2}, {3, 1}, {4, 5}, {5, 1} }; int result = solution.minMalwareSpread(users, ops); System.out.println("Minimum number of users to prevent spread: " + result); } }
描述:
给定一个无向图,返回其所有连通分量的列表。连通分量是一个子图,其中任意两个顶点都是连通的。
示例:
输入:
graph = [
[1, 2, 3],
[0, 2],
[1, 3],
[2, 4],
[3, 4]
]
输出: [[0, 1, 2, 3], [4]]
Java 源码:
public class ConnectedComponents { public List<List<Integer>> connectedComponents(int[][] graph) { int n = graph.length; int[] parent = new int[n]; for (int i = 0; i < n; i++) { parent[i] = i; } List<List<Integer>> components = new ArrayList<>(); for (int i = 0; i < n; i++) { if (parent[i] == i) { List<Integer> component = new ArrayList<>(); dfs(graph, i, parent, component); components.add(component); } } return components; } private void dfs(int[][] graph, int node, int[] parent, List<Integer> component) { component.add(node); for (int neighbor : graph[node]) { int p = find(parent, neighbor); if (p == neighbor) { dfs(graph, neighbor, parent, component); } } } private int find(int[] parent, int x) { if (parent[x] != x) { parent[x] = find(parent, parent[x]); } return parent[x]; } public static void main(String[] args) { ConnectedComponents solution = new ConnectedComponents(); int[][] graph = { {1, 2, 3}, {0, 2}, {1, 3}, {2, 4}, {3, 4} }; List<List<Integer>> components = solution.connectedComponents(graph); System.out.println("Connected components: " + components); } }
描述:
给定两个二叉树的根节点,判断它们是否是相同的树。两个二叉树相同,当且仅当它们的结构相同,并且所有对应位置的节点具有相同的值。
示例:
输入:
tree1 = [1, 2, 3],
tree2 = [1, 2, 3]
输出: true
Java 源码:
public class IsSameTree { public boolean isSameTree(TreeNode tree1, TreeNode tree2) { if (tree1 == null && tree2 == null) { return true; } if (tree1 == null || tree2 == null) { return false; } return (tree1.val == tree2.val) && isSameTree(tree1.left, tree2.left) && isSameTree(tree1.right, tree2.right); } public static void main(String[] args) { IsSameTree solution = new IsSameTree(); TreeNode tree1 = new TreeNode(1); tree1.left = new TreeNode(2); tree1.right = new TreeNode(3); TreeNode tree2 = new TreeNode(1); tree2.left = new TreeNode(2); tree2.right = new TreeNode(3); boolean result = solution.isSameTree(tree1, tree2); System.out.println("Trees are the same: " + result); } } class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { val = x; } }
这些题目和源码展示了并查集在解决实际问题中的应用。在面试中,能够根据问题的特点选择合适的算法并实现其解决方案是非常重要的。希望这些示例能够帮助你更好地准备面试!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。