<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Graph on 跟著 Desolve 學程式</title><link>https://desolve.pages.dev/tags/graph/</link><description>Recent content in Graph on 跟著 Desolve 學程式</description><generator>Hugo -- gohugo.io</generator><language>zh-tw</language><lastBuildDate>Wed, 01 May 2024 00:00:00 +0800</lastBuildDate><atom:link href="https://desolve.pages.dev/tags/graph/index.xml" rel="self" type="application/rss+xml"/><item><title>Learn Algorithms from LeetCode-121 (0802. Find Eventual Safe States)</title><link>https://desolve.pages.dev/post/learn-algorithms-from-leetcode-121-0802-find-eventual-safe-states/</link><pubDate>Wed, 01 May 2024 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithms-from-leetcode-121-0802-find-eventual-safe-states/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post Learn Algorithms from LeetCode-121 (0802. Find Eventual Safe States)" /&gt;&lt;h2 id="categories-graphdfs"&gt;Categories: Graph/DFS
&lt;/h2&gt;&lt;h2 id="level-medium"&gt;Level: Medium
&lt;/h2&gt;&lt;p&gt;Introduction: (Basic + Advanced + Interview Edition) &lt;br&gt;
Learning Algorithms from LeetCode + Interview Success Guide &lt;br&gt;
(Regular price: 3591 NTD, Discounted price until 2024/05/16 23:59)&lt;br&gt;
&lt;a class="link" href="https://hiskio.com/bundles/egb397?s=tc" target="_blank" rel="noopener"
&gt;https://hiskio.com/bundles/egb397?s=tc&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(Regular price: 3990 NTD, Valid for a long term) &lt;br&gt;
&lt;a class="link" href="https://bit.ly/lc2022all" target="_blank" rel="noopener"
&gt;https://bit.ly/lc2022all&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Please help me click on the “SHOW EMBED” below and give it 5 likes~ If you like it, you can also give me a round of applause~ &lt;br&gt;
(Liking doesn’t cost anything, thank you for supporting my writing~)&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;There is a directed graph of &lt;code&gt;n&lt;/code&gt; nodes with each node labeled from &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;n - 1&lt;/code&gt;. The graph is represented by a &lt;strong&gt;0-indexed&lt;/strong&gt; 2D integer array &lt;code&gt;graph&lt;/code&gt; where &lt;code&gt;graph[i]&lt;/code&gt; is an integer array of nodes adjacent to node &lt;code&gt;i&lt;/code&gt;, meaning there is an edge from node &lt;code&gt;i&lt;/code&gt; to each node in &lt;code&gt;graph[i]&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A node is a &lt;strong&gt;terminal node&lt;/strong&gt; if there are no outgoing edges. A node is a ** safe node** if every possible path starting from that node leads to a ** terminal node** (or another safe node).&lt;/p&gt;
&lt;p&gt;Return &lt;em&gt;an array containing all the&lt;/em&gt; *&lt;strong&gt;safe nodes&lt;/strong&gt; * &lt;em&gt;of the graph&lt;/em&gt;. The answer should be sorted in &lt;strong&gt;ascending&lt;/strong&gt; order.&lt;/p&gt;
&lt;h3 id="example-1"&gt;Example 1
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithms-from-leetcode-121-0802-find-eventual-safe-states/image-001.png"
width="800"
height="228"
srcset="https://desolve.pages.dev/post/learn-algorithms-from-leetcode-121-0802-find-eventual-safe-states/image-001_hu_a8658ffdefe37f65.png 480w, https://desolve.pages.dev/post/learn-algorithms-from-leetcode-121-0802-find-eventual-safe-states/image-001_hu_43b3ee2d7a89e4a5.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="350"
data-flex-basis="842px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: graph = [[1,2],[2,3],[5],[0],[5],[],[]]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: [2,4,5,6]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Explanation: The given graph is shown above.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Nodes 5 and 6 are terminal nodes as there are no outgoing edges from either of them.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Every path starting at nodes 2, 4, 5, and 6 all lead to either node 5 or 6.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-2"&gt;Example 2
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: graph = [[1,2,3,4],[1,2],[3,4],[0,4],[]]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: [4]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Explanation:
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="constraints"&gt;Constraints
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;n == graph.length&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;1 &amp;lt;= n &amp;lt;= 104&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0 &amp;lt;= graph[i].length &amp;lt;= n&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0 &amp;lt;= graph[i][j] &amp;lt;= n - 1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;graph[i]&lt;/code&gt; is sorted in a strictly increasing order.&lt;/li&gt;
&lt;li&gt;The graph may contain self-loops.&lt;/li&gt;
&lt;li&gt;The number of edges in the graph will be in the range &lt;code&gt;[1, 4 * 104]&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Analysis/Approach:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;There is a directed graph with n nodes, each labeled from 0 to n-1. The graph is represented using a 2D array called “graph,” where graph[i] represents the nodes connected to node i with an edge. The direction of the edge is from node i to each node in graph[i]. If a node has &lt;strong&gt;no outgoing edges&lt;/strong&gt; , it is considered a &lt;strong&gt;terminal node&lt;/strong&gt; . If &lt;strong&gt;all possible paths&lt;/strong&gt; from a node ** lead to terminal nodes**, the node is considered a ** safe node**.&lt;/p&gt;
&lt;p&gt;The task is to find all the safe nodes in the graph and return them in &lt;strong&gt;ascending order&lt;/strong&gt; as an array (or list). To determine if a node is a safe node, we need to check if there are any cycles in the paths starting from that node. ** If there is a cycle, the node itself and all the nodes in the cycle will not be safe nodes.** Additionally, since we need to check that all paths are cycle-free to determine a safe node, ** the results from earlier checks for nodes can be applied to later checks.**&lt;/p&gt;
&lt;p&gt;To solve this problem, we can use a depth-first search (&lt;strong&gt;DFS&lt;/strong&gt; ) approach to traverse each node and its paths until the end (or until we can determine if there is a cycle). The steps for solving the problem are as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Initialize two arrays/lists, &lt;strong&gt;vis&lt;/strong&gt; and ** path**, to keep track of whether a node has been visited and whether it is part of a cycle. Both arrays/lists should have a length equal to the number of nodes in the graph, n, and initialized with 0 (or False).&lt;/li&gt;
&lt;li&gt;Initialize an empty result list called &lt;strong&gt;res&lt;/strong&gt; .&lt;/li&gt;
&lt;li&gt;Declare a DFS function that takes the &lt;strong&gt;current node, graph&lt;/strong&gt; , &lt;strong&gt;vis&lt;/strong&gt; , and &lt;strong&gt;path&lt;/strong&gt; as parameters and returns ** True if a cycle is found** and ** False if no cycle is found**.&lt;/li&gt;
&lt;li&gt;In the DFS function, perform the following steps: &lt;br&gt;
4.1. Set &lt;strong&gt;vis[curr]&lt;/strong&gt; and ** path[curr]** to ** 1** (indicating that the node has been visited and is temporarily part of a cycle). &lt;br&gt;
4.2. Iterate over the &lt;strong&gt;nodes u in graph[curr]&lt;/strong&gt; : &lt;br&gt;
4.2.1. &lt;strong&gt;If vis[u] is 0&lt;/strong&gt; (indicating that the node hasn’t been visited), recursively call DFS with u as the current node and check if it returns True. ** If True, return True (indicating a cycle is found)&lt;strong&gt;. &lt;br&gt;
4.2.2. Otherwise, if &lt;strong&gt;path[u] == 1&lt;/strong&gt; (indicating that u is already part of a cycle), return ** True&lt;/strong&gt;. &lt;br&gt;
4.3. After the &lt;strong&gt;loop ends without returning True&lt;/strong&gt; , it means there is &lt;strong&gt;no cycle found&lt;/strong&gt; when going down from the current node. ** Reset path[curr] to 0 and return False. (Since we set all the path[curr] alone with 1, we need to set it back)**&lt;/li&gt;
&lt;li&gt;In the main function, use a loop to iterate over i from &lt;strong&gt;0 to n-1&lt;/strong&gt; . If vis[i] is 0, call DFS with i as the current node.&lt;/li&gt;
&lt;li&gt;After all iterations, use another loop to iterate over i from &lt;strong&gt;0 to n-1&lt;/strong&gt; and add the nodes i with path[i] == 0 to the res list.&lt;/li&gt;
&lt;li&gt;Return the res list.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here is the code implementation in both Java and Python:&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;p&gt;In the Java implementation, an ArrayList is used for the &lt;code&gt;res&lt;/code&gt; variable. If we want to reduce the number of parameters passed to the &lt;code&gt;dfs&lt;/code&gt; function, we can make &lt;code&gt;vis&lt;/code&gt; and &lt;code&gt;path&lt;/code&gt; class variables. However, since their lengths are tied to the number of nodes in the graph, they still need to be initialized within the &lt;code&gt;eventualSafeNodes&lt;/code&gt; method.&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/a0d407e4d47566801d4644afb900a168.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;p&gt;As mentioned before, in the Python implementation, using nested functions can slightly reduce the number of variables that need to be passed as arguments. In fact, if we move the &lt;code&gt;vis&lt;/code&gt; and &lt;code&gt;path&lt;/code&gt; arrays/lists to the outermost scope, they don&amp;rsquo;t need to be passed as arguments at all because the nested function can access variables from the outer scope.&lt;/p&gt;
&lt;p&gt;You may try rewriting the code and experimenting with this approach.&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/182d787f4f43559379a39a192c1ffe24.js"&gt;&lt;/script&gt;
&lt;p&gt;&lt;strong&gt;Potential Interview Questions:&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;“What are the time and space complexities?”&lt;/strong&gt;&lt;br&gt;
(&lt;strong&gt;O(V+E)/O(V)&lt;/strong&gt; , where V is the number of nodes in the graph and E is the number of edges in the graph)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;“Can we use a single array/list to handle visited nodes and cycles?”&lt;/strong&gt; (Hint: State can have more than 1 or 0; &lt;br&gt;
you can use 3 different states to handle this)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Similar and Extended Topics:&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Special thanks to suggestions/corrections from viewers:&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;(Welcome to provide feedback to help with corrections~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Learn Algorithms from LeetCode — See you next time!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Want to see more problems? &lt;br&gt;
Feel free to check out &lt;a class="link" href="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-0/" &gt;&lt;strong&gt;Article 0&lt;/strong&gt; &lt;/a&gt; for the topic you want!&lt;/p&gt;
&lt;p&gt;Also, follow our Facebook page for notifications on new articles:&lt;br&gt;
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
&gt;&lt;strong&gt;Learn with Desolve&lt;/strong&gt; &lt;/a&gt;&lt;/p&gt;</description></item><item><title>從LeetCode學演算法-121 (0802. Find Eventual Safe States)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-121-0802-find-eventual-safe-states/</link><pubDate>Wed, 01 May 2024 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-121-0802-find-eventual-safe-states/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法-121 (0802. Find Eventual Safe States)" /&gt;&lt;h2 id="categories-graphdfs"&gt;Categories: Graph/DFS
&lt;/h2&gt;&lt;h2 id="level-medium"&gt;Level: Medium
&lt;/h2&gt;&lt;h2 id="寫在前面"&gt;寫在前面
&lt;/h2&gt;&lt;p&gt;(基礎+進階+面試篇)從 LeetCode 學演算法 + 面試成功指南**&lt;/p&gt;
&lt;p&gt;(3591元有效期限至 2024/05/16 23:59)&lt;br&gt;
&lt;a class="link" href="https://hiskio.com/bundles/egb397?s=tc" target="_blank" rel="noopener"
&gt;https://hiskio.com/bundles/egb397?s=tc&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(3990元 長期有效) &lt;a class="link" href="https://bit.ly/lc2022all" target="_blank" rel="noopener"
&gt;https://bit.ly/lc2022all&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;容筆者工商一下，&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」&lt;/strong&gt; 這次選了40道難度加深的LeetCode題目，&lt;br&gt;
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br&gt;
同時這次購買進階篇的話，&lt;br&gt;
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br&gt;
當中包含了&lt;strong&gt;面試準備須知分享&lt;/strong&gt; ，&lt;strong&gt;及訪談國內外不同經驗的工程師&lt;/strong&gt; ，&lt;br&gt;
讓你不論是&lt;strong&gt;想走前端/後端/一般軟工&lt;/strong&gt; 或者是&lt;strong&gt;想找國外的工作&lt;/strong&gt; ，&lt;br&gt;
是&lt;strong&gt;初學想轉職&lt;/strong&gt; 還是&lt;strong&gt;正在工作&lt;/strong&gt; ，都能夠從中得到收穫呦！&lt;br&gt;
有興趣的朋友可以使用下面的優惠～&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong&gt; ：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/lc2022adv" target="_blank" rel="noopener"
&gt;https://bit.ly/lc2022adv&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;There is a directed graph of &lt;code&gt;n&lt;/code&gt; nodes with each node labeled from &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;n - 1&lt;/code&gt;. The graph is represented by a &lt;strong&gt;0-indexed&lt;/strong&gt; 2D integer array &lt;code&gt;graph&lt;/code&gt; where &lt;code&gt;graph[i]&lt;/code&gt; is an integer array of nodes adjacent to node &lt;code&gt;i&lt;/code&gt;, meaning there is an edge from node &lt;code&gt;i&lt;/code&gt; to each node in &lt;code&gt;graph[i]&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A node is a &lt;strong&gt;terminal node&lt;/strong&gt; if there are no outgoing edges. A node is a ** safe node** if every possible path starting from that node leads to a ** terminal node** (or another safe node).&lt;/p&gt;
&lt;p&gt;Return &lt;em&gt;an array containing all the&lt;/em&gt; *&lt;strong&gt;safe nodes&lt;/strong&gt; * &lt;em&gt;of the graph&lt;/em&gt;. The answer should be sorted in &lt;strong&gt;ascending&lt;/strong&gt; order.&lt;/p&gt;
&lt;h3 id="example-1"&gt;Example 1
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-121-0802-find-eventual-safe-states/image-001.png"
width="800"
height="228"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-121-0802-find-eventual-safe-states/image-001_hu_a8658ffdefe37f65.png 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-121-0802-find-eventual-safe-states/image-001_hu_43b3ee2d7a89e4a5.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="350"
data-flex-basis="842px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: graph = [[1,2],[2,3],[5],[0],[5],[],[]]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: [2,4,5,6]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Explanation: The given graph is shown above.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Nodes 5 and 6 are terminal nodes as there are no outgoing edges from either of them.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Every path starting at nodes 2, 4, 5, and 6 all lead to either node 5 or 6.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-2"&gt;Example 2
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: graph = [[1,2,3,4],[1,2],[3,4],[0,4],[]]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: [4]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Explanation:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Only node 4 is a terminal node, and every path starting at node 4 leads to node 4.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="constraints"&gt;Constraints
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;n == graph.length&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;1 &amp;lt;= n &amp;lt;= 104&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0 &amp;lt;= graph[i].length &amp;lt;= n&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0 &amp;lt;= graph[i][j] &amp;lt;= n - 1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;graph[i]&lt;/code&gt; is sorted in a strictly increasing order.&lt;/li&gt;
&lt;li&gt;The graph may contain self-loops.&lt;/li&gt;
&lt;li&gt;The number of edges in the graph will be in the range &lt;code&gt;[1, 4 * 104]&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="分析解題"&gt;分析/解題
&lt;/h2&gt;&lt;p&gt;有一個有向圖，當中包含了n個節點，每個節點分別被標記為0~n-1。&lt;br&gt;
這個圖使用2D的array graph來表示，&lt;br&gt;
當中graph[i]代表所有從節點i有邊(edge)相連的節點，&lt;br&gt;
且方向是從節點i到每個graph[i]中的節點。&lt;/p&gt;
&lt;p&gt;如果一個節點&lt;strong&gt;沒有任何向外的邊&lt;/strong&gt; 的話，則該節點是&lt;strong&gt;terminal node&lt;/strong&gt; ；&lt;br&gt;
如果從一個節點出去的&lt;strong&gt;所有可能的路徑&lt;/strong&gt; 都&lt;strong&gt;導向到terminal node&lt;/strong&gt; 的話，&lt;br&gt;
則該節點是&lt;strong&gt;safe node&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;試找出所有圖中的safe nodes，並且以陣列(串列)型態回傳，&lt;br&gt;
當中答案必須要以&lt;strong&gt;升冪排序&lt;/strong&gt; (由小到大排列)。&lt;/p&gt;
&lt;p&gt;首先我們要思考的是，怎麼樣的狀況下會沒辦法terminal呢？&lt;br&gt;
按照定義，一旦導到&lt;strong&gt;terminal node&lt;/strong&gt; ，則由於沒有向外的邊，&lt;br&gt;
於是路徑就會停在terminal node了(因為&lt;strong&gt;無路可走&lt;/strong&gt; )。&lt;br&gt;
換句話說，如果要不停下來的話，就要一直有路可走。&lt;br&gt;
但&lt;strong&gt;節點和邊都是有限的&lt;/strong&gt; ，那麼就只有當&lt;strong&gt;存在環&lt;/strong&gt; 的狀況下，&lt;br&gt;
才能夠一直有路可以走囉！&lt;/p&gt;
&lt;p&gt;因此，要判斷一個點是否為safe node，&lt;br&gt;
端看從該點出發的路徑&lt;strong&gt;是否存在有環&lt;/strong&gt; ；&lt;br&gt;
如果有環的話，&lt;strong&gt;則包含該點，以及環上的所有節點都不會是safe node&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;同時，由於我們判斷safe node必須要&lt;strong&gt;所有路徑&lt;/strong&gt; 都沒有環存在，&lt;br&gt;
&lt;strong&gt;因此前面檢查過的節點結果，會同樣適用於後面的檢查&lt;/strong&gt; 。&lt;br&gt;
例如：從點A出發，如果其中一條路徑我們走過點B跟點C，&lt;br&gt;
那麼下次當檢查從點B出發的時候，&lt;br&gt;
我們可以直接採納前面點A出發經過點B時對點B判斷的結果，&lt;br&gt;
如此一來就不用重新再走一遍了！&lt;/p&gt;
&lt;p&gt;那麼這題應該要做的就是遍歷每一個節點及路徑，&lt;br&gt;
並且每條路徑都走到底(或者走到可以判定是否有環)為止，&lt;br&gt;
這顯然適用於DFS的做法。&lt;/p&gt;
&lt;p&gt;讓我們來試著列看看解題步驟：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;初始化兩個陣列(串列) &lt;strong&gt;vis, path&lt;/strong&gt; ，分別代表該節點是否已造訪過，&lt;br&gt;
以及該節點是否為某個環的一部分，兩者的長度均為graph的節點數量n，&lt;br&gt;
預設值均為0(或False也可以)。&lt;/li&gt;
&lt;li&gt;初始化一個空的res串列備用。&lt;/li&gt;
&lt;li&gt;宣告一個dfs函式，代入&lt;strong&gt;curr, graph, vis, path&lt;/strong&gt; (curr為要檢查的node)，&lt;br&gt;
其回傳&lt;strong&gt;True則代表存在環，False則代表不存在環&lt;/strong&gt; 。&lt;/li&gt;
&lt;li&gt;在dfs函式中，進行以下處理：&lt;br&gt;
4–1. 將vis[curr]和path[curr]均&lt;strong&gt;設為1&lt;/strong&gt; (也就是已造訪，且&lt;strong&gt;暫定環存在&lt;/strong&gt; )&lt;br&gt;
4–2. 迴圈從&lt;strong&gt;graph[curr]&lt;/strong&gt; 中取出節點u：&lt;br&gt;
4–2–1. 若vis[u]為0 (表示這個節點還沒被造訪) -&amp;gt; &lt;br&gt;
代入到dfs往下檢查，如得到回傳True的話則也回傳True(代表確定有環)&lt;br&gt;
4–2–2. 否則，若&lt;strong&gt;path[u] == 1&lt;/strong&gt; (表示** u在環上**)，回傳True。&lt;br&gt;
4–3. 經過迴圈結束後尚未回傳，代表其實從curr往下走並不存在環，&lt;br&gt;
這時候重新將&lt;strong&gt;path[curr]設為0&lt;/strong&gt; ，並且回傳&lt;strong&gt;False&lt;/strong&gt; 。&lt;br&gt;
(前面直接回傳True的時候，因為我們預先將沿路的path[curr]設為1，&lt;br&gt;
因此離開的時候&lt;strong&gt;整條路徑上的節點都被標記成環了&lt;/strong&gt; ；&lt;br&gt;
反過來說，當發現不存在環的時候，&lt;strong&gt;該還原的就要還原回來&lt;/strong&gt; 。)&lt;/li&gt;
&lt;li&gt;在主函式中，使用迴圈令i依次從&lt;strong&gt;0~n-1&lt;/strong&gt; ，&lt;br&gt;
如果&lt;strong&gt;vis[i] == 0&lt;/strong&gt; 的話，就代入進行dfs。&lt;/li&gt;
&lt;li&gt;都做完的狀況下，再次使用迴圈令i從&lt;strong&gt;0~n-1&lt;/strong&gt; ，&lt;br&gt;
將&lt;strong&gt;path[i] == 0&lt;/strong&gt; 的&lt;strong&gt;i&lt;/strong&gt; 加入到res。&lt;/li&gt;
&lt;li&gt;回傳res。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;依此，寫成程式碼如下：&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;p&gt;Java的部分使用了ArrayList給res使用，&lt;br&gt;
如果想要讓dfs不要帶入那麼多東西的話，&lt;br&gt;
也可以將vis跟path設定為class variables，&lt;br&gt;
不過因為長度跟graph的節點數掛勾，&lt;br&gt;
所以還是要在eventualSafeNodes裡才能初始化。&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/a0d407e4d47566801d4644afb900a168.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;p&gt;Python的部分如同以前提到過的，&lt;br&gt;
使用子函式也可以稍微減少需要代入的變數量，&lt;br&gt;
甚至將vis和path放最前面的話也可以連它們都不需要代入，&lt;br&gt;
因為子函式可以去取得到上面這層的變數。&lt;br&gt;
(讀者可以自行嘗試再改寫看看)&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/182d787f4f43559379a39a192c1ffe24.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間／空間複雜度？」&lt;br&gt;
(O(V+E)/O(V)，V為graph的節點數，E為graph的邊數)&lt;/p&gt;
&lt;p&gt;「能不能只用一個陣列／串列來處理經過的節點和環？」&lt;br&gt;
(提示：State可以不只有1或0，可以設定3種state來處理)&lt;/p&gt;
&lt;h2 id="相似及延伸"&gt;相似及延伸
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Special Thanks suggestions/corrections from viewers:&lt;br&gt;
(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;
&lt;p&gt;想看看其他題目嗎？&lt;br&gt;
歡迎從&lt;a class="link" href="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-0/" &gt;&lt;strong&gt;第零篇&lt;/strong&gt; &lt;/a&gt;找你想要的！&lt;/p&gt;
&lt;p&gt;同時追蹤粉專以獲得更多新文章的通知：&lt;br&gt;
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
&gt;&lt;strong&gt;跟著Desolve學程式&lt;/strong&gt; &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;另外，&lt;strong&gt;「從Leetcode學演算法｜基礎篇」&lt;/strong&gt; 已經回原價囉，&lt;br&gt;
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br&gt;
雖然&lt;strong&gt;整捆一起買總體比較划算&lt;/strong&gt; (差290而已就有整組了阿XD)，&lt;br&gt;
如果你還是想先試試基礎課的話，&lt;br&gt;
&lt;strong&gt;300元折抵的連結&lt;/strong&gt; 在這邊：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/lc2022base" target="_blank" rel="noopener"
&gt;https://bit.ly/lc2022base&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Learn Algorithms from LeetCode-120 (0547. Number of Provinces)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-120-0547-number-of-provinces-en/</link><pubDate>Tue, 06 Jun 2023 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-120-0547-number-of-provinces-en/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post Learn Algorithms from LeetCode-120 (0547. Number of Provinces)" /&gt;&lt;h2 id="categories-graphunion-find"&gt;Categories: Graph/Union Find
&lt;/h2&gt;&lt;h2 id="level-medium"&gt;Level: Medium**
&lt;/h2&gt;&lt;p&gt;Introduction: (Basic + Advanced + Interview Edition) &lt;br&gt;
Learning Algorithms from LeetCode + Interview Success Guide &lt;br&gt;
(Regular price: 3591 NTD, Discounted price until 2023/06/30 23:59)&lt;br&gt;
&lt;a class="link" href="https://hiskio.com/bundles/eCP23B397?s=tc" target="_blank" rel="noopener"
&gt;https://hiskio.com/bundles/eCP23B397?s=tc&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(Regular price: 3990 NTD, Valid for a long term) &lt;br&gt;
&lt;a class="link" href="https://bit.ly/lc2022all" target="_blank" rel="noopener"
&gt;https://bit.ly/lc2022all&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Please help me click on the “SHOW EMBED” below and give it 5 likes~ If you like it, you can also give me a round of applause~ &lt;br&gt;
(Liking doesn’t cost anything, thank you for supporting my writing~)&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;There are &lt;code&gt;n&lt;/code&gt; cities. Some of them are connected, while some are not. If city &lt;code&gt;a&lt;/code&gt; is connected directly with city &lt;code&gt;b&lt;/code&gt;, and city &lt;code&gt;b&lt;/code&gt; is connected directly with city &lt;code&gt;c&lt;/code&gt;, then city &lt;code&gt;a&lt;/code&gt; is connected indirectly with city &lt;code&gt;c&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;province&lt;/strong&gt; is a group of directly or indirectly connected cities and no other cities outside of the group.&lt;/p&gt;
&lt;p&gt;You are given an &lt;code&gt;n x n&lt;/code&gt; matrix &lt;code&gt;isConnected&lt;/code&gt; where &lt;code&gt;isConnected[i][j] = 1&lt;/code&gt; if the &lt;code&gt;ith&lt;/code&gt; city and the &lt;code&gt;jth&lt;/code&gt; city are directly connected, and &lt;code&gt;isConnected[i][j] = 0&lt;/code&gt; otherwise.&lt;/p&gt;
&lt;p&gt;Return &lt;em&gt;the total number of&lt;/em&gt; *&lt;strong&gt;provinces&lt;/strong&gt; *.&lt;/p&gt;
&lt;h3 id="example-1"&gt;Example 1
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-120-0547-number-of-provinces-en/0_gzPQzUPCV6vo5zpO.jpg"
width="222"
height="142"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-120-0547-number-of-provinces-en/0_gzPQzUPCV6vo5zpO_hu_57f2b94360956ce8.jpg 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-120-0547-number-of-provinces-en/0_gzPQzUPCV6vo5zpO_hu_9e1c69c1f2e289c0.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="156"
data-flex-basis="375px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: isConnected = [[1,1,0],[1,1,0],[0,0,1]]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: 2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-2"&gt;Example 2
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-120-0547-number-of-provinces-en/0_vYmD9XAZJEU4Isbo.jpg"
width="222"
height="142"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-120-0547-number-of-provinces-en/0_vYmD9XAZJEU4Isbo_hu_af71b661ff852cd7.jpg 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-120-0547-number-of-provinces-en/0_vYmD9XAZJEU4Isbo_hu_48eac003d0a48d17.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="156"
data-flex-basis="375px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: isConnected = [[1,0,0],[0,1,0],[0,0,1]]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: 3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="constraints"&gt;Constraints
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;1 &amp;lt;= n &amp;lt;= 200&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;n == isConnected.length&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;n == isConnected[i].length&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;isConnected[i][j]&lt;/code&gt; is &lt;code&gt;1&lt;/code&gt; or &lt;code&gt;0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;isConnected[i][i] == 1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;isConnected[i][j] == isConnected[j][i]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Analysis/Approach:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;There are n cities, some of which are directly connected to each other, while others are not. If city a is directly connected to city b, and city b is directly connected to city c, then city a is indirectly connected to city c. (That’s a lot of unnecessary words LOL)&lt;/p&gt;
&lt;p&gt;A province is a group of cities that are directly or indirectly connected, and there are no other cities in this group. (In other words, if you can walk from x to y, they are considered part of the same province).&lt;/p&gt;
&lt;p&gt;Given an n x n matrix isConnected, where isConnected[i][j] = 1 means the ith city is directly connected to the jth city, and isConnected[i][j] = 0 means they are not directly connected, return the total number of provinces.&lt;/p&gt;
&lt;p&gt;We have discussed many concepts related to graphs in &lt;a class="link" href="https://desolve.medium.com/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-115-graph-1-union-find-1-3616ad4a6496" target="_blank" rel="noopener"
&gt;&lt;strong&gt;Article 115&lt;/strong&gt; &lt;/a&gt; and the previous article. Today, let’s take a closer look at the usage of Union Find.&lt;/p&gt;
&lt;p&gt;Since the variable name “isConnected” is too long, we will use “edges” to refer to it for convenience.&lt;/p&gt;
&lt;p&gt;First, we need to find the number of provinces, which is another typical scenario where Union Find can be used. However, as we mentioned before, if we only trace back along the edges to find the root, the find operation for a single point can potentially take &lt;strong&gt;O(n)&lt;/strong&gt; time. Therefore, we need to simplify the process by performing ** path compression** during the ** union** operation.&lt;/p&gt;
&lt;p&gt;In the union operation, instead of arbitrary assignment as before, we can now choose to check which root has a higher rank and merge the group with the lower rank into the group with the higher rank. The root of the group with the lower rank should be set as the root of the group with the higher rank. This way, during the union process, since we always merge the smaller group into the larger one, it will be less likely to create long chains of connections. This technique is called &lt;strong&gt;path compression&lt;/strong&gt; .&lt;/p&gt;
&lt;p&gt;Therefore, our implementation of the find operation and union operation will look like this:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;find(root, i)&lt;/strong&gt; :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Initialize r as root[i]&lt;/li&gt;
&lt;li&gt;If r and root[r] are not equal (indicating that we haven’t reached the node that is the root), enter the loop:&lt;/li&gt;
&lt;li&gt;Set root[r] as root[root[r]]&lt;/li&gt;
&lt;li&gt;Set r as root[r] (move up one level and continue the evaluation)&lt;/li&gt;
&lt;li&gt;After the loop (steps 2–4) ends, set root[i] as r, indicating that the topmost leader of node i is r.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;union(root, rank, x, y):&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Apply the find operation to x and y separately to obtain their respective roots &lt;strong&gt;rx and ry&lt;/strong&gt; .&lt;/li&gt;
&lt;li&gt;If &lt;strong&gt;rx and ry are the same&lt;/strong&gt; , it means they are already in the same group, so &lt;strong&gt;return false&lt;/strong&gt; .&lt;/li&gt;
&lt;li&gt;If they are different, compare the ranks rank[rx] and rank[ry]:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;If &lt;strong&gt;rank[rx] ≥ rank[ry]&lt;/strong&gt; , increase rank[rx] by rank[ry] and &lt;strong&gt;set root[ry] as rx&lt;/strong&gt; .&lt;/li&gt;
&lt;li&gt;Otherwise, if &lt;strong&gt;rank[rx] &amp;lt; rank[ry]&lt;/strong&gt; , increase rank[ry] by rank[rx] and &lt;strong&gt;set root[rx] as ry&lt;/strong&gt; .&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After initializing root and rank (from &lt;strong&gt;1 to n-1&lt;/strong&gt; and ** 1**), we can use a nested loop to call the union operation for the pairs of cities that are connected by edges. Finally, we iterate through each node and perform the find operation to determine the ** unique roots** and store them in a HashSet. The answer can be obtained by checking the size of the HashSet.&lt;/p&gt;
&lt;p&gt;Here is an implementation in Java:&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;p&gt;We can use &lt;strong&gt;Arrays.fill()&lt;/strong&gt; to set values in Java. Since we don’t specifically need the true/false return value for the union operation, we can change its return type to void and modify the necessary parts accordingly. Finally, we can use a HashSet to record the answers, iterate through i, call find(), and add the results. The final answer can be obtained by checking the size of the HashSet.&lt;/p&gt;
&lt;p&gt;Notice that you could start j from i+1 rather than 0.&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/26aa057a36ea78c2d4511cba41333eeb.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;p&gt;In Python, the implementation is similar except for the use of sub-functions.&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/40a58853d50c6c18acded10bee487bac.js"&gt;&lt;/script&gt;
&lt;p&gt;&lt;strong&gt;Potential Interview Questions:&lt;/strong&gt;&lt;br&gt;
“What are the time and space complexities?”&lt;br&gt;
(O(n²)/O(n), as even with path compression, traversing all edges still takes O(n²) time, and the space complexity only needs to consider the space for recording roots and ranks.)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Similar and Extended Topics:&lt;/strong&gt; 0684. Redundant Connection (Medium)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Special thanks to suggestions/corrections from viewers:&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;(Welcome to provide feedback to help with corrections~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Learn Algorithms from LeetCode — See you next time!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Want to see more problems? &lt;br&gt;
Feel free to check out &lt;a class="link" href="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-0/" &gt;&lt;strong&gt;Article 0&lt;/strong&gt; &lt;/a&gt; for the topic you want!&lt;/p&gt;
&lt;p&gt;Also, follow our Facebook page for notifications on new articles:&lt;br&gt;
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
&gt;&lt;strong&gt;Learn with Desolve&lt;/strong&gt; &lt;/a&gt;&lt;/p&gt;</description></item><item><title>從LeetCode學演算法-120 (0547. Number of Provinces)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-120-0547-number-of-provinces/</link><pubDate>Tue, 06 Jun 2023 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-120-0547-number-of-provinces/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法-120 (0547. Number of Provinces)" /&gt;&lt;h2 id="categories-graphunion-find"&gt;Categories: Graph/Union Find
&lt;/h2&gt;&lt;h2 id="level-medium"&gt;Level: Medium
&lt;/h2&gt;&lt;h2 id="寫在前面"&gt;寫在前面
&lt;/h2&gt;&lt;p&gt;(基礎+進階+面試篇)從 LeetCode 學演算法 + 面試成功指南**&lt;/p&gt;
&lt;p&gt;(3591元 特價中: 2023/06/30 23:59後截止) &lt;br&gt;
&lt;a class="link" href="https://hiskio.com/bundles/eCP23B397?s=tc" target="_blank" rel="noopener"
&gt;https://hiskio.com/bundles/eCP23B397?s=tc&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(3990元 長期有效) &lt;a class="link" href="https://bit.ly/lc2022all" target="_blank" rel="noopener"
&gt;https://bit.ly/lc2022all&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;容筆者工商一下，&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」&lt;/strong&gt; 這次選了40道難度加深的LeetCode題目，&lt;br&gt;
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br&gt;
同時這次購買進階篇的話，&lt;br&gt;
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br&gt;
當中包含了&lt;strong&gt;面試準備須知分享&lt;/strong&gt; ，&lt;strong&gt;及訪談國內外不同經驗的工程師&lt;/strong&gt; ，&lt;br&gt;
讓你不論是&lt;strong&gt;想走前端/後端/一般軟工&lt;/strong&gt; 或者是&lt;strong&gt;想找國外的工作&lt;/strong&gt; ，&lt;br&gt;
是&lt;strong&gt;初學想轉職&lt;/strong&gt; 還是&lt;strong&gt;正在工作&lt;/strong&gt; ，都能夠從中得到收穫呦！&lt;br&gt;
有興趣的朋友可以使用下面的優惠～&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong&gt; ：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/lc2022adv" target="_blank" rel="noopener"
&gt;https://bit.ly/lc2022adv&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;There are &lt;code&gt;n&lt;/code&gt; cities. Some of them are connected, while some are not. If city &lt;code&gt;a&lt;/code&gt; is connected directly with city &lt;code&gt;b&lt;/code&gt;, and city &lt;code&gt;b&lt;/code&gt; is connected directly with city &lt;code&gt;c&lt;/code&gt;, then city &lt;code&gt;a&lt;/code&gt; is connected indirectly with city &lt;code&gt;c&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;province&lt;/strong&gt; is a group of directly or indirectly connected cities and no other cities outside of the group.&lt;/p&gt;
&lt;p&gt;You are given an &lt;code&gt;n x n&lt;/code&gt; matrix &lt;code&gt;isConnected&lt;/code&gt; where &lt;code&gt;isConnected[i][j] = 1&lt;/code&gt; if the &lt;code&gt;ith&lt;/code&gt; city and the &lt;code&gt;jth&lt;/code&gt; city are directly connected, and &lt;code&gt;isConnected[i][j] = 0&lt;/code&gt; otherwise.&lt;/p&gt;
&lt;p&gt;Return &lt;em&gt;the total number of&lt;/em&gt; *&lt;strong&gt;provinces&lt;/strong&gt; *.&lt;/p&gt;
&lt;h3 id="example-1"&gt;Example 1
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-120-0547-number-of-provinces/0_gzPQzUPCV6vo5zpO.jpg"
width="222"
height="142"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-120-0547-number-of-provinces/0_gzPQzUPCV6vo5zpO_hu_57f2b94360956ce8.jpg 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-120-0547-number-of-provinces/0_gzPQzUPCV6vo5zpO_hu_9e1c69c1f2e289c0.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="156"
data-flex-basis="375px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: isConnected = [[1,1,0],[1,1,0],[0,0,1]]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: 2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-2"&gt;Example 2
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-120-0547-number-of-provinces/0_vYmD9XAZJEU4Isbo.jpg"
width="222"
height="142"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-120-0547-number-of-provinces/0_vYmD9XAZJEU4Isbo_hu_af71b661ff852cd7.jpg 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-120-0547-number-of-provinces/0_vYmD9XAZJEU4Isbo_hu_48eac003d0a48d17.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="156"
data-flex-basis="375px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: isConnected = [[1,0,0],[0,1,0],[0,0,1]]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: 3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="constraints"&gt;Constraints
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;1 &amp;lt;= n &amp;lt;= 200&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;n == isConnected.length&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;n == isConnected[i].length&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;isConnected[i][j]&lt;/code&gt; is &lt;code&gt;1&lt;/code&gt; or &lt;code&gt;0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;isConnected[i][i] == 1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;isConnected[i][j] == isConnected[j][i]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;有n個城市，其中一些城市彼此相連，而另一些則沒有。&lt;br&gt;
如果城市a與城市b直接相連，並且城市b與城市c直接相連，&lt;br&gt;
那麼城市a與城市c之間間接相連。(OS: 好廢話XD)&lt;/p&gt;
&lt;p&gt;一個省(province)是一組直接或間接相連的城市，&lt;br&gt;
且該群組中沒有其他的城市。&lt;br&gt;
(也就是直要可以從x走到y，它們就視為相同省)&lt;/p&gt;
&lt;p&gt;給定一個n x n的矩陣isConnected，&lt;br&gt;
其中isConnected[i][j] = 1表示第i個城市和第j個城市直接相連，isConnected[i][j] = 0則表示它們不直接相連，回傳省的總數量。&lt;/p&gt;
&lt;p&gt;我們已經在&lt;a class="link" href="https://desolve.medium.com/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-115-graph-1-union-find-1-3616ad4a6496" target="_blank" rel="noopener"
&gt;&lt;strong&gt;第115篇&lt;/strong&gt; &lt;/a&gt;以及上一篇中提到了很多Graph的概念，&lt;br&gt;
今天再來仔細一點探討Union Find的用法。&lt;/p&gt;
&lt;p&gt;由於isConnected太長了，我們底下還是直接使用edges來稱呼比較簡便。&lt;br&gt;
首先看到了要找provinces的組數，&lt;br&gt;
顯然又是一個很典型能使用Union Find的場合；&lt;br&gt;
但先前我們提到過，如果只是一路沿著edge往回trace老大的話，&lt;br&gt;
對於單一點的find有可能達到O(n)，&lt;br&gt;
因此我們需要做一些簡化：在&lt;strong&gt;union&lt;/strong&gt; 的合併時，&lt;br&gt;
就盡可能地&lt;strong&gt;先行收斂&lt;/strong&gt; 。那麼我們應該怎麼做呢？&lt;/p&gt;
&lt;p&gt;我們這邊定義一個串列叫做rank，&lt;br&gt;
用以表達每個節點往上對到的root所含有的節點總數。&lt;br&gt;
那麼在合併的時候，有別於先前的任意指定，&lt;br&gt;
我們這次可以選擇先檢查誰的rank大，&lt;br&gt;
接著&lt;strong&gt;人多欺負人少&lt;/strong&gt; &amp;hellip;&amp;hellip;不對，是&lt;strong&gt;rank大的合併掉rank小&lt;/strong&gt; 的群組；&lt;br&gt;
rank小的群組的root要設定為rank大的群組的root。&lt;br&gt;
這麼一來，在合併的過程中，由於一直是大的合併小的，&lt;br&gt;
相對而言會較不容易將union的連接拉太多層，&lt;br&gt;
這個手法我們稱之為&lt;strong&gt;路徑壓縮(path compression)&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;因此，我們的find的寫法和union的寫法會像這樣：&lt;br&gt;
&lt;strong&gt;find(root, i):&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先取到r = root[i]&lt;/li&gt;
&lt;li&gt;如果r和root[r]不相等(代表還沒走到自己是root(老大)的節點)進行迴圈:&lt;/li&gt;
&lt;li&gt;將root[root[r]]的值塞給root[r]&lt;/li&gt;
&lt;li&gt;令r = root[r] (來到上面一層，繼續準備判斷)&lt;/li&gt;
&lt;li&gt;在2~4的迴圈結束後，直接令root[i] = r，&lt;br&gt;
標明節點i的最上面的老大是r。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;union(root, rank, x, y):&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;對x, y分別使用find，取得各自的root &lt;strong&gt;rx, ry&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;如果&lt;strong&gt;rx和ry相同&lt;/strong&gt; ，代表已經是同一組了，&lt;strong&gt;直接回傳false&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;如果不同，則看rank[rx]和rank[ry]的關係，&lt;br&gt;
&lt;strong&gt;rank[rx] ≥ rank[ry]&lt;/strong&gt; 的話，就將&lt;strong&gt;rank[rx]遞增rank[ry]&lt;/strong&gt; ，&lt;br&gt;
並且令&lt;strong&gt;root[ry] = rx&lt;/strong&gt; ；&lt;br&gt;
反之，若&lt;strong&gt;rank[rx] &amp;lt; rank[ry]&lt;/strong&gt; ，則將&lt;strong&gt;rank[ry]遞增rank[rx]&lt;/strong&gt; ，&lt;br&gt;
並且令&lt;strong&gt;root[rx] = ry&lt;/strong&gt; 。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;那麼，剩下來我們只需要做完對root和rank的初始化(&lt;strong&gt;1~n-1&lt;/strong&gt; 跟&lt;strong&gt;1&lt;/strong&gt; )&lt;br&gt;
剩下就是&lt;strong&gt;雙層迴圈&lt;/strong&gt; 對有&lt;strong&gt;edge&lt;/strong&gt; 的兩點呼叫&lt;strong&gt;union&lt;/strong&gt; ，&lt;br&gt;
最後對於每個節點確認它們&lt;strong&gt;不重複的root有哪些&lt;/strong&gt; 即可。&lt;/p&gt;
&lt;p&gt;依此，寫成程式碼如下：&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;p&gt;Java的部分一樣可以用&lt;strong&gt;Arrays.fill()&lt;/strong&gt; 來設定定值，&lt;br&gt;
同時因為我們union其實沒特別用到true/false的需求，&lt;br&gt;
可以設定為void，直接將對應該改的東西改一改，&lt;br&gt;
並直接return即可。&lt;/p&gt;
&lt;p&gt;同時，在記錄答案時，我們可以使用HashSet，&lt;br&gt;
在最後對i做遍歷並逐個進行find()，並加到當中，&lt;br&gt;
最後檢查res.size()即可得到我們要的答案。&lt;/p&gt;
&lt;p&gt;另外可以留意的是，雙重迴圈的union(i, j)因為沒有方向性的關係，&lt;br&gt;
第二層的j可以&lt;strong&gt;從i+1開始&lt;/strong&gt; 就好，不需要從0開始。&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/26aa057a36ea78c2d4511cba41333eeb.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;p&gt;Python的部分除了改成用子函式以外，&lt;br&gt;
其餘則大同小異。&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/40a58853d50c6c18acded10bee487bac.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
( O(n²)/O(n)，因為即便有經過path的壓縮，遍歷所有edge仍然要O(n²)，&lt;br&gt;
空間的部分則是只需要考慮記錄root和rank的空間)&lt;/p&gt;
&lt;h2 id="相似及延伸"&gt;相似及延伸
&lt;/h2&gt;&lt;ol start="684"&gt;
&lt;li&gt;Redundant Connection (Medium)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Special Thanks suggestions/corrections from viewers:&lt;br&gt;
(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;
&lt;p&gt;想看看其他題目嗎？&lt;br&gt;
歡迎從&lt;a class="link" href="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-0/" &gt;&lt;strong&gt;第零篇&lt;/strong&gt; &lt;/a&gt;找你想要的！&lt;/p&gt;
&lt;p&gt;同時追蹤粉專以獲得更多新文章的通知：&lt;br&gt;
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
&gt;&lt;strong&gt;跟著Desolve學程式&lt;/strong&gt; &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;另外，&lt;strong&gt;「從Leetcode學演算法｜基礎篇」&lt;/strong&gt; 已經回原價囉，&lt;br&gt;
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br&gt;
雖然&lt;strong&gt;整捆一起買總體比較划算&lt;/strong&gt; (差290而已就有整組了阿XD)，&lt;br&gt;
如果你還是想先試試基礎課的話，&lt;br&gt;
&lt;strong&gt;300元折抵的連結&lt;/strong&gt; 在這邊：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/lc2022base" target="_blank" rel="noopener"
&gt;https://bit.ly/lc2022base&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Learn Algorithms from LeetCode - 119 (0797. All Paths From Source to Target(Medium))</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-119-0797-all-paths-from-source-to-target-medium/</link><pubDate>Sun, 04 Jun 2023 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-119-0797-all-paths-from-source-to-target-medium/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post Learn Algorithms from LeetCode - 119 (0797. All Paths From Source to Target(Medium))" /&gt;&lt;h2 id="categories-graphdfs"&gt;Categories: Graph/DFS
&lt;/h2&gt;&lt;h2 id="level-medium"&gt;Level: Medium
&lt;/h2&gt;&lt;p&gt;Introduction: (Basic + Advanced + Interview Edition) &lt;br&gt;
Learning Algorithms from LeetCode + Interview Success Guide &lt;br&gt;
(Regular price: 3591 NTD, Discounted price until 2023/06/30 23:59)&lt;br&gt;
&lt;a class="link" href="https://hiskio.com/bundles/eCP23B397?s=tc" target="_blank" rel="noopener"
&gt;https://hiskio.com/bundles/eCP23B397?s=tc&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(Regular price: 3990 NTD, Valid for a long term) &lt;br&gt;
&lt;a class="link" href="https://bit.ly/lc2022all" target="_blank" rel="noopener"
&gt;https://bit.ly/lc2022all&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Please help me click on the “SHOW EMBED” below and give it 5 likes~ If you like it, you can also give me a round of applause~ &lt;br&gt;
(Liking doesn’t cost anything, thank you for supporting my writing~)&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;Given a directed acyclic graph (&lt;strong&gt;DAG&lt;/strong&gt; ) of &lt;code&gt;n&lt;/code&gt; nodes labeled from &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;n - 1&lt;/code&gt;, find all possible paths from node &lt;code&gt;0&lt;/code&gt; to node &lt;code&gt;n - 1&lt;/code&gt; and return them in &lt;strong&gt;any order&lt;/strong&gt; .&lt;/p&gt;
&lt;p&gt;The graph is given as follows: &lt;code&gt;graph[i]&lt;/code&gt; is a list of all nodes you can visit from node &lt;code&gt;i&lt;/code&gt; (i.e., there is a directed edge from node &lt;code&gt;i&lt;/code&gt; to node &lt;code&gt;graph[i][j]&lt;/code&gt;).&lt;/p&gt;
&lt;h3 id="example-1"&gt;Example 1
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-119-0797-all-paths-from-source-to-target-medium/0_JZvZO8TcGYlV_krH.jpg"
width="242"
height="242"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-119-0797-all-paths-from-source-to-target-medium/0_JZvZO8TcGYlV_krH_hu_60b1ca5817f91f36.jpg 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-119-0797-all-paths-from-source-to-target-medium/0_JZvZO8TcGYlV_krH_hu_e1c4b444c3304661.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="100"
data-flex-basis="240px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: graph = [[1,2],[3],[3],[]]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: [[0,1,3],[0,2,3]]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Explanation: There are two paths: 0 -&amp;gt; 1 -&amp;gt; 3 and 0 -&amp;gt; 2 -&amp;gt; 3.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-2"&gt;Example 2
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-119-0797-all-paths-from-source-to-target-medium/0_205SEP480YZHWDkX.jpg"
width="423"
height="301"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-119-0797-all-paths-from-source-to-target-medium/0_205SEP480YZHWDkX_hu_ec6726b91810384e.jpg 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-119-0797-all-paths-from-source-to-target-medium/0_205SEP480YZHWDkX_hu_694746669cf369eb.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="140"
data-flex-basis="337px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: graph = [[4,3,1],[3,2,4],[3],[4],[]]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: [[0,4],[0,3,4],[0,1,3,4],[0,1,2,3,4],[0,1,4]]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="constraints"&gt;Constraints
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;n == graph.length&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;2 &amp;lt;= n &amp;lt;= 15&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0 &amp;lt;= graph[i][j] &amp;lt; n&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;graph[i][j] != i&lt;/code&gt; (i.e., there will be no self-loops).&lt;/li&gt;
&lt;li&gt;All the elements of &lt;code&gt;graph[i]&lt;/code&gt; are &lt;strong&gt;unique&lt;/strong&gt; .&lt;/li&gt;
&lt;li&gt;The input graph is &lt;strong&gt;guaranteed&lt;/strong&gt; to be a ** DAG**.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Analysis/Approach:&lt;/strong&gt; &lt;br&gt;
Given a directed acyclic graph (DAG) with n nodes labeled from 0 to n — 1, we need to find all possible paths from node 0 to node n — 1 and return them in any order.&lt;/p&gt;
&lt;p&gt;The graph is represented in the following way: graph[i] represents a list of nodes that can be visited from node i. (Directly visiting means there is a directed edge from node i to graph[i][j].)&lt;/p&gt;
&lt;p&gt;Let’s talk about graphs in this article. As mentioned in &lt;a class="link" href="https://desolve.medium.com/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-115-graph-1-union-find-1-3616ad4a6496" target="_blank" rel="noopener"
&gt;&lt;strong&gt;Article 115&lt;/strong&gt; &lt;/a&gt;, in a graph with directionality (a -&amp;gt; b and b -&amp;gt; a are considered different edges), it is called a &lt;strong&gt;directed graph&lt;/strong&gt; . If a directed graph does not have cycles (a &lt;strong&gt;cycle&lt;/strong&gt; means there is a path starting from a point a and ending at a, forming a loop), it is called a ** directed acyclic graph**, abbreviated as ** DAG**.&lt;/p&gt;
&lt;p&gt;Since the problem guarantees that the graph is a DAG, it is impossible to return to the same node from any starting node, and it is also impossible to backtrack, meaning there are no duplicates in the paths.&lt;/p&gt;
&lt;p&gt;Let’s try to outline the steps to find the paths:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Start from i = 0 and examine the connections in &lt;strong&gt;graph[i]&lt;/strong&gt; . For example, in Example 1, node 0 connects to nodes 1 and 2, so there are two paths: 0-&amp;gt;1 and 0-&amp;gt;2.&lt;/li&gt;
&lt;li&gt;For the path 0-&amp;gt;1, we need to check the connections from node 1. It is connected only to node 3, which happens to be the last node in this graph. Therefore, we have found one valid path: 0-&amp;gt;1-&amp;gt;3.&lt;/li&gt;
&lt;li&gt;Similarly, for the path 0-&amp;gt;2, it only has one connection: 0-&amp;gt;2-&amp;gt;3.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Therefore, for this problem, we can use DFS starting from node 0 and recursively explore the graph. Along the way, we need to keep track of the current path at each step. Whenever we reach the destination node, we add that path to the result list. Finally, we return the entire result.&lt;/p&gt;
&lt;p&gt;The steps for solving this problem are as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Initialize a list called res to store the resulting paths.&lt;/li&gt;
&lt;li&gt;Define a function dfs with parameters (i, path), where i is the current node and path is the path taken to reach node i (including i).&lt;/li&gt;
&lt;li&gt;Inside the function, first check if i is equal to the length of the graph minus 1. If true, it means we have reached node n-1, and this path is one of the answers. Add it to res.&lt;/li&gt;
&lt;li&gt;If the previous check fails, it means we need to continue exploring. Iterate through the next node nxt in graph[i] and recursively call dfs with nxt and the updated path (path + nxt).&lt;/li&gt;
&lt;li&gt;Start the recursion by calling dfs with (0, [0]).&lt;/li&gt;
&lt;li&gt;After Step 5 is completed, return res.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Based on this, the code can be written as follows:&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;p&gt;In Java, the res list is obviously two-dimensional, so we can use an ArrayList to store the paths. In the helper (or dfs) function, since we cannot use nested functions like in Python, we need to include graph, i, path, and res as parameters. Since the path is reused in each recursion, we use backtracking to keep track of the path. In each call to the helper function, we add the current node i to the path (path.add(i)), and remember to remove it (path.remove(path.size() — 1)) before exiting.&lt;/p&gt;
&lt;p&gt;One important thing to note is that when adding paths to res, ArrayList is a reference-based structure, meaning it doesn’t create a copy of the path. Therefore, when adding to res, we need to use new ArrayList(path) to create a copy. Otherwise, when we backtrack, it will affect the results in res.&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/f8e5a08fab8cce5a8c5118d8725791b7.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;p&gt;In Python, we can use nested functions, so we don’t need to include res and graph as parameters, which makes the code cleaner. When performing dfs, we can directly create a new list using &lt;strong&gt;path + [nxt]&lt;/strong&gt; . This way, we don’t need to deal with backtracking, and we can directly append path to res without making a separate copy. (Since path + [nxt] creates a new list already.)&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/edc9788f87792c4c6dc14a112f7ee51a.js"&gt;&lt;/script&gt;
&lt;p&gt;&lt;strong&gt;Potential Interview Questions:&lt;/strong&gt;&lt;br&gt;
“What are the time and space complexities?” (O(V * 2^V), as each path has a maximum complexity of O(V), and there can be up to O(2^V) paths.)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Similar and Extended Topics:&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Special thanks to suggestions/corrections from viewers:&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;(Welcome to provide feedback to help with corrections~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Learn Algorithms from LeetCode — See you next time!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Want to see more problems? &lt;br&gt;
Feel free to check out &lt;a class="link" href="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-0/" &gt;&lt;strong&gt;Article 0&lt;/strong&gt; &lt;/a&gt; for the topic you want!&lt;/p&gt;
&lt;p&gt;Also, follow our Facebook page for notifications on new articles:&lt;br&gt;
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
&gt;&lt;strong&gt;Learn with Desolve&lt;/strong&gt; &lt;/a&gt;&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 119 Graph (2) / DFS (21)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-119-graph-2-dfs-21/</link><pubDate>Sun, 04 Jun 2023 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-119-graph-2-dfs-21/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 119 Graph (2) / DFS (21)" /&gt;&lt;p&gt;&lt;strong&gt;0797. All Paths From Source to Target (Medium)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="寫在前面"&gt;寫在前面
&lt;/h2&gt;&lt;p&gt;(基礎+進階+面試篇)從 LeetCode 學演算法 + 面試成功指南**&lt;/p&gt;
&lt;p&gt;(3591元 特價中: 2023/06/30 23:59後截止) &lt;br&gt;
&lt;a class="link" href="https://hiskio.com/bundles/eCP23B397?s=tc" target="_blank" rel="noopener"
&gt;https://hiskio.com/bundles/eCP23B397?s=tc&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(3990元 長期有效) &lt;a class="link" href="https://bit.ly/lc2022all" target="_blank" rel="noopener"
&gt;https://bit.ly/lc2022all&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;容筆者工商一下，&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」&lt;/strong&gt; 這次選了40道難度加深的LeetCode題目，&lt;br&gt;
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br&gt;
同時這次購買進階篇的話，&lt;br&gt;
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br&gt;
當中包含了&lt;strong&gt;面試準備須知分享&lt;/strong&gt; ，&lt;strong&gt;及訪談國內外不同經驗的工程師&lt;/strong&gt; ，&lt;br&gt;
讓你不論是&lt;strong&gt;想走前端/後端/一般軟工&lt;/strong&gt; 或者是&lt;strong&gt;想找國外的工作&lt;/strong&gt; ，&lt;br&gt;
是&lt;strong&gt;初學想轉職&lt;/strong&gt; 還是&lt;strong&gt;正在工作&lt;/strong&gt; ，都能夠從中得到收穫呦！&lt;br&gt;
有興趣的朋友可以使用下面的優惠～&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong&gt; ：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/lc2022adv" target="_blank" rel="noopener"
&gt;https://bit.ly/lc2022adv&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;Given a directed acyclic graph (&lt;strong&gt;DAG&lt;/strong&gt; ) of &lt;code&gt;n&lt;/code&gt; nodes labeled from &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;n - 1&lt;/code&gt;, find all possible paths from node &lt;code&gt;0&lt;/code&gt; to node &lt;code&gt;n - 1&lt;/code&gt; and return them in &lt;strong&gt;any order&lt;/strong&gt; .&lt;/p&gt;
&lt;p&gt;The graph is given as follows: &lt;code&gt;graph[i]&lt;/code&gt; is a list of all nodes you can visit from node &lt;code&gt;i&lt;/code&gt; (i.e., there is a directed edge from node &lt;code&gt;i&lt;/code&gt; to node &lt;code&gt;graph[i][j]&lt;/code&gt;).&lt;/p&gt;
&lt;h3 id="example-1"&gt;Example 1
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-119-graph-2-dfs-21/0_JZvZO8TcGYlV_krH.jpg"
width="242"
height="242"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-119-graph-2-dfs-21/0_JZvZO8TcGYlV_krH_hu_60b1ca5817f91f36.jpg 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-119-graph-2-dfs-21/0_JZvZO8TcGYlV_krH_hu_e1c4b444c3304661.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="100"
data-flex-basis="240px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: graph = [[1,2],[3],[3],[]]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: [[0,1,3],[0,2,3]]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Explanation: There are two paths: 0 -&amp;gt; 1 -&amp;gt; 3 and 0 -&amp;gt; 2 -&amp;gt; 3.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-2"&gt;Example 2
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-119-graph-2-dfs-21/0_205SEP480YZHWDkX.jpg"
width="423"
height="301"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-119-graph-2-dfs-21/0_205SEP480YZHWDkX_hu_ec6726b91810384e.jpg 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-119-graph-2-dfs-21/0_205SEP480YZHWDkX_hu_694746669cf369eb.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="140"
data-flex-basis="337px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: graph = [[4,3,1],[3,2,4],[3],[4],[]]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: [[0,4],[0,3,4],[0,1,3,4],[0,1,2,3,4],[0,1,4]]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="constraints"&gt;Constraints
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;n == graph.length&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;2 &amp;lt;= n &amp;lt;= 15&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0 &amp;lt;= graph[i][j] &amp;lt; n&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;graph[i][j] != i&lt;/code&gt; (i.e., there will be no self-loops).&lt;/li&gt;
&lt;li&gt;All the elements of &lt;code&gt;graph[i]&lt;/code&gt; are &lt;strong&gt;unique&lt;/strong&gt; .&lt;/li&gt;
&lt;li&gt;The input graph is &lt;strong&gt;guaranteed&lt;/strong&gt; to be a ** DAG**.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;給定一個有向無環圖(directed acyclic graph, DAG)，&lt;br&gt;
當中有n個nodes，分別被標記為0到n - 1，&lt;br&gt;
找出所有可以從node 0走到node n - 1的路徑，&lt;br&gt;
並且以任意排序的方式回傳。&lt;/p&gt;
&lt;p&gt;graph的給定方式如以下敘述：&lt;br&gt;
graph[i] 代表所有從node i可以造訪的nodes的串列。&lt;br&gt;
(直接造訪，也就是指node i到graph[i][j]之間會有一個有方向的edge(邊))&lt;/p&gt;
&lt;p&gt;我們這篇再來談談graph。&lt;br&gt;
之前我們在&lt;a class="link" href="https://desolve.medium.com/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-115-graph-1-union-find-1-3616ad4a6496" target="_blank" rel="noopener"
&gt;&lt;strong&gt;第115篇&lt;/strong&gt; &lt;/a&gt;提到過，&lt;br&gt;
在graph當中，有方向性的(a -&amp;gt; b和 b -&amp;gt; a被視為不一樣的邊)圖，&lt;br&gt;
被稱為&lt;strong&gt;有向圖(directed graph)&lt;/strong&gt; ；而如果有向圖中，&lt;br&gt;
不存在&lt;strong&gt;環(cycle，也就是圖上存在一個點a，從點a出發，&lt;br&gt;
有一條路徑可以再走回點a)&lt;strong&gt;的話，&lt;br&gt;
則稱為&lt;/strong&gt;有向無環圖&lt;/strong&gt; ，簡寫為DAG。&lt;/p&gt;
&lt;p&gt;既然題目保證圖是DAG，那麼我們從任何一個點出發，&lt;br&gt;
都保證不可能會再回到同一個點，同時也不可能走回頭路，&lt;br&gt;
也就不存在重複的可能。&lt;/p&gt;
&lt;p&gt;讓我們嘗試列出找尋路徑的步驟：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;首先從i = 0開始，觀察&lt;strong&gt;graph[i]&lt;/strong&gt; 的連接，&lt;br&gt;
例如像Example 1中0就連到1跟2，&lt;br&gt;
也就是說會有 &lt;strong&gt;0-&amp;gt;1&lt;/strong&gt; 跟&lt;strong&gt;0-&amp;gt;2&lt;/strong&gt; 這兩條路徑&lt;/li&gt;
&lt;li&gt;對於0-&amp;gt;1而言，接下來我們要看1的連接，&lt;br&gt;
發現它只連接到3，而3剛好是這個graph的最後一個節點，&lt;br&gt;
因此得到其中一個有效的路徑是0-&amp;gt;1-&amp;gt;3。&lt;/li&gt;
&lt;li&gt;同理，對於0-&amp;gt;2而言也剛好只有0-&amp;gt;2-&amp;gt;3。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;因此對於這題，我們可以使用DFS從node 0做遞迴往下，&lt;br&gt;
中途要記住每一步當下走過的路徑，只要有走到終點的路徑，&lt;br&gt;
就將其放到答案的列表裡，最後再將整個結果回傳即可。&lt;/p&gt;
&lt;p&gt;列出解題步驟如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;初始化一個串列res，用以存放結果的路徑&lt;/li&gt;
&lt;li&gt;定義一個dfs的函式，輸入為**(i, path)** ，&lt;br&gt;
當中i為當前走到的node，path為走到node i時經過的路徑(&lt;strong&gt;包含i&lt;/strong&gt; )。&lt;/li&gt;
&lt;li&gt;在函式中，首先檢查i是否和graph的長度-1相等，&lt;br&gt;
如是，代表走到&lt;strong&gt;node n-1&lt;/strong&gt; 的位置了，&lt;br&gt;
&lt;strong&gt;該路徑是答案之一，將其加到res上&lt;/strong&gt; 。&lt;/li&gt;
&lt;li&gt;若3的檢查解果為否，代表要繼續往下走，&lt;br&gt;
迴圈遍歷&lt;strong&gt;graph[i]&lt;/strong&gt; 中的下一個node nxt，&lt;br&gt;
並呼叫dfs，將&lt;strong&gt;node nxt&lt;/strong&gt; 和新的path(&lt;strong&gt;path加上nxt&lt;/strong&gt; )代入遞迴。&lt;/li&gt;
&lt;li&gt;將**(0, [0])** 代入dfs中開始遞迴。&lt;/li&gt;
&lt;li&gt;完成5後，將res回傳即可。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;依此，寫成程式碼如下：&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;p&gt;在Java的部分，我們的res顯然是二維的，&lt;br&gt;
因此我們可以使用ArrayList來放入其中。&lt;br&gt;
在helper(或dfs)中，因為不能像Python使用子函式，&lt;br&gt;
這邊參數就需要graph、i、path、res；&lt;br&gt;
又因為path是反覆遞迴下去利用的，&lt;br&gt;
我們在記錄時使用backtracking的方式，&lt;br&gt;
選擇在每次進入helper函式時，將path給加上當前走到的node i，&lt;br&gt;
在離開時，則要記得將其收回，因此分別會在頭尾做&lt;strong&gt;path.add(i)&lt;/strong&gt; ，&lt;br&gt;
以及&lt;strong&gt;path.remove(path.size()-1)&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;其他要留意的部分是，由於在放到res的時候，&lt;br&gt;
對於ArrayList來說是一個指向性質的放置，並不會直接複製一份path，&lt;br&gt;
所以在res.add的時候，必須要使用&lt;strong&gt;new ArrayList(path)&lt;/strong&gt; 的手法，&lt;br&gt;
將path複製一份出來才行；不然後面我們在backtracking的時候，&lt;br&gt;
就會同步影響到res的結果喲！&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/f8e5a08fab8cce5a8c5118d8725791b7.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;p&gt;在Python的部分由於可以使用子函式，&lt;br&gt;
我們可以不需要再將res跟graph加到參數，&lt;br&gt;
就會簡潔一點；&lt;br&gt;
同時，在進行dfs的時候，我們這邊改成用&lt;br&gt;
&lt;strong&gt;path + [nxt]&lt;/strong&gt; 的方式，就會直接形成一個新的list。&lt;br&gt;
這樣一來，path的部分就不需要再回頭處理backtracking的問題，&lt;br&gt;
同時res也可以直接進行append(path)，不需要另行複製。&lt;br&gt;
(因為前面path + [nxt]時已經複製完path並形成一個新的list了)&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/edc9788f87792c4c6dc14a112f7ee51a.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(O(V * 2^V)，因為單一條最多是O(V)，最多可能有O(2^V)條)&lt;/p&gt;
&lt;h2 id="相似及延伸"&gt;相似及延伸
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Special Thanks suggestions/corrections from viewers:&lt;br&gt;
(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;
&lt;p&gt;想看看其他題目嗎？&lt;br&gt;
歡迎從&lt;a class="link" href="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-0/" &gt;&lt;strong&gt;第零篇&lt;/strong&gt; &lt;/a&gt;找你想要的！&lt;/p&gt;
&lt;p&gt;同時追蹤粉專以獲得更多新文章的通知：&lt;br&gt;
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
&gt;&lt;strong&gt;跟著Desolve學程式&lt;/strong&gt; &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;另外，&lt;strong&gt;「從Leetcode學演算法｜基礎篇」&lt;/strong&gt; 已經回原價囉，&lt;br&gt;
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br&gt;
雖然&lt;strong&gt;整捆一起買總體比較划算&lt;/strong&gt; (差290而已就有整組了阿XD)，&lt;br&gt;
如果你還是想先試試基礎課的話，&lt;br&gt;
&lt;strong&gt;300元折抵的連結&lt;/strong&gt; 在這邊：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/lc2022base" target="_blank" rel="noopener"
&gt;https://bit.ly/lc2022base&lt;/a&gt;&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 115 Graph(1) / Union Find (1)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-115-graph-1-union-find-1/</link><pubDate>Sun, 04 Jul 2021 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-115-graph-1-union-find-1/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 115 Graph(1) / Union Find (1)" /&gt;&lt;p&gt;&lt;strong&gt;0684. Redundant Connection (Medium)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="寫在前面"&gt;寫在前面
&lt;/h2&gt;&lt;p&gt;從 LeetCode 學演算法 + 面試成功指南**&lt;a class="link" href="https://bit.ly/zeroclg?fbclid=IwAR0cGOc6L5R4j26i6BqncG0m1tPPPx5-Z1M0vAOzJpnwUrByX3q-gWE1Sfw" target="_blank" rel="noopener"
&gt;http://bit.ly/zeroclg&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;容筆者工商一下，&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」&lt;/strong&gt; 這次選了40道難度加深的LeetCode題目，&lt;br&gt;
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br&gt;
同時這次購買進階篇的話，&lt;br&gt;
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br&gt;
當中包含了&lt;strong&gt;面試準備須知分享&lt;/strong&gt; ，&lt;strong&gt;及訪談國內外不同經驗的工程師&lt;/strong&gt; ，&lt;br&gt;
讓你不論是&lt;strong&gt;想走前端/後端/一般軟工&lt;/strong&gt; 或者是&lt;strong&gt;想找國外的工作&lt;/strong&gt; ，&lt;br&gt;
是&lt;strong&gt;初學想轉職&lt;/strong&gt; 還是&lt;strong&gt;正在工作&lt;/strong&gt; ，都能夠從中得到收穫呦！&lt;br&gt;
有興趣的朋友可以使用下面的優惠～&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong&gt; ：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/leetcodeadv" target="_blank" rel="noopener"
&gt;https://bit.ly/leetcodeadv&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;In this problem, a tree is an &lt;strong&gt;undirected graph&lt;/strong&gt; that is connected and has no cycles.&lt;/p&gt;
&lt;p&gt;You are given a graph that started as a tree with &lt;code&gt;n&lt;/code&gt; nodes labeled from &lt;code&gt;1&lt;/code&gt; to &lt;code&gt;n&lt;/code&gt;, with one additional edge added. The added edge has two &lt;strong&gt;different&lt;/strong&gt; vertices chosen from &lt;code&gt;1&lt;/code&gt; to &lt;code&gt;n&lt;/code&gt;, and was not an edge that already existed. The graph is represented as an array &lt;code&gt;edges&lt;/code&gt; of length &lt;code&gt;n&lt;/code&gt; where &lt;code&gt;edges[i] = [ai, bi]&lt;/code&gt; indicates that there is an edge between nodes &lt;code&gt;ai&lt;/code&gt; and &lt;code&gt;bi&lt;/code&gt; in the graph.&lt;/p&gt;
&lt;p&gt;Return &lt;em&gt;an edge that can be removed so that the resulting graph is a tree of&lt;/em&gt; &lt;code&gt;n&lt;/code&gt; &lt;em&gt;nodes&lt;/em&gt;. If there are multiple answers, return the answer that occurs last in the input.&lt;/p&gt;
&lt;h3 id="example-1"&gt;Example 1
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-115-graph-1-union-find-1/0_m69nQSg0Xz1tu5mf.jpg"
width="222"
height="222"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-115-graph-1-union-find-1/0_m69nQSg0Xz1tu5mf_hu_3326d65e86806957.jpg 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-115-graph-1-union-find-1/0_m69nQSg0Xz1tu5mf_hu_9bed4f62bccceac9.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="100"
data-flex-basis="240px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: edges = [[1,2],[1,3],[2,3]]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: [2,3]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-2"&gt;Example 2
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-115-graph-1-union-find-1/0_saAjSjHo_CMHr584.jpg"
width="382"
height="222"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-115-graph-1-union-find-1/0_saAjSjHo_CMHr584_hu_17679c459b72d567.jpg 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-115-graph-1-union-find-1/0_saAjSjHo_CMHr584_hu_4ad50aa88815e03a.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="172"
data-flex-basis="412px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: edges = [[1,2],[2,3],[3,4],[1,4],[1,5]]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: [1,4]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="constraints"&gt;Constraints
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;n == edges.length&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;3 &amp;lt;= n &amp;lt;= 1000&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;edges[i].length == 2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;1 &amp;lt;= ai &amp;lt; bi &amp;lt;= edges.length&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ai != bi&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;There are no repeated edges.&lt;/li&gt;
&lt;li&gt;The given graph is connected.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;在這個問題中，一棵樹是一個無向圖(undirected graph)，且當中沒有環(cycle)。給定一個圖，當中有n個node，標記為從1到n，其中有多一個邊(edge)；多出來的邊是由1到n選出兩個不同的節點(vertices, vertex的複數)所構成的，且並非已經存在的邊。這個圖是由一個長度為n的陣列edges來表示的，其每個元素edges[i]=[ai, bi]表示在圖中，ai和bi兩個節點中間有一個邊連結。&lt;/p&gt;
&lt;p&gt;請回傳一個可以在移除後令這個圖可以形成一棵含有n個節點的樹的邊，如果有多個答案的話，請回傳讓其發生在最後的輸入。&lt;/p&gt;
&lt;p&gt;好的，光翻譯題目就是一個很麻煩的事情，這也是為什麼從之前到現在始終不太想作圖(graph)相關的文章：因為實在太麻煩了，且不好解釋XD&lt;/p&gt;
&lt;p&gt;那我們今天就來挑戰看看吧！希望在看完本篇文章以後，大家還醒著(笑)XD&lt;/p&gt;
&lt;p&gt;在解這題之前，我們應該要先對圖作一點基本介紹：&lt;br&gt;
圖(graph)是一種描述資料與資料之間的連結(不是人與人之間的)的結構，&lt;br&gt;
當中最主要會分為兩個主要的元素：vertex(節點)及edge(邊/線段)。&lt;br&gt;
節點可能擁有自己的一些屬性或值，這個可以依照定義而改變，而節點和節點之間，則是透過邊來連接，因此在同一張圖內，如果有超過一個節點，那它們至少要有能夠相連的邊連結彼此(不然就不會是同一張圖了！)。&lt;/p&gt;
&lt;p&gt;接下來另一個很重要的點是，圖可以分為&lt;strong&gt;有向圖(directed graph)&lt;/strong&gt; 和&lt;strong&gt;無向圖(undirected graph)&lt;/strong&gt; ，什麼意思呢？&lt;/p&gt;
&lt;p&gt;舉例來說，筆者對台北還不夠熟悉的時候，騎著機車在台北附近總是容易繞一大圈才走到自己的目的地，而且回程的時候還容易繞錯路，其中一個原因就是&lt;strong&gt;單行道&lt;/strong&gt; 。單行道表示了今天從A走到B可能可以走XX路，但從B到A可能要走OO路接RR路才行，因為XX路是單向的；換句話說，當從A到B和從B到A無法等價看待的時候，我們會稱這樣的圖為有向圖，因為其關連性不能夠直接反過來也成立。這種圖在繪製上的體現就是節點到節點之間會&lt;strong&gt;有箭頭以表示方向&lt;/strong&gt; ，對於本題來說，由於給定是無方向的，所以讀者會看到圖形上的連接僅有線條，沒有箭頭。&lt;/p&gt;
&lt;p&gt;接著是&lt;strong&gt;環(cycle)&lt;/strong&gt; ，如果一個圖可以從某個節點出發，經過&lt;strong&gt;不重複&lt;/strong&gt; 的節點(起點除外)，最終又能回到起始的節點，我們稱這個圖具有一個循環。&lt;/p&gt;
&lt;p&gt;圖的表示方式一般有兩種：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Adjacency Matrix(相鄰矩陣)，也就是如果有N個節點，就開一個NxN的矩陣Mat，當中如果A點跟B點有edge的話，Mat[A][B]=1，否則為0；可以想見，如果某個圖是無向圖的話，這個矩陣應該會沿對角線相對稱(因為Mat[A][B]會和Mat[B][A]等價)。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Adjacency List(相鄰串列)，也就是對每個節點，都用一個串列來列出跟這個節點有相連的邊的所有節點。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;一般而言，如果總體的edge數量較多的話會使用相鄰矩陣，比較少的話則會使用相鄰串列。&lt;/p&gt;
&lt;p&gt;其它跟圖有關的基礎其實還很多，我們容後有機會再慢慢講。&lt;/p&gt;
&lt;p&gt;回到我們的題目，其實它是一個相對簡單的圖，&lt;br&gt;
因為要連接n個節點總體只需要n-1個邊，而這個圖有n個邊，&lt;br&gt;
要讓這個圖不成環，只能將其中一個會構成環的邊給去除掉。&lt;/p&gt;
&lt;p&gt;那麼，我們怎麼知道哪邊會有環成立呢？&lt;br&gt;
這邊我們可以使用union find的概念來處理。&lt;br&gt;
union find其實是在探究&lt;strong&gt;併查集(&lt;/strong&gt; Disjoint-set data structure**)** 的問題。&lt;br&gt;
用最白話的方式，就是「我們有沒有同一國」的概念。&lt;br&gt;
什麼意思呢？&lt;/p&gt;
&lt;p&gt;假設一個班級有幾個小團體，這些小團體跟幫派一樣很講17且不能重覆加入，我們現在想知道究竟哪些同學屬於哪個小團體，要怎麼找呢？&lt;br&gt;
其實很簡單，就是把每個同學叫過來問：「你的老大是誰？」&lt;/p&gt;
&lt;p&gt;舉例來說，如果有一個班級有兩個小團體，它們之間的層級分部是這樣的：&lt;/p&gt;
&lt;p&gt;A&lt;br&gt;
| &lt;br&gt;
B C&lt;br&gt;
| | &lt;br&gt;
DE- F&lt;/p&gt;
&lt;p&gt;G&lt;br&gt;
|&lt;br&gt;
H&lt;br&gt;
|&lt;br&gt;
I&lt;/p&gt;
&lt;p&gt;D會告訴你他的老大是B；&lt;br&gt;
E會告訴你他的老大是C；&lt;br&gt;
然後B、C會告訴你他們的老大是A；&lt;br&gt;
最後問到A他會說：「我就是老大！」&lt;br&gt;
於是我們就會發現B、C、D、E這四位其實都是隸屬於A的，&lt;br&gt;
也就是他們都是同一團體的。而G、H、I則屬於另一個團體。&lt;br&gt;
因此，我們可以對某個節點找到它最上層的節點，&lt;br&gt;
用這個節點來定義它所屬的團體，同時在過程中依照新增的邊來合併彼此的老大，這個過程叫作&lt;strong&gt;find&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;那麼，我們換個角度來思考：&lt;br&gt;
依照上面的概念，每個節點之間的邊，其實就可以代表它們是同一國的，&lt;br&gt;
那麼，如果在看到這個邊之前，它們就已經有相同的老大了呢？&lt;br&gt;
比如上面的圖而言，&lt;strong&gt;對於E和F來說，由於有A-C-E跟A-C-F，&lt;br&gt;
因此E跟F都知道自己的老大是A&lt;/strong&gt;。&lt;br&gt;
接著我們看到E-F的這條邊連結起來，就意味著這邊&lt;strong&gt;構成了一個環&lt;/strong&gt; ！&lt;br&gt;
因為前面E已經可以連到A，F也可以連到A表示EAF之間可以連接起來，&lt;br&gt;
因此E-F的連接就給這之間構成了一個環。&lt;/p&gt;
&lt;p&gt;因此，我們可以利用這點，來找出構成環的邊，就是我們要的答案了！&lt;br&gt;
因為節點和邊的總數量我們知道是n，所有節點也只有1~n，&lt;br&gt;
所以我們可以使用一個陣列或串列來簡單表示某個節點的老大是哪個節點。&lt;br&gt;
如果它自己就是最大的老大的話，那麼我們就用-1來代表它沒有更上層了。&lt;/p&gt;
&lt;p&gt;因此，我們的解題步驟應該像這樣：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;產生一個root的陣列/串列，其長度為&lt;strong&gt;n+1&lt;/strong&gt; (比較方便對應1~n)，&lt;br&gt;
其初始值均為**-1** 。&lt;/li&gt;
&lt;li&gt;對於edges中的每個邊edge，使用&lt;strong&gt;find&lt;/strong&gt; 函式找到它們的老大x跟y，&lt;br&gt;
檢查x和y是否相同；&lt;strong&gt;若相同，表示這個邊構成了一個環&lt;/strong&gt; ，回傳&lt;strong&gt;edge&lt;/strong&gt; 即可；&lt;br&gt;
若不同，則須統一老大，將&lt;strong&gt;root[x]設定為y&lt;/strong&gt; (將x這系列的上層往y這邊合併)。&lt;/li&gt;
&lt;li&gt;如果檢查完均檢查不到，則在外層回傳空的陣列/串列表示沒找到(但題目表示應該都會存在答案，所以理論上不會走到這邊)。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在&lt;strong&gt;find函式&lt;/strong&gt; 的定義中，輸入應該是root這個陣列跟要被確認的節點i：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;使用迴圈，當&lt;strong&gt;root[i]不是-1時，令i = root[i]&lt;/strong&gt; ，往上找尋更上層的老大。&lt;/li&gt;
&lt;li&gt;直到迴圈結束，這時候的i應該是最上層了，就&lt;strong&gt;回傳i&lt;/strong&gt; 即可。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;依此，寫成程式碼如下：&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;p&gt;Java的部份可以使用Arrays.fill來給定一整組的陣列初始值。&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/596d829af98746c03991688cfae63b09.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;p&gt;Python的部分則直接用*號來初始化即可，同時使用子函式，&lt;br&gt;
略去self相關的麻煩寫法。&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/718f00bd8c163db8cabb118bb6ef35ee.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(如果找尋root的時間沒有到最糟糕狀況的話為O(N)/O(N)，但我們在這個版本的只實作了find，最差狀況下find會一條線接上去，導致find的複雜度達到O(N)，這時候總體時間複雜度就會是O(N^2)。)&lt;/p&gt;
&lt;p&gt;「如果要實作化簡的部份的話？」&lt;br&gt;
(化簡的概念在於將中間尋找的部分也一併處理，也就是告訴沿路上的所有節點它們最大的老大是誰，要怎麼作才能讓整個路徑更短，可以參見&lt;a class="link" href="https://en.wikipedia.org/wiki/Disjoint-set_data_structure" target="_blank" rel="noopener"
&gt;https://en.wikipedia.org/wiki/Disjoint-set_data_structure&lt;/a&gt;，或者參考LeetCode的Solution也有提供，原則上是看兩個小團之間的節點數量來進行誰併到誰的決定。)&lt;/p&gt;
&lt;h2 id="相似及延伸"&gt;相似及延伸
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Special Thanks suggestions/corrections from viewers:&lt;br&gt;
(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;
&lt;p&gt;想看看其他題目嗎？&lt;br&gt;
歡迎從&lt;a class="link" href="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-0/" &gt;&lt;strong&gt;第零篇&lt;/strong&gt; &lt;/a&gt;找你想要的！&lt;/p&gt;
&lt;p&gt;同時追蹤粉專以獲得更多新文章的通知：&lt;br&gt;
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
&gt;&lt;strong&gt;跟著Desolve學程式&lt;/strong&gt; &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;另外，&lt;strong&gt;「從Leetcode學演算法｜基礎篇」&lt;/strong&gt; 已經回原價囉，&lt;br&gt;
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br&gt;
雖然&lt;strong&gt;整捆一起買總體比較划算&lt;/strong&gt; (差290而已就有整組了阿XD)，&lt;br&gt;
如果你還是想先試試基礎課的話，&lt;br&gt;
&lt;strong&gt;300元折抵的連結&lt;/strong&gt; 在這邊：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
&gt;https://bit.ly/1desolve&lt;/a&gt;&lt;/p&gt;</description></item></channel></rss>