From fdafcff0ed741cc4ecb9243330b9c5b242e89605 Mon Sep 17 00:00:00 2001 From: algorithmzuo Date: Wed, 8 Feb 2023 22:22:57 +0800 Subject: [PATCH] modify code --- .../Code01_NumberOfMusicPlaylists.java | 72 +++++++++ ...02_VerticalOrderTraversalOfBinaryTree.java | 82 ++++++++++ .../Code03_WidthOfBinaryTree.java | 54 +++++++ .../Code04_MinimizeMalwareSpreadII.java | 144 ++++++++++++++++++ ...¥å…»çš„大厂算法é¢è¯•题(正在直播) | 60 ++++++++ 5 files changed, 412 insertions(+) create mode 100644 算法周更ç­/class_2023_02_2_week/Code01_NumberOfMusicPlaylists.java create mode 100644 算法周更ç­/class_2023_02_2_week/Code02_VerticalOrderTraversalOfBinaryTree.java create mode 100644 算法周更ç­/class_2023_02_2_week/Code03_WidthOfBinaryTree.java create mode 100644 算法周更ç­/class_2023_02_2_week/Code04_MinimizeMalwareSpreadII.java diff --git a/算法周更ç­/class_2023_02_2_week/Code01_NumberOfMusicPlaylists.java b/算法周更ç­/class_2023_02_2_week/Code01_NumberOfMusicPlaylists.java new file mode 100644 index 0000000..303c56a --- /dev/null +++ b/算法周更ç­/class_2023_02_2_week/Code01_NumberOfMusicPlaylists.java @@ -0,0 +1,72 @@ +package class_2023_02_2_week; + +// ä½ çš„éŸ³ä¹æ’­æ”¾å™¨é‡Œæœ‰ N 首ä¸åŒçš„æ­Œ +// 在旅途中,你的旅伴想è¦å¬ L 首歌(ä¸ä¸€å®šä¸åŒï¼Œå³ï¼Œå…许歌曲é‡å¤ +// 请你为她按如下规则创建一个播放列表 +// æ¯é¦–歌至少播放一次 +// ä¸€é¦–æ­Œåªæœ‰åœ¨å…¶ä»– K é¦–æ­Œæ’­æ”¾å®Œä¹‹åŽæ‰èƒ½å†æ¬¡æ’­æ”¾ +// 返回å¯ä»¥æ»¡è¶³è¦æ±‚çš„æ’­æ”¾åˆ—è¡¨çš„æ•°é‡ +// 由于答案å¯èƒ½éžå¸¸å¤§ï¼Œè¯·è¿”回它模 10^9 + 7 的结果 +// 测试链接 : https://leetcode.cn/problems/number-of-music-playlists/ +public class Code01_NumberOfMusicPlaylists { + + public static int mod = 1000000007; + + public static int limit = 100; + + // 阶乘表 + public static long[] fac = new long[limit + 1]; + + // 阶乘结果的乘法逆元表 + public static long[] inv = new long[limit + 1]; + + static { + fac[0] = inv[0] = 1; + for (int i = 1; i <= limit; i++) { + fac[i] = ((long) i * fac[i - 1]) % mod; + } + // 费马å°å®šç†è®¡ç®—乘法逆元 +// for (int i = 1; i <= limit; i++) { +// inv[i] = power(fac[i], mod - 2); +// } + // 费马å°å®šç†è®¡ç®—乘法逆元,优化如下 + // 这一å—å«ï¼šé˜¶ä¹˜çš„逆元倒推 + inv[limit] = power(fac[limit], mod - 2); + for (int i = limit; i > 1; i--) { + inv[i - 1] = ((long) i * inv[i]) % mod; + } + } + + // xçš„n次方,% mod之åŽï¼Œæ˜¯å¤šå°‘? + public static long power(long x, int n) { + long ans = 1; + while (n > 0) { + if ((n & 1) == 1) { + ans = (ans * x) % mod; + } + x = (x * x) % mod; + n >>= 1; + } + return ans; + } + + // n * logn + public static int numMusicPlaylists(int n, int l, int k) { + long cur, ans = 0, sign = 1; + for (int i = 0; i <= n - k; i++, sign = sign == 1 ? (mod - 1) : 1) { + // cur -> + // fac[n] -> n! % mod çš„ç»“æžœï¼ + // inv[i] -> i! çš„é€†å…ƒï¼ + // inv[n - k - i] -> (n - k - i)! 的逆元 + // sign * 1 -> 1 + // * -1 -> mod - 1 + cur = (sign * power(n - k - i, l - k)) % mod; + cur = (cur * fac[n]) % mod; + cur = (cur * inv[i]) % mod; + cur = (cur * inv[n - k - i]) % mod; + ans = (ans + cur) % mod; + } + return (int) ans; + } + +} diff --git a/算法周更ç­/class_2023_02_2_week/Code02_VerticalOrderTraversalOfBinaryTree.java b/算法周更ç­/class_2023_02_2_week/Code02_VerticalOrderTraversalOfBinaryTree.java new file mode 100644 index 0000000..da8e899 --- /dev/null +++ b/算法周更ç­/class_2023_02_2_week/Code02_VerticalOrderTraversalOfBinaryTree.java @@ -0,0 +1,82 @@ +package class_2023_02_2_week; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +// ç»™ä½ äºŒå‰æ ‘的根结点 root ï¼Œè¯·ä½ è®¾è®¡ç®—æ³•è®¡ç®—äºŒå‰æ ‘çš„ åž‚åºé历 åºåˆ—。 +// 对ä½äºŽ (row, col) çš„æ¯ä¸ªç»“点而言, +// å…¶å·¦å³å­ç»“点分别ä½äºŽ (row + 1, col - 1) å’Œ (row + 1, col + 1) +// 树的根结点ä½äºŽ (0, 0) 。 +// äºŒå‰æ ‘çš„ åž‚åºé历 从最左边的列开始直到最å³è¾¹çš„列结æŸï¼ŒæŒ‰åˆ—索引æ¯ä¸€åˆ—上的所有结点, +// å½¢æˆä¸€ä¸ªæŒ‰å‡ºçްä½ç½®ä»Žä¸Šåˆ°ä¸‹æŽ’åºçš„æœ‰åºåˆ—表。如果åŒè¡ŒåŒåˆ—上有多个结点, +// 则按结点的值从å°åˆ°å¤§è¿›è¡ŒæŽ’åºã€‚ +// è¿”å›žäºŒå‰æ ‘çš„ åž‚åºé历 åºåˆ—。 +// 测试链接 : https://leetcode.cn/problems/vertical-order-traversal-of-a-binary-tree/ +public class Code02_VerticalOrderTraversalOfBinaryTree { + + // ä¸æäº¤è¿™ä¸ªç±» + public static class TreeNode { + int val; + TreeNode left; + TreeNode right; + } + + // æäº¤ä»¥ä¸‹æ‰€æœ‰çš„code + public static class Info { + public int row; + public int col; + public int val; + + public Info(int r, int c, int v) { + row = r; + col = c; + val = v; + } + } + + public static class InfoComparator implements Comparator { + + @Override + public int compare(Info o1, Info o2) { + if (o1.col != o2.col) { + return o1.col - o2.col; + } + if (o1.row != o2.row) { + return o1.row - o2.row; + } + return o1.val - o2.val; + } + + } + + public static List> verticalTraversal(TreeNode root) { + ArrayList collects = new ArrayList<>(); + Info rootInfo = new Info(0, 0, root.val); + collects.add(rootInfo); + dfs(root, rootInfo, collects); + List> ans = new ArrayList<>(); + collects.sort(new InfoComparator()); + for (int i = 0; i < collects.size(); i++) { + if (i == 0 || collects.get(i - 1).col != collects.get(i).col) { + ans.add(new ArrayList<>()); + } + ans.get(ans.size() - 1).add(collects.get(i).val); + } + return ans; + } + + public static void dfs(TreeNode root, Info rootInfo, ArrayList collects) { + if (root.left != null) { + Info leftInfo = new Info(rootInfo.row + 1, rootInfo.col - 1, root.left.val); + collects.add(leftInfo); + dfs(root.left, leftInfo, collects); + } + if (root.right != null) { + Info rightInfo = new Info(rootInfo.row + 1, rootInfo.col + 1, root.right.val); + collects.add(rightInfo); + dfs(root.right, rightInfo, collects); + } + } + +} diff --git a/算法周更ç­/class_2023_02_2_week/Code03_WidthOfBinaryTree.java b/算法周更ç­/class_2023_02_2_week/Code03_WidthOfBinaryTree.java new file mode 100644 index 0000000..31cf6b0 --- /dev/null +++ b/算法周更ç­/class_2023_02_2_week/Code03_WidthOfBinaryTree.java @@ -0,0 +1,54 @@ +package class_2023_02_2_week; + +import java.util.LinkedList; + +// ç»™ä½ ä¸€æ£µäºŒå‰æ ‘的根节点 root ,返回树的 最大宽度 。 +// æ ‘çš„ 最大宽度 是所有层中最大的 宽度 。 +// æ¯ä¸€å±‚çš„ 宽度 被定义为该层最左和最å³çš„éžç©ºèŠ‚ç‚¹ï¼ˆå³ï¼Œä¸¤ä¸ªç«¯ç‚¹ï¼‰ä¹‹é—´çš„长度。 +// å°†è¿™ä¸ªäºŒå‰æ ‘è§†ä½œä¸Žæ»¡äºŒå‰æ ‘结构相åŒï¼Œä¸¤ç«¯ç‚¹é—´ä¼šå‡ºçŽ°ä¸€äº›å»¶ä¼¸åˆ°è¿™ä¸€å±‚çš„ null 节点, +// 这些 null 节点也计入长度。 +// 题目数æ®ä¿è¯ç­”案将会在 32 ä½ å¸¦ç¬¦å·æ•´æ•°èŒƒå›´å†…。 +// 测试链接 : https://leetcode.cn/problems/maximum-width-of-binary-tree/ +public class Code03_WidthOfBinaryTree { + + // ä¸æäº¤è¿™ä¸ªç±» + public static class TreeNode { + public int val; + public TreeNode left; + public TreeNode right; + } + + // æäº¤ä»¥ä¸‹æ‰€æœ‰çš„æ–¹æ³• + public static class Info { + // 当å‰èŠ‚ç‚¹ + public TreeNode node; + // ç¼–å·ï¼ + public int index; + + public Info(TreeNode n, int i) { + node = n; + index = i; + } + } + + public static int widthOfBinaryTree(TreeNode root) { + int ans = 1; + LinkedList queue = new LinkedList<>(); + queue.add(new Info(root, 1)); + while (!queue.isEmpty()) { + ans = Math.max(ans, queue.peekLast().index - queue.peekFirst().index + 1); + int size = queue.size(); + for (int i = 0; i < size; i++) { + Info cur = queue.pollFirst(); + if (cur.node.left != null) { + queue.addLast(new Info(cur.node.left, cur.index * 2)); + } + if (cur.node.right != null) { + queue.addLast(new Info(cur.node.right, cur.index * 2 + 1)); + } + } + } + return ans; + } + +} \ No newline at end of file diff --git a/算法周更ç­/class_2023_02_2_week/Code04_MinimizeMalwareSpreadII.java b/算法周更ç­/class_2023_02_2_week/Code04_MinimizeMalwareSpreadII.java new file mode 100644 index 0000000..0873c2e --- /dev/null +++ b/算法周更ç­/class_2023_02_2_week/Code04_MinimizeMalwareSpreadII.java @@ -0,0 +1,144 @@ +package class_2023_02_2_week; + +import java.util.Arrays; + +// 给定一个由 n 个节点组æˆçš„网络,用 n x n 个邻接矩阵 graph 表示 +// åœ¨èŠ‚ç‚¹ç½‘ç»œä¸­ï¼Œåªæœ‰å½“ graph[i][j] = 1 时,节点 i 能够直接连接到å¦ä¸€ä¸ªèŠ‚ç‚¹ j。 +// 一些节点 initial 最åˆè¢«æ¶æ„软件感染。åªè¦ä¸¤ä¸ªèŠ‚ç‚¹ç›´æŽ¥è¿žæŽ¥ï¼Œ +// 且其中至少一个节点å—åˆ°æ¶æ„è½¯ä»¶çš„æ„ŸæŸ“ï¼Œé‚£ä¹ˆä¸¤ä¸ªèŠ‚ç‚¹éƒ½å°†è¢«æ¶æ„软件感染。 +// è¿™ç§æ¶æ„软件的传播将继续,直到没有更多的节点å¯ä»¥è¢«è¿™ç§æ–¹å¼æ„ŸæŸ“。 +// å‡è®¾ M(initial) æ˜¯åœ¨æ¶æ„è½¯ä»¶åœæ­¢ä¼ æ’­ä¹‹åŽï¼Œæ•´ä¸ªç½‘ç»œä¸­æ„ŸæŸ“æ¶æ„软件的最终节点数。 +// 我们å¯ä»¥ä»Ž initial 中删除一个节点, +// 并完全移除该节点以åŠä»Žè¯¥èŠ‚ç‚¹åˆ°ä»»ä½•å…¶ä»–èŠ‚ç‚¹çš„ä»»ä½•è¿žæŽ¥ã€‚ +// 请返回移除åŽèƒ½å¤Ÿä½¿ M(initial) 最å°åŒ–的节点。 +// 如果有多个节点满足æ¡ä»¶ï¼Œè¿”回索引 最å°çš„节点 。 +// initial 中æ¯ä¸ªæ•´æ•°éƒ½ä¸åŒ +// 测试链接 : https://leetcode.cn/problems/minimize-malware-spread-ii/ +public class Code04_MinimizeMalwareSpreadII { + + public int minMalwareSpread(int[][] graph, int[] initial) { + // 节点个数 + int n = graph.length; + // 病毒数组, + // 病毒initial -> [3,6,9] + // virus[3] = true; + // virus[6] = true; + // virus[7] = false; + boolean[] virus = new boolean[n]; + for (int i : initial) { + virus[i] = true; + } + // 建立并查集 + // nå¤§å° 0~n-1 + UnionFind uf = new UnionFind(n); + // 忽略感染点åŠå…¶é“¾æŽ¥ï¼ + // åˆå¹¶é›†åˆï¼ + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + // i, j ? + if (graph[i][j] == 1 && !virus[i] && !virus[j]) { + uf.union(i, j); + } + } + } + // æ‰€æœ‰éžæ„ŸæŸ“ç‚¹ï¼Œè¯¥é“¾æŽ¥éƒ½é“¾æŽ¥äº†ï¼ + // 0,6,7,8 æ˜¯ä¸€ä¸ªé›†åˆ + // 6被选æˆäº†ä»£è¡¨ç‚¹ï¼Œæ— æ³•控制,åªç”±å¹¶æŸ¥é›†è‡ªå·±å†³å®š + // infect[6] == -1 ,目å‰è¿™ä¸ªé›†åˆæ²¡æœ‰æ„ŸæŸ“æº + // infect[6] == -2 ,目å‰è¿™ä¸ªé›†åˆå·²ç»å‘现了ä¸åªä¸€ä¸ªæ„ŸæŸ“æº + // infect[6] == x x>=0,目å‰è¿™ä¸ªé›†åˆå·²ç»å‘现了一个感染æºï¼Œæ˜¯x点 + int[] infect = new int[n]; + // ç›®å‰æ‰€æœ‰é›†åˆéƒ½æ²¡æœ‰æ„ŸæŸ“æº + Arrays.fill(infect, -1); + for (int v : initial) { // æžšä¸¾æ‰€æœ‰æ„ŸæŸ“ç‚¹ï¼ + // 当剿„ŸæŸ“点是v + // è·Ÿv链接的所有点,next + // n = 7 ç¼–å·0~6 + // n = 13 ç¼–å·0~12 + for (int next = 0; next < n; next++) { + if (v != next && !virus[next] && graph[v][next] == 1) { + // next 无辜点 + // 找到nexté›†åˆæ‰€åœ¨çš„代表点,f + int f = uf.find(next); + if (infect[f] == -1) { + infect[f] = v; + } else { // != -1 å¯èƒ½ == -2 或者 >= 0 + // 之å‰çš„æ„ŸæŸ“点 -> infect[f] + if (infect[f] != -2 && infect[f] != v) { + infect[f] = -2; + } + // infect[f] == -2 + // infect[f] == v + // è¿™ä¸¤ç§æƒ…况,一律ä¸è®¾ç½®æ˜¯ç¬¦åˆé¢„期的 + } + } + } + } + int[] cnt = new int[n]; + for (int i = 0; i < n; i++) { + if (infect[i] >= 0) { + cnt[infect[i]] += uf.size[i]; + } + } + // 4 -> 13 + // 0 -> 6 + // 1 -> 5 + // 13 -> 50 + // 9 -> 20 + // 0 1 4 9 13 14 15 + // 6 5 13 20 50 34 7 + Arrays.sort(initial); + int ans = initial[0]; + int count = cnt[ans]; + for (int i : initial) { + if (cnt[i] > count) { + ans = i; + count = cnt[i]; + } + } + return ans; + } + + public static class UnionFind { + public int[] father; + public int[] size; + public int[] help; + + public UnionFind(int n) { + father = new int[n]; + size = new int[n]; + help = new int[n]; + for (int i = 0; i < n; i++) { + father[i] = i; + size[i] = 1; + } + } + + public int find(int i) { + int hi = 0; + while (i != father[i]) { + help[hi++] = i; + i = father[i]; + } + while (hi != 0) { + father[help[--hi]] = i; + } + return i; + } + + public void union(int i, int j) { + int fi = find(i); + int fj = find(j); + if (fi != fj) { + if (size[fi] >= size[fj]) { + father[fj] = fi; + size[fi] += size[fj]; + } else { + father[fi] = fj; + size[fj] += size[fi]; + } + } + } + } + +} diff --git a/算法课堂笔记/课堂内容汇总/æ¯å‘¨æœ‰è¥å…»çš„大厂算法é¢è¯•题(正在直播) b/算法课堂笔记/课堂内容汇总/æ¯å‘¨æœ‰è¥å…»çš„大厂算法é¢è¯•题(正在直播) index 8b87a4c..c63d9c8 100644 --- a/算法课堂笔记/课堂内容汇总/æ¯å‘¨æœ‰è¥å…»çš„大厂算法é¢è¯•题(正在直播) +++ b/算法课堂笔记/课堂内容汇总/æ¯å‘¨æœ‰è¥å…»çš„大厂算法é¢è¯•题(正在直播) @@ -2911,5 +2911,65 @@ kä½ç¿»è½¬ 就是从 nums 中选择一个长度为 k çš„ å­æ•°ç»„ +第057节 2023å¹´2月第2周æµè¡Œç®—æ³•é¢˜ç›®è§£æž + +ä½ çš„éŸ³ä¹æ’­æ”¾å™¨é‡Œæœ‰ N 首ä¸åŒçš„æ­Œ +在旅途中,你的旅伴想è¦å¬ L 首歌(ä¸ä¸€å®šä¸åŒï¼Œå³ï¼Œå…许歌曲é‡å¤ +请你为她按如下规则创建一个播放列表 +æ¯é¦–歌至少播放一次 +ä¸€é¦–æ­Œåªæœ‰åœ¨å…¶ä»– K é¦–æ­Œæ’­æ”¾å®Œä¹‹åŽæ‰èƒ½å†æ¬¡æ’­æ”¾ +返回å¯ä»¥æ»¡è¶³è¦æ±‚çš„æ’­æ”¾åˆ—è¡¨çš„æ•°é‡ +由于答案å¯èƒ½éžå¸¸å¤§ï¼Œè¯·è¿”回它模 10^9 + 7 的结果 +测试链接 : https://leetcode.cn/problems/number-of-music-playlists/ + +ç»™ä½ äºŒå‰æ ‘的根结点 root ï¼Œè¯·ä½ è®¾è®¡ç®—æ³•è®¡ç®—äºŒå‰æ ‘çš„ åž‚åºé历 åºåˆ—。 +对ä½äºŽ (row, col) çš„æ¯ä¸ªç»“点而言, +å…¶å·¦å³å­ç»“点分别ä½äºŽ (row + 1, col - 1) å’Œ (row + 1, col + 1) +树的根结点ä½äºŽ (0, 0) 。 +äºŒå‰æ ‘çš„ åž‚åºé历 从最左边的列开始直到最å³è¾¹çš„列结æŸï¼ŒæŒ‰åˆ—索引æ¯ä¸€åˆ—上的所有结点, +å½¢æˆä¸€ä¸ªæŒ‰å‡ºçްä½ç½®ä»Žä¸Šåˆ°ä¸‹æŽ’åºçš„æœ‰åºåˆ—表。如果åŒè¡ŒåŒåˆ—上有多个结点, +则按结点的值从å°åˆ°å¤§è¿›è¡ŒæŽ’åºã€‚ +è¿”å›žäºŒå‰æ ‘çš„ åž‚åºé历 åºåˆ—。 +测试链接 : https://leetcode.cn/problems/vertical-order-traversal-of-a-binary-tree/ + +ç»™ä½ ä¸€æ£µäºŒå‰æ ‘的根节点 root ,返回树的 最大宽度 。 +æ ‘çš„ 最大宽度 是所有层中最大的 宽度 。 +æ¯ä¸€å±‚çš„ 宽度 被定义为该层最左和最å³çš„éžç©ºèŠ‚ç‚¹ï¼ˆå³ï¼Œä¸¤ä¸ªç«¯ç‚¹ï¼‰ä¹‹é—´çš„长度。 +å°†è¿™ä¸ªäºŒå‰æ ‘è§†ä½œä¸Žæ»¡äºŒå‰æ ‘结构相åŒï¼Œä¸¤ç«¯ç‚¹é—´ä¼šå‡ºçŽ°ä¸€äº›å»¶ä¼¸åˆ°è¿™ä¸€å±‚çš„ null 节点, +这些 null 节点也计入长度。 +题目数æ®ä¿è¯ç­”案将会在 32 ä½ å¸¦ç¬¦å·æ•´æ•°èŒƒå›´å†…。 +测试链接 : https://leetcode.cn/problems/maximum-width-of-binary-tree/ + +给定一个由 n 个节点组æˆçš„网络,用 n x n 个邻接矩阵 graph 表示 +åœ¨èŠ‚ç‚¹ç½‘ç»œä¸­ï¼Œåªæœ‰å½“ graph[i][j] = 1 时,节点 i 能够直接连接到å¦ä¸€ä¸ªèŠ‚ç‚¹ j。 +一些节点 initial 最åˆè¢«æ¶æ„软件感染。åªè¦ä¸¤ä¸ªèŠ‚ç‚¹ç›´æŽ¥è¿žæŽ¥ï¼Œ +且其中至少一个节点å—åˆ°æ¶æ„è½¯ä»¶çš„æ„ŸæŸ“ï¼Œé‚£ä¹ˆä¸¤ä¸ªèŠ‚ç‚¹éƒ½å°†è¢«æ¶æ„软件感染。 +è¿™ç§æ¶æ„软件的传播将继续,直到没有更多的节点å¯ä»¥è¢«è¿™ç§æ–¹å¼æ„ŸæŸ“。 +å‡è®¾ M(initial) æ˜¯åœ¨æ¶æ„è½¯ä»¶åœæ­¢ä¼ æ’­ä¹‹åŽï¼Œæ•´ä¸ªç½‘ç»œä¸­æ„ŸæŸ“æ¶æ„软件的最终节点数。 +我们å¯ä»¥ä»Ž initial 中删除一个节点, +并完全移除该节点以åŠä»Žè¯¥èŠ‚ç‚¹åˆ°ä»»ä½•å…¶ä»–èŠ‚ç‚¹çš„ä»»ä½•è¿žæŽ¥ã€‚ +请返回移除åŽèƒ½å¤Ÿä½¿ M(initial) 最å°åŒ–的节点。 +如果有多个节点满足æ¡ä»¶ï¼Œè¿”回索引 最å°çš„节点 。 +initial 中æ¯ä¸ªæ•´æ•°éƒ½ä¸åŒ +测试链接 : https://leetcode.cn/problems/minimize-malware-spread-ii/ + + + + + + + + + + + + + + + + + + +