<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>connected components Archives - Huahua&#039;s Tech Road</title>
	<atom:link href="https://zxi.mytechroad.com/blog/tag/connected-components/feed/" rel="self" type="application/rss+xml" />
	<link>https://zxi.mytechroad.com/blog/tag/connected-components/</link>
	<description></description>
	<lastBuildDate>Sun, 30 Apr 2023 15:34:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.0.8</generator>

<image>
	<url>https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/cropped-photo-32x32.jpg</url>
	<title>connected components Archives - Huahua&#039;s Tech Road</title>
	<link>https://zxi.mytechroad.com/blog/tag/connected-components/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>花花酱 LeetCode 2658. Maximum Number of Fish in a Grid</title>
		<link>https://zxi.mytechroad.com/blog/graph/leetcode-2658-maximum-number-of-fish-in-a-grid/</link>
					<comments>https://zxi.mytechroad.com/blog/graph/leetcode-2658-maximum-number-of-fish-in-a-grid/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 30 Apr 2023 15:30:49 +0000</pubDate>
				<category><![CDATA[Graph]]></category>
		<category><![CDATA[connected components]]></category>
		<category><![CDATA[DFS]]></category>
		<category><![CDATA[graph]]></category>
		<category><![CDATA[medium]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=10032</guid>

					<description><![CDATA[<p>You are given a&#160;0-indexed&#160;2D matrix&#160;grid&#160;of size&#160;m x n, where&#160;(r, c)&#160;represents: A&#160;land&#160;cell if&#160;grid[r][c] = 0, or A&#160;water&#160;cell containing&#160;grid[r][c]&#160;fish, if&#160;grid[r][c] &#62; 0. A fisher can start at&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/graph/leetcode-2658-maximum-number-of-fish-in-a-grid/">花花酱 LeetCode 2658. Maximum Number of Fish in a Grid</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>You are given a&nbsp;<strong>0-indexed</strong>&nbsp;2D matrix&nbsp;<code>grid</code>&nbsp;of size&nbsp;<code>m x n</code>, where&nbsp;<code>(r, c)</code>&nbsp;represents:</p>



<ul><li>A&nbsp;<strong>land</strong>&nbsp;cell if&nbsp;<code>grid[r][c] = 0</code>, or</li><li>A&nbsp;<strong>water</strong>&nbsp;cell containing&nbsp;<code>grid[r][c]</code>&nbsp;fish, if&nbsp;<code>grid[r][c] &gt; 0</code>.</li></ul>



<p>A fisher can start at any&nbsp;<strong>water</strong>&nbsp;cell&nbsp;<code>(r, c)</code>&nbsp;and can do the following operations any number of times:</p>



<ul><li>Catch all the fish at cell&nbsp;<code>(r, c)</code>, or</li><li>Move to any adjacent&nbsp;<strong>water</strong>&nbsp;cell.</li></ul>



<p>Return&nbsp;<em>the&nbsp;<strong>maximum</strong>&nbsp;number of fish the fisher can catch if he chooses his starting cell optimally, or&nbsp;</em><code>0</code>&nbsp;if no water cell exists.</p>



<p>An&nbsp;<strong>adjacent</strong>&nbsp;cell of the cell&nbsp;<code>(r, c)</code>, is one of the cells&nbsp;<code>(r, c + 1)</code>,&nbsp;<code>(r, c - 1)</code>,&nbsp;<code>(r + 1, c)</code>&nbsp;or&nbsp;<code>(r - 1, c)</code>&nbsp;if it exists.</p>



<p><strong>Example 1:</strong></p>



<figure class="wp-block-image"><img src="https://assets.leetcode.com/uploads/2023/03/29/example.png" alt=""/></figure>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> grid = [[0,2,1,0],[4,0,0,3],[1,0,0,4],[0,3,2,0]]
<strong>Output:</strong> 7
<strong>Explanation:</strong> The fisher can start at cell <code>(1,3)</code> and collect 3 fish, then move to cell <code>(2,3)</code>&nbsp;and collect 4 fish.
</pre>



<p><strong>Example 2:</strong></p>



<figure class="wp-block-image"><img src="https://assets.leetcode.com/uploads/2023/03/29/example2.png" alt=""/></figure>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> grid = [[1,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,1]]
<strong>Output:</strong> 1
<strong>Explanation:</strong> The fisher can start at cells (0,0) or (3,3) and collect a single fish. 
</pre>



<p><strong>Constraints:</strong></p>



<ul><li><code>m == grid.length</code></li><li><code>n == grid[i].length</code></li><li><code>1 &lt;= m, n &lt;= 10</code></li><li><code>0 &lt;= grid[i][j] &lt;= 10</code></li></ul>



<h2><strong>Solution: Connected Component</strong></h2>



<p>Similar to <a href="https://zxi.mytechroad.com/blog/graph/leetcode-695-max-area-of-island/">花花酱 LeetCode 695. Max Area of Island</a></p>



<p>Find the connected component that has the max sum.</p>



<p>Time complexity: O(mn)<br>Space complexity: O(mn)</p>



<div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  int findMaxFish(vector&lt;vector&lt;int&gt;&gt;&amp; grid) {
    const int m = grid.size();
    const int n = grid[0].size();
    function&lt;int(int, int)&gt; dfs = [&amp;](int r, int c) {
      if (r &lt; 0 || r &gt;= m || c &lt; 0 || c &gt;= n || !grid[r][c]) return 0;      
      return exchange(grid[r][c], 0) 
        + dfs(r - 1, c) + dfs(r, c - 1) + dfs(r + 1, c) + dfs(r, c + 1);
    };
    int ans = 0;
    for (int r = 0; r &lt; m; ++r)
      for (int c = 0; c &lt; n; ++c)
        ans = max(ans, dfs(r, c));
    return ans;
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/graph/leetcode-2658-maximum-number-of-fish-in-a-grid/">花花酱 LeetCode 2658. Maximum Number of Fish in a Grid</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/graph/leetcode-2658-maximum-number-of-fish-in-a-grid/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2157. Groups of Strings</title>
		<link>https://zxi.mytechroad.com/blog/searching/leetcode-2157-groups-of-strings/</link>
					<comments>https://zxi.mytechroad.com/blog/searching/leetcode-2157-groups-of-strings/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Mon, 07 Feb 2022 01:03:45 +0000</pubDate>
				<category><![CDATA[Search]]></category>
		<category><![CDATA[connected components]]></category>
		<category><![CDATA[graph]]></category>
		<category><![CDATA[search]]></category>
		<category><![CDATA[union find]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=9492</guid>

					<description><![CDATA[<p>You are given a&#160;0-indexed&#160;array of strings&#160;words. Each string consists of&#160;lowercase English letters&#160;only. No letter occurs more than once in any string of&#160;words. Two strings&#160;s1&#160;and&#160;s2&#160;are said&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/searching/leetcode-2157-groups-of-strings/">花花酱 LeetCode 2157. Groups of Strings</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>You are given a&nbsp;<strong>0-indexed</strong>&nbsp;array of strings&nbsp;<code>words</code>. Each string consists of&nbsp;<strong>lowercase English letters</strong>&nbsp;only. No letter occurs more than once in any string of&nbsp;<code>words</code>.</p>



<p>Two strings&nbsp;<code>s1</code>&nbsp;and&nbsp;<code>s2</code>&nbsp;are said to be&nbsp;<strong>connected</strong>&nbsp;if the set of letters of&nbsp;<code>s2</code>&nbsp;can be obtained from the set of letters of&nbsp;<code>s1</code>&nbsp;by any&nbsp;<strong>one</strong>&nbsp;of the following operations:</p>



<ul><li>Adding exactly one letter to the set of the letters of&nbsp;<code>s1</code>.</li><li>Deleting exactly one letter from the set of the letters of&nbsp;<code>s1</code>.</li><li>Replacing exactly one letter from the set of the letters of&nbsp;<code>s1</code>&nbsp;with any letter,&nbsp;<strong>including</strong>&nbsp;itself.</li></ul>



<p>The array&nbsp;<code>words</code>&nbsp;can be divided into one or more non-intersecting&nbsp;<strong>groups</strong>. A string belongs to a group if any&nbsp;<strong>one</strong>&nbsp;of the following is true:</p>



<ul><li>It is connected to&nbsp;<strong>at least one</strong>&nbsp;other string of the group.</li><li>It is the&nbsp;<strong>only</strong>&nbsp;string present in the group.</li></ul>



<p>Note that the strings in&nbsp;<code>words</code>&nbsp;should be grouped in such a manner that a string belonging to a group cannot be connected to a string present in any other group. It can be proved that such an arrangement is always unique.</p>



<p>Return&nbsp;<em>an array</em>&nbsp;<code>ans</code>&nbsp;<em>of size</em>&nbsp;<code>2</code>&nbsp;<em>where:</em></p>



<ul><li><code>ans[0]</code>&nbsp;<em>is the&nbsp;<strong>total number</strong>&nbsp;of groups</em>&nbsp;<code>words</code>&nbsp;<em>can be divided into, and</em></li><li><code>ans[1]</code>&nbsp;<em>is the&nbsp;<strong>size of the largest</strong>&nbsp;group</em>.</li></ul>



<p><strong>Example 1:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> words = ["a","b","ab","cde"]
<strong>Output:</strong> [2,3]
<strong>Explanation:</strong>
- words[0] can be used to obtain words[1] (by replacing 'a' with 'b'), and words[2] (by adding 'b'). So words[0] is connected to words[1] and words[2].
- words[1] can be used to obtain words[0] (by replacing 'b' with 'a'), and words[2] (by adding 'a'). So words[1] is connected to words[0] and words[2].
- words[2] can be used to obtain words[0] (by deleting 'b'), and words[1] (by deleting 'a'). So words[2] is connected to words[0] and words[1].
- words[3] is not connected to any string in words.
Thus, words can be divided into 2 groups ["a","b","ab"] and ["cde"]. The size of the largest group is 3.  
</pre>



<p><strong>Example 2:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> words = ["a","ab","abc"]
<strong>Output:</strong> [1,3]
<strong>Explanation:</strong>
- words[0] is connected to words[1].
- words[1] is connected to words[0] and words[2].
- words[2] is connected to words[1].
Since all strings are connected to each other, they should be grouped together.
Thus, the size of the largest group is 3.
</pre>



<p><strong>Constraints:</strong></p>



<ul><li><code>1 &lt;= words.length &lt;= 2 * 10<sup>4</sup></code></li><li><code>1 &lt;= words[i].length &lt;= 26</code></li><li><code>words[i]</code>&nbsp;consists of lowercase English letters only.</li><li>No letter occurs more than once in&nbsp;<code>words[i]</code>.</li></ul>



<h2><strong>Solution: Bitmask + DFS</strong></h2>



<p>Use a bitmask to represent a string. Use dfs to find connected components.</p>



<p>Time complexity: O(n*26<sup>2</sup>)<br>Space complexity: O(n)</p>



<div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  vector&lt;int&gt; groupStrings(vector&lt;string&gt;&amp; words) {
    unordered_map&lt;int, int&gt; m;
    for (const string&amp; w : words)
      ++m[accumulate(begin(w), end(w), 0, [](int k, char c){ return k | (1 &lt;&lt; (c - 'a')); })];
    function&lt;int(int)&gt; dfs = [&amp;](int mask) {
      auto it = m.find(mask);
      if (it == end(m)) return 0;
      int ans = it-&gt;second;      
      m.erase(it);
      for (int i = 0; i &lt; 26; ++i) {        
        ans += dfs(mask ^ (1 &lt;&lt; i));
        for (int j = i + 1; j &lt; 26; ++j)
          if ((mask &gt;&gt; i &amp; 1) != (mask &gt;&gt; j &amp; 1))
            ans += dfs(mask ^ (1 &lt;&lt; i) ^ (1 &lt;&lt; j));
      }
      return ans;
    };
    int size = 0;
    int groups = 0;
    while (!m.empty()) {
      size = max(size, dfs(begin(m)-&gt;first));
      ++groups;
    }
    return {groups, size};
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/searching/leetcode-2157-groups-of-strings/">花花酱 LeetCode 2157. Groups of Strings</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/searching/leetcode-2157-groups-of-strings/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1254. Number of Closed Islands</title>
		<link>https://zxi.mytechroad.com/blog/searching/leetcode-1254-number-of-closed-islands/</link>
					<comments>https://zxi.mytechroad.com/blog/searching/leetcode-1254-number-of-closed-islands/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 10 Nov 2019 06:38:30 +0000</pubDate>
				<category><![CDATA[Search]]></category>
		<category><![CDATA[connected components]]></category>
		<category><![CDATA[DFS]]></category>
		<category><![CDATA[island]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[O(n*m)]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=5817</guid>

					<description><![CDATA[<p>Given a 2D&#160;grid&#160;consists of&#160;0s&#160;(land)&#160;and&#160;1s&#160;(water).&#160; An&#160;island&#160;is a maximal 4-directionally connected group of&#160;0s&#160;and a&#160;closed island&#160;is an island&#160;totally&#160;(all left, top, right, bottom) surrounded by&#160;1s. Return the number of&#160;closed&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/searching/leetcode-1254-number-of-closed-islands/">花花酱 LeetCode 1254. Number of Closed Islands</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="花花酱 LeetCode 1252 1253 1254 1255 Weekly Contest 162  - 刷题找工作" width="500" height="375" src="https://www.youtube.com/embed/1XMpzhFUvco?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<p>Given a 2D&nbsp;<code>grid</code>&nbsp;consists of&nbsp;<code>0s</code>&nbsp;(land)&nbsp;and&nbsp;<code>1s</code>&nbsp;(water).&nbsp; An&nbsp;<em>island</em>&nbsp;is a maximal 4-directionally connected group of&nbsp;<code>0s</code>&nbsp;and a&nbsp;<em>closed island</em>&nbsp;is an island&nbsp;<strong>totally</strong>&nbsp;(all left, top, right, bottom) surrounded by&nbsp;<code>1s.</code></p>



<p>Return the number of&nbsp;<em>closed islands</em>.</p>



<p><strong>Example 1:</strong></p>



<figure class="wp-block-image"><img src="https://assets.leetcode.com/uploads/2019/10/31/sample_3_1610.png" alt=""/></figure>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> grid = [[1,1,1,1,1,1,1,0],[1,0,0,0,0,1,1,0],[1,0,1,0,1,1,1,0],[1,0,0,0,0,1,0,1],[1,1,1,1,1,1,1,0]]
<strong>Output:</strong> 2
<strong>Explanation:</strong> 
Islands in gray are closed because they are completely surrounded by water (group of 1s).</pre>



<p><strong>Example 2:</strong></p>



<figure class="wp-block-image"><img src="https://assets.leetcode.com/uploads/2019/10/31/sample_4_1610.png" alt=""/></figure>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> grid = [[0,0,1,0,0],[0,1,0,1,0],[0,1,1,1,0]]
<strong>Output:</strong> 1
</pre>



<p><strong>Example 3:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> grid = [[1,1,1,1,1,1,1],
&nbsp;              [1,0,0,0,0,0,1],
&nbsp;              [1,0,1,1,1,0,1],
&nbsp;              [1,0,1,0,1,0,1],
&nbsp;              [1,0,1,1,1,0,1],
&nbsp;              [1,0,0,0,0,0,1],
               [1,1,1,1,1,1,1]]
<strong>Output:</strong> 2
</pre>



<p><strong>Constraints:</strong></p>



<ul><li><code>1 &lt;= grid.length, grid[0].length &lt;= 100</code></li><li><code>0 &lt;= grid[i][j] &lt;=1</code></li></ul>



<h2><strong>Solution: DFS/Backtracking</strong></h2>



<p>For each connected component, if it can reach the boundary then it&#8217;s not a closed island.</p>



<p>Time complexity: O(n*m)<br>Space complexity: O(n*m)</p>



<div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  int closedIsland(vector&lt;vector&lt;int&gt;&gt;&amp; grid) {    
    const int n = grid.size();
    const int m = grid[0].size();    
    function&lt;int(int, int)&gt; dfs = [&amp;](int x, int y) {
      if (x &lt; 0 || y &lt; 0 || x &gt;= m || y &gt;= n) return 0;      
      if (grid[y][x]++) return 1;
      return dfs(x + 1, y) &amp; dfs(x - 1, y) &amp; dfs(x, y + 1) &amp; dfs(x, y - 1);
    };
    
    int ans = 0;
    for (int i = 0; i &lt; n; ++i)
      for (int j = 0; j &lt; m; ++j)
        if (!grid[i][j]) ans += dfs(j, i);      
    return ans;
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/searching/leetcode-1254-number-of-closed-islands/">花花酱 LeetCode 1254. Number of Closed Islands</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/searching/leetcode-1254-number-of-closed-islands/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1202. Smallest String With Swaps</title>
		<link>https://zxi.mytechroad.com/blog/graph/leetcode-1202-smallest-string-with-swaps/</link>
					<comments>https://zxi.mytechroad.com/blog/graph/leetcode-1202-smallest-string-with-swaps/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 22 Sep 2019 09:18:15 +0000</pubDate>
				<category><![CDATA[Graph]]></category>
		<category><![CDATA[connected components]]></category>
		<category><![CDATA[DFS]]></category>
		<category><![CDATA[graph]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[union find]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=5573</guid>

					<description><![CDATA[<p>You are given a string&#160;s, and an array of pairs of indices in the string&#160;pairs&#160;where&#160;pairs[i] =&#160;[a, b]&#160;indicates 2 indices(0-indexed) of the string. You can&#160;swap the&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/graph/leetcode-1202-smallest-string-with-swaps/">花花酱 LeetCode 1202. Smallest String With Swaps</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe width="500" height="375" src="https://www.youtube.com/embed/qosJ4632QAg?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<p>You are given a string&nbsp;<code>s</code>, and an array of pairs of indices in the string&nbsp;<code>pairs</code>&nbsp;where&nbsp;<code>pairs[i] =&nbsp;[a, b]</code>&nbsp;indicates 2 indices(0-indexed) of the string.</p>



<p>You can&nbsp;swap the characters at any pair of indices in the given&nbsp;<code>pairs</code>&nbsp;<strong>any number of times</strong>.</p>



<p>Return the&nbsp;lexicographically smallest string that&nbsp;<code>s</code>&nbsp;can be changed to after using the swaps.</p>



<p><strong>Example 1:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> s = "dcab", pairs = [[0,3],[1,2]]
<strong>Output:</strong> "bacd"
<strong>Explaination:</strong> 
Swap s[0] and s[3], s = "bcad"
Swap s[1] and s[2], s = "bacd"
</pre>



<p><strong>Example 2:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> s = "dcab", pairs = [[0,3],[1,2],[0,2]]
<strong>Output:</strong> "abcd"
<strong>Explaination: </strong>
Swap s[0] and s[3], s = "bcad"
Swap s[0] and s[2], s = "acbd"
Swap s[1] and s[2], s = "abcd"</pre>



<p><strong>Example 3:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> s = "cba", pairs = [[0,1],[1,2]]
<strong>Output:</strong> "abc"
<strong>Explaination: </strong>
Swap s[0] and s[1], s = "bca"
Swap s[1] and s[2], s = "bac"
Swap s[0] and s[1], s = "abc"

</pre>



<p><strong>Constraints:</strong></p>



<ul><li><code>1 &lt;= s.length &lt;= 10^5</code></li><li><code>0 &lt;= pairs.length &lt;= 10^5</code></li><li><code>0 &lt;= pairs[i][0], pairs[i][1] &lt;&nbsp;s.length</code></li><li><code>s</code>&nbsp;only contains lower case English letters.</li></ul>



<h2><strong>Solution: Connected Components</strong></h2>



<figure class="wp-block-image"><img width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2019/09/1202-ep271.png" alt="" class="wp-image-5587" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2019/09/1202-ep271.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2019/09/1202-ep271-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2019/09/1202-ep271-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></figure>



<p>Use DFS / Union-Find to find all the connected components of swapable indices. For each connected components (index group), extract the subsequence of corresponding chars as a string, sort it and put it back to the original string in the same location.</p>



<p>e.g. s = &#8220;dcab&#8221;, pairs = [[0,3],[1,2]]<br>There are two connected components: {0,3}, {1,2}<br>subsequences: <br>1. 0,3 &#8220;db&#8221;, sorted: &#8220;bd&#8221;<br>2. 1,2 &#8220;ca&#8221;, sorted: &#8220;ac&#8221;<br>0 =&gt; b<br>1 =&gt; a<br>2 =&gt; c<br>3 =&gt; d<br>final = &#8220;bacd&#8221;<br></p>



<p>Time complexity: DFS: O(nlogn + k*(V+E)), Union-Find: O(nlogn + V+E)<br>Space complexity: O(n)</p>



<div class="responsive-tabs">
<h2 class="tabtitle">C++/DFS</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">// Author: Huahua, 268 ms, 89 MB
class Solution {
public:
  string smallestStringWithSwaps(string s, vector&lt;vector&lt;int&gt;&gt;&amp; pairs) {
    vector&lt;vector&lt;int&gt;&gt; g(s.length());
    for (const auto&amp; e : pairs) {
      g[e[0]].push_back(e[1]);
      g[e[1]].push_back(e[0]);
    }

    unordered_set&lt;int&gt; seen;
    vector&lt;int&gt; idx;
    string tmp;
    function&lt;void(int)&gt; dfs = [&amp;](int cur) {
      if (seen.count(cur)) return;
      seen.insert(cur);
      idx.push_back(cur);
      tmp += s[cur];
      for (int nxt : g[cur]) dfs(nxt);
    };

    for (int i = 0; i &lt; s.length(); ++i) {
      if (seen.count(i)) continue;
      idx.clear();
      tmp.clear();
      dfs(i);
      sort(begin(tmp), end(tmp));
      sort(begin(idx), end(idx));      
      for (int k = 0; k &lt; idx.size(); ++k)
        s[idx[k]] = tmp[k];
    }
    return s;
  }
};</pre>

</div><h2 class="tabtitle">C++/Union-Find</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">// Author: Huahua, 152 ms, 48.2 MB
class Solution {
public:
  string smallestStringWithSwaps(string s, vector&lt;vector&lt;int&gt;&gt;&amp; pairs) {
    int n = s.length();
    vector&lt;int&gt; p(n);    
    iota(begin(p), end(p), 0); // p = {0, 1, 2, ... n - 1}
    
    function&lt;int(int)&gt; find = [&amp;](int x) {
      return p[x] == x ? x : p[x] = find(p[x]);
    };        
    
    for (const auto&amp; e : pairs)
      p[find(e[0])] = find(e[1]); // union
    
    vector&lt;vector&lt;int&gt;&gt; idx(n);
    vector&lt;string&gt; ss(n);
    
    for (int i = 0; i &lt; s.length(); ++i) {
      int id = find(i);      
      idx[id].push_back(i); // already sorted
      ss[id].push_back(s[i]);
    }
    
    for (int i = 0; i &lt; n; ++i) {      
      sort(begin(ss[i]), end(ss[i]));
      for (int k = 0; k &lt; idx[i].size(); ++k)
        s[idx[i][k]] = ss[i][k];
    }
    
    return s;
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/graph/leetcode-1202-smallest-string-with-swaps/">花花酱 LeetCode 1202. Smallest String With Swaps</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/graph/leetcode-1202-smallest-string-with-swaps/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 947. Most Stones Removed with Same Row or Column</title>
		<link>https://zxi.mytechroad.com/blog/graph/leetcode-947-most-stones-removed-with-same-row-or-column/</link>
					<comments>https://zxi.mytechroad.com/blog/graph/leetcode-947-most-stones-removed-with-same-row-or-column/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Fri, 30 Nov 2018 05:06:23 +0000</pubDate>
				<category><![CDATA[Graph]]></category>
		<category><![CDATA[connected components]]></category>
		<category><![CDATA[island]]></category>
		<category><![CDATA[union find]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=4379</guid>

					<description><![CDATA[<p>Problem On a 2D plane, we place stones at some integer coordinate points.&#160; Each coordinate point may have at most one stone. Now, a&#160;move&#160;consists of&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/graph/leetcode-947-most-stones-removed-with-same-row-or-column/">花花酱 LeetCode 947. Most Stones Removed with Same Row or Column</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1><strong>Problem</strong></h1>
<p>On a 2D plane, we place stones at some integer coordinate points.&nbsp; Each coordinate point may have at most one stone.</p>
<p>Now, a&nbsp;<em>move</em>&nbsp;consists of removing a stone&nbsp;that shares a column or row with another stone on the grid.</p>
<p>What is the largest possible number of moves we can make?</p>
<p><strong>Example 1:</strong></p>
<pre class="crayon:false"><strong>Input: </strong>stones = <span id="example-input-1-2">[[0,0],[0,1],[1,0],[1,2],[2,1],[2,2]]</span>
<strong>Output: </strong>5
</pre>
<p><strong>Example 2:</strong></p>
<pre class="crayon:false"><strong>Input: </strong>stones = <span id="example-input-2-2">[[0,0],[0,2],[1,1],[2,0],[2,2]]</span>
<strong>Output: </strong>3
</pre>
<p><strong>Example 3:</strong></p>
<pre class="crayon:false"><strong>Input: </strong>stones = <span id="example-input-3-2">[[0,0]]</span>
<strong>Output: </strong>0
</pre>
<p><strong>Note:</strong></p>
<ol>
<li><code>1 &lt;= stones.length &lt;= 1000</code></li>
<li><code>0 &lt;= stones[i][j] &lt; 10000</code></li>
</ol>
<p><script async="" src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script><br />
<ins class="adsbygoogle" style="display:block" data-ad-format="fluid" data-ad-layout-key="-fb+5w+4e-db+86" data-ad-client="ca-pub-2404451723245401" data-ad-slot="2162692788"></ins><br />
<script><br />
     (adsbygoogle = window.adsbygoogle || []).push({});<br />
</script></p>
<h1><strong>Solution 2: Union Find</strong></h1>
<p>Find all connected components (islands)</p>
<p>Ans = # of stones &#8211; # of islands</p>
<p><div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">// Author: Huahua, running time: 16 ms
class Solution {
public:
  int removeStones(vector&lt;vector&lt;int&gt;&gt;&amp; stones) {
    const int kSize = 10000;
    DSU dsu(kSize * 2);
    for (const auto&amp; stone : stones)
      dsu.Union(stone[0], stone[1] + kSize);
    unordered_set&lt;int&gt; seen;
    for (const auto&amp; stone : stones)
      seen.insert(dsu.Find(stone[0]));
    return stones.size() - seen.size();
  }
private:
  class DSU {
  public:
    DSU(int n): p_(n) {
      for (int i = 0 ; i &lt; n; ++i)
        p_[i] = i;              
    }
    
    void Union(int i, int j) {
      p_[Find(i)] = Find(j);      
    }
    
    int Find(int i) {
      if (p_[i] != i) p_[i] = Find(p_[i]);
      return p_[i];
    }    
  private:
    vector&lt;int&gt; p_;    
  };
};</pre><p></div></div></p>
<h1><strong>Related Problems</strong></h1>
<ul>
<li><a href="https://zxi.mytechroad.com/blog/searching/leetcode-200-number-of-islands/">花花酱 LeetCode 200. Number of Islands</a></li>
</ul>
<p>&nbsp;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/graph/leetcode-947-most-stones-removed-with-same-row-or-column/">花花酱 LeetCode 947. Most Stones Removed with Same Row or Column</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/graph/leetcode-947-most-stones-removed-with-same-row-or-column/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 841. Keys and Rooms</title>
		<link>https://zxi.mytechroad.com/blog/graph/leetcode-841-keys-and-rooms/</link>
					<comments>https://zxi.mytechroad.com/blog/graph/leetcode-841-keys-and-rooms/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 27 May 2018 16:25:19 +0000</pubDate>
				<category><![CDATA[Graph]]></category>
		<category><![CDATA[connected components]]></category>
		<category><![CDATA[DFS]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=2847</guid>

					<description><![CDATA[<p>Problem There are N rooms and you start in room 0.  Each room has a distinct number in 0, 1, 2, ..., N-1, and each room may have some keys&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/graph/leetcode-841-keys-and-rooms/">花花酱 LeetCode 841. Keys and Rooms</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/y46WQ5KMiD8?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<h1>Problem</h1>
<p>There are <code>N</code> rooms and you start in room <code>0</code>.  Each room has a distinct number in <code>0, 1, 2, ..., N-1</code>, and each room may have some keys to access the next room.</p>
<p>Formally, each room <code>i</code> has a list of keys <code>rooms[i]</code>, and each key <code>rooms[i][j]</code> is an integer in <code>[0, 1, ..., N-1]</code> where <code>N = rooms.length</code>.  A key <code>rooms[i][j] = v</code> opens the room with number <code>v</code>.</p>
<p>Initially, all the rooms start locked (except for room <code>0</code>).</p>
<p>You can walk back and forth between rooms freely.</p>
<p>Return <code>true</code> if and only if you can enter every room.</p>
<p><strong>Example 1:</strong></p>
<pre class="crayon:false"><strong>Input: </strong>[[1],[2],[3],[]]
<strong>Output: </strong>true
<strong>Explanation:  </strong>
We start in room 0, and pick up key 1.
We then go to room 1, and pick up key 2.
We then go to room 2, and pick up key 3.
We then go to room 3.  Since we were able to go to every room, we return true.
</pre>
<p><strong>Example 2:</strong></p>
<pre class="crayon:false"><strong>Input: </strong>[[1,3],[3,0,1],[2],[0]]
<strong>Output: </strong>false
<strong>Explanation: </strong>We can't enter the room with number 2.
</pre>
<p><b>Note:</b></p>
<ol>
<li><code>1 &lt;= rooms.length &lt;= 1000</code></li>
<li><code>0 &lt;= rooms[i].length &lt;= 1000</code></li>
<li>The number of keys in all rooms combined is at most <code>3000</code>.</li>
</ol>
<h1><img class="alignnone size-full wp-image-2858" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2018/05/841-ep190.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/05/841-ep190.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/05/841-ep190-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/05/841-ep190-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></h1>
<h1><strong>Solution: DFS</strong></h1>
<p>Time complexity: O(V + E)</p>
<p>Space complexity: O(V)</p>
<p>C++</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 12 ms
class Solution {
public:
  bool canVisitAllRooms(vector&lt;vector&lt;int&gt;&gt;&amp; rooms) {
    unordered_set&lt;int&gt; visited;
    dfs(rooms, 0, visited);
    return visited.size() == rooms.size();
  }
private:
  void dfs(const vector&lt;vector&lt;int&gt;&gt;&amp; rooms, 
           int cur, unordered_set&lt;int&gt;&amp; visited) {
    if (visited.count(cur)) return;
    visited.insert(cur);
    for (int nxt : rooms[cur])
      dfs(rooms, nxt, visited);
  }
};</pre><p>&nbsp;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/graph/leetcode-841-keys-and-rooms/">花花酱 LeetCode 841. Keys and Rooms</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/graph/leetcode-841-keys-and-rooms/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 827. Making A Large Island</title>
		<link>https://zxi.mytechroad.com/blog/graph/leetcode-827-making-a-large-island/</link>
					<comments>https://zxi.mytechroad.com/blog/graph/leetcode-827-making-a-large-island/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Mon, 30 Apr 2018 10:59:51 +0000</pubDate>
				<category><![CDATA[Graph]]></category>
		<category><![CDATA[connected components]]></category>
		<category><![CDATA[DFS]]></category>
		<category><![CDATA[graph]]></category>
		<category><![CDATA[hard]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=2808</guid>

					<description><![CDATA[<p>Problem In a 2D grid of 0s and 1s, we change at most one 0 to a 1. After, what is the size of the largest island? (An island is a&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/graph/leetcode-827-making-a-large-island/">花花酱 LeetCode 827. Making A Large Island</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/KqkXZpRB1x8?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<h1><strong>Problem</strong></h1>
<p>In a 2D grid of <code>0</code>s and <code>1</code>s, we change at most one <code>0</code> to a <code>1</code>.</p>
<p>After, what is the size of the largest island? (An island is a 4-directionally connected group of <code>1</code>s).</p>
<p><strong>Example 1:</strong></p>
<pre class="crayon:false"><strong>Input: </strong>[[1, 0], [0, 1]]
<strong>Output:</strong> 3
<strong>Explanation:</strong> Change one 0 to 1 and connect two 1s, then we get an island with area = 3.
</pre>
<p><strong>Example 2:</strong></p>
<pre class="crayon:false"><strong>Input: </strong>[[1, 1], [1, 0]]
<strong>Output:</strong> 4
<strong>Explanation: </strong>Change the 0 to 1 and make the island bigger, only one island with area = 1.</pre>
<p><strong>Example 3:</strong></p>
<pre class="crayon:false"><strong>Input: </strong>[[1, 1], [1, 1]]
<strong>Output:</strong> 4
<strong>Explanation:</strong> Can't change any 0 to 1, only one island with area = 1.</pre>
<p>Notes:</p>
<ul>
<li><code>1 &lt;= grid.length = grid[0].length &lt;= 50</code>.</li>
<li><code>0 &lt;= grid[i][j] &lt;= 1</code>.</li>
</ul>
<h1><strong>Solution</strong></h1>
<p>Step 1: give each connected component a unique id and count its ara.</p>
<p>Step 2: for each 0 zero, check its 4 neighbours, sum areas up by unique ids.</p>
<p>Time complexity: O(n*m)</p>
<p>Space complexity: O(n*m)</p>
<p>C++</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 14 ms
class Solution {
public:
  int largestIsland(vector&lt;vector&lt;int&gt;&gt;&amp; grid) {
    color_ = 1;
    g_ = &amp;grid;
    m_ = grid.size();
    n_ = grid[0].size();
    unordered_map&lt;int, int&gt; areas; // color -&gt; area
    int ans = 0;
    for (int i = 0; i &lt; m_; ++i)
      for (int j = 0; j &lt; n_; ++j)
        if (grid[i][j] == 1) {
          ++color_;
          areas[color_] = getArea(j, i);
          ans = max(ans, areas[color_]);
        }
    for (int i = 0; i &lt; m_; ++i)
      for (int j = 0; j &lt; n_; ++j)
        if (grid[i][j] == 0) {                    
          int area = 1;
          for (int color : set&lt;int&gt;{getColor(j, i - 1), getColor(j, i + 1),
                                    getColor(j - 1, i), getColor(j + 1, i)}) 
            area += areas[color];
          ans = max(ans, area);
        }
    return ans;
  }
private:
  int m_;
  int n_;
  int color_;
  vector&lt;vector&lt;int&gt;&gt;* g_; // does not own the object.
  
  int getColor(int x, int y) {
    return (x &lt; 0 || x &gt;= n_ || y &lt; 0 || y &gt;= m_) ? 0 : (*g_)[y][x];
  }
  
  // Return the area of a connected component, set all elements to color_.
  int getArea(int x, int y) {
    if (x &lt; 0 || x &gt;= n_ || y &lt; 0 || y &gt;= m_ || (*g_)[y][x] != 1) return 0;
    (*g_)[y][x] = color_;
    return 1 + getArea(x - 1, y) + getArea(x + 1, y) 
             + getArea(x, y - 1) + getArea(x, y + 1);
  }
};</pre><p>&nbsp;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/graph/leetcode-827-making-a-large-island/">花花酱 LeetCode 827. Making A Large Island</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/graph/leetcode-827-making-a-large-island/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 817. Linked List Components</title>
		<link>https://zxi.mytechroad.com/blog/graph/leetcode-817-linked-list-components/</link>
					<comments>https://zxi.mytechroad.com/blog/graph/leetcode-817-linked-list-components/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 15 Apr 2018 03:34:29 +0000</pubDate>
				<category><![CDATA[Graph]]></category>
		<category><![CDATA[List]]></category>
		<category><![CDATA[connected components]]></category>
		<category><![CDATA[graph]]></category>
		<category><![CDATA[list]]></category>
		<category><![CDATA[medium]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=2493</guid>

					<description><![CDATA[<p>Problem 题目大意：给你一个链表，再给你一些合法的节点，问你链表中有多少个连通分量（所有节点必须合法）。 https://leetcode.com/problems/linked-list-components/description/ We are given head, the head node of a linked list containing unique integer values. We are also given the list G, a subset of the&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/graph/leetcode-817-linked-list-components/">花花酱 LeetCode 817. Linked List Components</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/y1_lFSkQNDc?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<h1><strong>Problem</strong></h1>
<p>题目大意：给你一个链表，再给你一些合法的节点，问你链表中有多少个连通分量（所有节点必须合法）。</p>
<p><a href="https://leetcode.com/problems/linked-list-components/description/">https://leetcode.com/problems/linked-list-components/description/</a></p>
<p>We are given <code>head</code>, the head node of a linked list containing <strong>unique integer values</strong>.</p>
<p>We are also given the list <code>G</code>, a subset of the values in the linked list.</p>
<p>Return the number of connected components in <code>G</code>, where two values are connected if they appear consecutively in the linked list.</p>
<p><strong>Example 1:</strong></p>
<pre class="crayon:false"><strong>Input:</strong> 
head: 0-&gt;1-&gt;2-&gt;3
G = [0, 1, 3]
<strong>Output:</strong> 2
<strong>Explanation:</strong> 
0 and 1 are connected, so [0, 1] and [3] are the two connected components.
</pre>
<p><strong>Example 2:</strong></p>
<pre class="crayon:false"><strong>Input:</strong> 
head: 0-&gt;1-&gt;2-&gt;3-&gt;4
G = [0, 3, 1, 4]
<strong>Output:</strong> 2
<strong>Explanation:</strong> 
0 and 1 are connected, 3 and 4 are connected, so [0, 1] and [3, 4] are the two connected components.
</pre>
<p><strong>Note:</strong></p>
<ul>
<li>If <code>N</code> is the length of the linked list given by <code>head</code>, <code>1 &lt;= N &lt;= 10000</code>.</li>
<li>The value of each node in the linked list will be in the range<code> [0, N - 1]</code>.</li>
<li><code>1 &lt;= G.length &lt;= 10000</code>.</li>
<li><code>G</code> is a subset of all values in the linked list.</li>
</ul>
<p><img class="alignnone size-full wp-image-2500" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2018/04/817-ep181.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/04/817-ep181.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/04/817-ep181-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/04/817-ep181-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<h1>Solution1: Graph Traversal using DFS</h1>
<p></p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 76 ms
class Solution {
public:
  int numComponents(ListNode* head, vector&lt;int&gt;&amp; G) {
    unordered_set&lt;int&gt; f(G.begin(), G.end());
    unordered_map&lt;int, vector&lt;int&gt;&gt; g;
    int u = head-&gt;val;
    while (head-&gt;next) {
      head = head-&gt;next;
      int v = head-&gt;val;
      if (f.count(v) &amp;&amp; f.count(u)) {
        g[u].push_back(v);
        g[v].push_back(u);
      }
      u = v;
    }
    int ans = 0;
    unordered_set&lt;int&gt; visited;
    for (int u : G) {      
      if (visited.count(u)) continue;
      ++ans;
      dfs(u, g, visited);
    }
    return ans;
  }
private:
  void dfs(int cur, unordered_map&lt;int, vector&lt;int&gt;&gt;&amp; g, unordered_set&lt;int&gt;&amp; visited) {
    if (visited.count(cur)) return;
    visited.insert(cur);
    for (const int next : g[cur])
      dfs(next, g, visited);    
  }
};</pre><p></p>
<h1>Solution 2: Count tail node in sub graph</h1>
<p></p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 35 ms
class Solution {
public:
  int numComponents(ListNode* head, vector&lt;int&gt;&amp; G) {
    unordered_set&lt;int&gt; g(G.begin(), G.end());
    int ans = 0;
    while (head) {
      if (g.count(head-&gt;val) &amp;&amp; (!head-&gt;next || !g.count(head-&gt;next-&gt;val)))
        ++ans;
      head = head-&gt;next;
    }
    return ans;
  }
};</pre><p>&nbsp;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/graph/leetcode-817-linked-list-components/">花花酱 LeetCode 817. Linked List Components</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/graph/leetcode-817-linked-list-components/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 803. Bricks Falling When Hit</title>
		<link>https://zxi.mytechroad.com/blog/searching/leetcode-803-bricks-falling-when-hit/</link>
					<comments>https://zxi.mytechroad.com/blog/searching/leetcode-803-bricks-falling-when-hit/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 18 Mar 2018 09:43:17 +0000</pubDate>
				<category><![CDATA[Search]]></category>
		<category><![CDATA[Simulation]]></category>
		<category><![CDATA[connected components]]></category>
		<category><![CDATA[DFS]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[search]]></category>
		<category><![CDATA[simulation]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=2206</guid>

					<description><![CDATA[<p>Problem 题目大意：给你一堵砖墙，求每次击碎一块后掉落的砖头数量。 We have a grid of 1s and 0s; the 1s in a cell represent bricks.  A brick will not drop if and only&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/searching/leetcode-803-bricks-falling-when-hit/">花花酱 LeetCode 803. Bricks Falling When Hit</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/UrMZrAyyliw?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<h1><strong>Problem</strong></h1>
<p>题目大意：给你一堵砖墙，求每次击碎一块后掉落的砖头数量。</p>
<p>We have a grid of 1s and 0s; the 1s in a cell represent bricks.  A brick will not drop if and only if it is directly connected to the top of the grid, or at least one of its (4-way) adjacent bricks will not drop.</p>
<p>We will do some erasures sequentially. Each time we want to do the erasure at the location (i, j), the brick (if it exists) on that location will disappear, and then some other bricks may drop because of that erasure.</p>
<p>Return an array representing the number of bricks that will drop after each erasure in sequence.</p>
<pre class="crayon:false"><strong>Example 1:</strong>
<strong>Input:</strong> 
grid = [[1,0,0,0],[1,1,1,0]]
hits = [[1,0]]
<strong>Output:</strong> [2]
<strong>Explanation: </strong>
If we erase the brick at (1, 0), the brick at (1, 1) and (1, 2) will drop. So we should return 2.</pre>
<pre class="crayon:false"><strong>Example 2:</strong>
<strong>Input:</strong> 
grid = [[1,0,0,0],[1,1,0,0]]
hits = [[1,1],[1,0]]
<strong>Output:</strong> [0,0]
<strong>Explanation: </strong>
When we erase the brick at (1, 0), the brick at (1, 1) has already disappeared due to the last move. So each erasure will cause no bricks dropping.  Note that the erased brick (1, 0) will not be counted as a dropped brick.</pre>
<h1>Idea</h1>
<ol>
<li>For each day, hit and clear the specified brick.</li>
<li>Find all connected components (CCs) using DFS.</li>
<li>For each CC, if there is no brick that is on the first row that the entire cc will drop. Clear those CCs.</li>
</ol>
<p><img class="alignnone size-full wp-image-2223" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2018/03/803-ep175.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/03/803-ep175.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/03/803-ep175-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/03/803-ep175-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<h1>Solution: DFS</h1>
<p><div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 1261 ms
class Solution {
public:
  vector&lt;int&gt; hitBricks(vector&lt;vector&lt;int&gt;&gt;&amp; grid, vector&lt;vector&lt;int&gt;&gt;&amp; hits) {    
    dirs_ = {0, -1, 0, 1, 0};    
    m_ = grid.size();
    n_ = grid[0].size();
    g_.swap(grid);
    seq_ = 1;
    
    vector&lt;int&gt; ans;
    for (int i = 0; i &lt; hits.size(); ++i)
      ans.push_back(hit(hits[i][1], hits[i][0]));
    return ans;
  }
private:
  vector&lt;vector&lt;int&gt;&gt; g_;
  vector&lt;int&gt; dirs_;
  int seq_;
  int m_;
  int n_;
  
  // hit x, y and return the number of bricks fallen.
  int hit(int x, int y) {
    if (x &lt; 0 || x &gt;= n_ || y &lt; 0 || y &gt;= m_) return 0;    
    g_[y][x] = 0;
    int ans = 0; 
    for (int i = 0; i &lt; 4; ++i) {
      ++seq_;
      int count = 0;
      if (!fall(x + dirs_[i], y + dirs_[i + 1], false, count)) continue;      
      ++seq_;
      ans += count;
      fall(x + dirs_[i], y + dirs_[i + 1], true, count);
    }
    return ans;
  }
  
  // Check whether the CC contains (x, y) will fall or not.
  // Set all nodes in this CC as seq_ or 0 if clear.
  // count: the # of nodes in this CC.
  bool fall(int x, int y, bool clear, int&amp; count) {
    if (x &lt; 0 || x &gt;= n_ || y &lt; 0 || y &gt;= m_) return true;
    if (g_[y][x] == seq_ || g_[y][x] == 0) return true;
    if (y == 0) return false;
    g_[y][x] = clear ? 0 : seq_;
    ++count;
    for (int i = 0; i &lt; 4; ++i)
      if (!fall(x + dirs_[i], y + dirs_[i + 1], clear, count)) return false;
    return true;
  }
};</pre><p></div><h2 class="tabtitle">Java</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">// Author: Huahua
// Stack Overflow (1024 recursive calls)
class Solution {
  int[] dirs = new int[]{0, -1, 0, 1, 0};
  int m;
  int n;
  int[][] g;
  int seq;
  int count;
  
  public int[] hitBricks(int[][] grid, int[][] hits) {
    this.g = grid;
    this.m = grid.length;
    this.n = grid[0].length;
    
    int[] ans = new int[hits.length];
    
    for (int i = 0; i &lt; hits.length; ++i)
      ans[i] = hit(hits[i][1], hits[i][0]);
    
    return ans;
  }
  
  private int hit(int x, int y) {
    if (x &lt; 0 || x &gt;= n || y &lt; 0 || y &gt;= m || g[y][x] == 0) return 0;
    g[y][x] = 0;
    int ans = 0;
    for (int i = 0; i &lt; 4; ++i) {
      ++seq;      
      count = 0;
      if (!fall(x + dirs[i], y + dirs[i + 1], false)) continue;    
      ans += count;
      ++seq;
      fall(x + dirs[i], y + dirs[i + 1], true);
    }
    return ans;
  }
  
  private boolean fall(int x, int y, boolean clear) {
    if (x &lt; 0 || x &gt;= n || y &lt; 0 || y &gt;= m) return true;
    if (g[y][x] == seq || g[y][x] == 0) return true;
    if (y == 0) return false;
    g[y][x] = clear ? 0 : seq;
    ++count;
    for (int i = 0; i &lt; 4; ++i)
      if (!fall(x + dirs[i], y + dirs[i + 1], clear)) return false;
    return true;
  }
}</pre><p></div></div></p>
<h1><strong>Related Problems</strong></h1>
<ul>
<li><a href="http://zxi.mytechroad.com/blog/searching/leetcode-749-contain-virus/">花花酱 LeetCode 749. Contain Virus</a></li>
</ul>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/searching/leetcode-803-bricks-falling-when-hit/">花花酱 LeetCode 803. Bricks Falling When Hit</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/searching/leetcode-803-bricks-falling-when-hit/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 684. Redundant Connection</title>
		<link>https://zxi.mytechroad.com/blog/tree/leetcode-684-redundant-connection/</link>
					<comments>https://zxi.mytechroad.com/blog/tree/leetcode-684-redundant-connection/#comments</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Fri, 29 Sep 2017 03:54:42 +0000</pubDate>
				<category><![CDATA[Graph]]></category>
		<category><![CDATA[Tree]]></category>
		<category><![CDATA[connected components]]></category>
		<category><![CDATA[DFS]]></category>
		<category><![CDATA[union find]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=449</guid>

					<description><![CDATA[<p>https://leetcode.com/problems/redundant-connection/description/ Problem: In this problem, a tree is an undirected graph that is connected and has no cycles. The given input is a graph that started as&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/tree/leetcode-684-redundant-connection/">花花酱 LeetCode 684. Redundant Connection</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/4hJ721ce010?feature=oembed" frameborder="0" gesture="media" allow="encrypted-media" allowfullscreen></iframe></p>
<p><a href="https://leetcode.com/problems/redundant-connection/description/">https://leetcode.com/problems/redundant-connection/description/</a></p>
<p><strong>Problem:</strong></p>
<p>In this problem, a tree is an <b>undirected</b> graph that is connected and has no cycles.</p>
<p>The given input is a graph that started as a tree with N nodes (with distinct values 1, 2, &#8230;, N), with one additional edge added. The added edge has two different vertices chosen from 1 to N, and was not an edge that already existed.</p>
<p>The resulting graph is given as a 2D-array of <code>edges</code>. Each element of <code>edges</code> is a pair <code>[u, v]</code> with <code>u &lt; v</code>, that represents an <b>undirected</b> edge connecting nodes <code>u</code> and <code>v</code>.</p>
<p>Return an edge that can be removed so that the resulting graph is a tree of N nodes. If there are multiple answers, return the answer that occurs last in the given 2D-array. The answer edge <code>[u, v]</code> should be in the same format, with <code>u &lt; v</code>.</p>
<p><b>Example 1:</b></p><pre class="crayon-plain-tag">Input: [[1,2], [1,3], [2,3]]
Output: [2,3]
Explanation: The given undirected graph will be like this:
  1
 / \
2 - 3</pre><p><b>Example 2:</b></p><pre class="crayon-plain-tag">Input: [[1,2], [2,3], [3,4], [1,4], [1,5]]
Output: [1,4]
Explanation: The given undirected graph will be like this:
5 - 1 - 2
    |   |
    4 - 3</pre><p><b>Note:</b></p>
<p>&nbsp;</p>
<ul>
<li>The size of the input 2D-array will be between 3 and 1000.</li>
<li>Every integer represented in the 2D-array will be between 1 and N, where N is the size of the input array.</li>
</ul>
<p><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script><br />
<ins class="adsbygoogle" style="display: block; text-align: center;" data-ad-layout="in-article" data-ad-format="fluid" data-ad-client="ca-pub-2404451723245401" data-ad-slot="7983117522"></ins><br />
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></p>
<p><strong>Idea:</strong><br />
DFS / Union-Find</p>
<p><a href="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/684-ep74-1.png"><img class="alignnone size-full wp-image-454" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/684-ep74-1.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/684-ep74-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/684-ep74-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/684-ep74-1-768x432.png 768w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/684-ep74-1-624x351.png 624w" sizes="(max-width: 960px) 100vw, 960px" /></a></p>
<p><a href="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/684-ep74-2.png"><img class="alignnone size-full wp-image-453" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/684-ep74-2.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/684-ep74-2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/684-ep74-2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/684-ep74-2-768x432.png 768w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/684-ep74-2-624x351.png 624w" sizes="(max-width: 960px) 100vw, 960px" /></a></p>
<p>&nbsp;</p>
<p><strong>Solutions:</strong></p>
<p>C++ / DFS</p><pre class="crayon-plain-tag">// Author: Huahua
// Time Complexity: O(n^2)
// Running Time: 22 ms
class Solution {
public:
    vector&lt;int&gt; findRedundantConnection(vector&lt;vector&lt;int&gt;&gt;&amp; edges) {
        unordered_map&lt;int, vector&lt;int&gt;&gt; graph;
        for (const auto&amp; edge : edges) {
            int u = edge[0];
            int v = edge[1];
            
            unordered_set&lt;int&gt; visited;
            if (hasPath(u, v, graph, visited))
                return edge;
            
            graph[u].push_back(v);
            graph[v].push_back(u);
        }
        return {};
    }
private:
    bool hasPath(int curr, 
                 int goal, 
                 const unordered_map&lt;int, vector&lt;int&gt;&gt;&amp; graph, 
                 unordered_set&lt;int&gt;&amp; visited) {
        if (curr == goal) return true;
        visited.insert(curr);
        if (!graph.count(curr) || !graph.count(goal)) return false;
        for (int next : graph.at(curr)) {
            if (visited.count(next)) continue;
            if (hasPath(next, goal, graph, visited)) return true;
        }
        return false;
    }
};</pre><p>&nbsp;</p>
<p>C++ / Union Find</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 6 ms
class UnionFindSet {
public:
    UnionFindSet(int n) {
        ranks_ = vector&lt;int&gt;(n + 1, 0);        
        parents_ = vector&lt;int&gt;(n + 1, 0);                
        
        for (int i = 0; i &lt; parents_.size(); ++i)
            parents_[i] = i;
    }
    
    // Merge sets that contains u and v.
    // Return true if merged, false if u and v are already in one set.
    bool Union(int u, int v) {
        int pu = Find(u);
        int pv = Find(v);
        if (pu == pv) return false;
        
        // Meger low rank tree into high rank tree
        if (ranks_[pv] &gt; ranks_[pu])
            parents_[pu] = pv;           
        else if (ranks_[pu] &gt; ranks_[pv])
            parents_[pv] = pu;
        else {
            parents_[pv] = pu;
            ranks_[pv] += 1;
        }
        
        return true;
    }
    
    // Get the root of u.
    int Find(int u) {        
        // Compress the path during traversal
        if (u != parents_[u])
            parents_[u] = Find(parents_[u]);        
        return parents_[u];
    }
private:
    vector&lt;int&gt; parents_;
    vector&lt;int&gt; ranks_;
};

class Solution {
public:
    vector&lt;int&gt; findRedundantConnection(vector&lt;vector&lt;int&gt;&gt;&amp; edges) {    
        UnionFindSet s(edges.size());
        
        for(const auto&amp; edge: edges)
            if (!s.Union(edge[0], edge[1]))
                return edge;
        
        return {};
    }
};</pre><p>Java / Union Find</p><pre class="crayon-plain-tag">// Author: Huahua
// Runtime: 6 ms
class Solution {
    class UnionFindSet {
        private int[] parents_;
        private int[] ranks_;

        public UnionFindSet(int n) {
            parents_ = new int[n + 1];
            ranks_ = new int[n + 1];
            for (int i = 0; i &lt; parents_.length; ++i) {
                parents_[i] = i;
                ranks_[i] = 1;
            }
        }

        public boolean Union(int u, int v) {
            int pu = Find(u);
            int pv = Find(v);
            if (pu == pv) return false;

            if (ranks_[pv] &gt; ranks_[pu])
                parents_[pu] = pv;           
            else if (ranks_[pu] &gt; ranks_[pv])
                parents_[pv] = pu;
            else {
                parents_[pv] = pu;
                ranks_[pu] += 1;
            }

            return true;
        }

        public int Find(int u) {
            while (parents_[u] != u) {
                parents_[u] = parents_[parents_[u]];
                u = parents_[u];
            }
            return u;
        }
    }
    
    public int[] findRedundantConnection(int[][] edges) {
        UnionFindSet s = new UnionFindSet(edges.length);
        for (int[] edge : edges)
            if (!s.Union(edge[0], edge[1]))
                return edge;
        return null;
    }
    
    
}</pre><p>&nbsp;</p>
<p>Python: Union Find</p><pre class="crayon-plain-tag">"""
Author: Huahua
Running Time: 66 ms
"""
class Solution:
    def findRedundantConnection(self, edges):
        
        p = [0]*(len(edges) + 1)
        s = [1]*(len(edges) + 1)
        
        def find(u):
            while p[u] != u:
                p[u] = p[p[u]]
                u = p[u]
            return u
        
        for u, v in edges:
            if p[u] == 0: p[u] = u
            if p[v] == 0: p[v] = v
            pu, pv = find(u), find(v)
            if pu == pv: return [u, v]
            
            if s[pv] &gt; s[pu]: u, v = v, u
            p[pv] = pu
            s[pu] += s[pv]

        return []</pre><p>Python / Union Find V2</p><pre class="crayon-plain-tag">"""
Author: Huahua
Runtime: 59 ms (&lt;92.42%)
"""
class UnionFindSet:
    def __init__(self, n):
        self._parents = [i for i in range(n + 1)]
        self._ranks = [1 for i in range(n + 1)]
    
    def find(self, u):
        while u != self._parents[u]:
            self._parents[u] = self._parents[self._parents[u]]
            u = self._parents[u]
        return u
    
    def union(self, u, v):
        pu, pv = self.find(u), self.find(v)
        if pu == pv: return False
        
        if self._ranks[pu] &lt; self._ranks[pv]:
            self._parents[pu] = pv
        elif self._ranks[pu] &gt; self._ranks[pv]:
            self._parents[pv] = pu
        else:        
            self._parents[pv] = pu
            self._ranks[pu] += 1
        
        return True
        
class Solution:
    def findRedundantConnection(self, edges):
        s = UnionFindSet(len(edges))
        for edge in edges:
            if not s.union(edge[0], edge[1]): return edge
        return None
        ndSet(len(edges))
        for edge in edges:
            if not s.union(edge[0], edge[1]): return edge
        return None</pre><p>&nbsp;</p>
<p>&nbsp;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/tree/leetcode-684-redundant-connection/">花花酱 LeetCode 684. Redundant Connection</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/tree/leetcode-684-redundant-connection/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 547. Friend Circles</title>
		<link>https://zxi.mytechroad.com/blog/graph/leetcode-547-friend-circles/</link>
					<comments>https://zxi.mytechroad.com/blog/graph/leetcode-547-friend-circles/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Fri, 22 Sep 2017 04:29:41 +0000</pubDate>
				<category><![CDATA[Graph]]></category>
		<category><![CDATA[connected components]]></category>
		<category><![CDATA[DFS]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[SCC]]></category>
		<category><![CDATA[union find]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=382</guid>

					<description><![CDATA[<p>Problem: There are N students in a class. Some of them are friends, while some are not. Their friendship is transitive in nature. For example, if A&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/graph/leetcode-547-friend-circles/">花花酱 LeetCode 547. Friend Circles</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/HHiHno66j40?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<p><strong>Problem:</strong></p>
<p>There are <b>N</b> students in a class. Some of them are friends, while some are not. Their friendship is transitive in nature. For example, if A is a <b>direct</b> friend of B, and B is a <b>direct</b> friend of C, then A is an <b>indirect</b> friend of C. And we defined a friend circle is a group of students who are direct or indirect friends.</p>
<p>Given a <b>N*N</b> matrix <b>M</b> representing the friend relationship between students in the class. If M[i][j] = 1, then the i<sub>th</sub>and j<sub>th</sub> students are <b>direct</b> friends with each other, otherwise not. And you have to output the total number of friend circles among all the students.</p>
<p><b>Example 1:</b></p><pre class="crayon-plain-tag">Input: 
[[1,1,0],
 [1,1,0],
 [0,0,1]]
Output: 2</pre><p>E<b>xample 2:</b></p><pre class="crayon-plain-tag">Input: 
[[1,1,0],
 [1,1,1],
 [0,1,1]]
Output: 1</pre><p></p>
<ol>
<li>N is in range [1,200].</li>
<li>M[i][i] = 1 for all students.</li>
<li>If M[i][j] = 1, then M[j][i] = 1.</li>
</ol>
<p><strong>Idea:</strong></p>
<p>Find all connected components using DFS</p>
<p><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script><br />
<ins class="adsbygoogle" style="display: block; text-align: center;" data-ad-layout="in-article" data-ad-format="fluid" data-ad-client="ca-pub-2404451723245401" data-ad-slot="7983117522"></ins><br />
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></p>
<h1><strong>Solution: DFS</strong></h1>
<p><div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">// Author: Huahua
// Time complexity: O(n^2)
// Space complexity: O(n)
// Running Time: 25 ms
class Solution {
public:
    int findCircleNum(vector&lt;vector&lt;int&gt;&gt;&amp; M) {
        if (M.empty()) return 0;
        int n = M.size();
        int ans = 0;
        for (int i = 0; i &lt; n; ++i) {
            if (!M[i][i]) continue;
            ++ans;
            dfs(M, i, n);
        }
        return ans;
    }
private:
    void dfs(vector&lt;vector&lt;int&gt;&gt;&amp; M, int curr, int n) {        
        // Visit all friends (neighbors)
        for (int i = 0; i &lt; n; ++i) {
            if (!M[curr][i]) continue;
            M[curr][i] = M[i][curr] = 0;
            dfs(M, i, n);
        }
    }
};</pre><p></div><h2 class="tabtitle">Java</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">// Author: Huahua
// Time complexity: O(n^2)
// Space complexity: O(n)
// Running Time: 20 ms
class Solution {
    public int findCircleNum(int[][] M) {
        int n = M.length;
        if (n == 0) return 0;
        
        int ans = 0;
        for (int i = 0; i &lt; n; ++i) {
            if (M[i][i] == 0) continue;            
            ++ans;
            dfs(M, i, n);
        }
        return ans;
    }
    
    private void dfs(int[][] M, int curr, int n) {
        for (int i = 0; i &lt; n; ++i) {
            if (M[curr][i] == 0) continue;
            M[curr][i] = M[i][curr] = 0;
            dfs(M, i, n);
        }
    }
}</pre><p></div><h2 class="tabtitle">Python</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">"""
Author: Huahua
Time complexity: O(n^2)
Space complexity: O(n)
Running Time: 162 ms
"""
class Solution(object):
    def findCircleNum(self, M):
        """
        :type M: List[List[int]]
        :rtype: int
        """
        
        def dfs(M, curr, n):
            for i in xrange(n):
                if M[curr][i] == 1:
                    M[curr][i] = M[i][curr] = 0
                    dfs(M, i, n)
        
        n = len(M)
        ans = 0
        for i in xrange(n):
            if M[i][i] == 1:
                ans += 1
                dfs(M, i, n)
        
        return ans</pre><p></div></div></p>
<h1><strong>Solution 2: <a href="https://zxi.mytechroad.com/blog/data-structure/sp1-union-find-set/">Union Find</a></strong></h1>
<p><div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">// Author: Huahua
// Runtime: 19 ms
class UnionFindSet {
public:
    UnionFindSet(int n) {
        parents_ = vector&lt;int&gt;(n + 1, 0);
        ranks_ = vector&lt;int&gt;(n + 1, 0);
        
        for (int i = 0; i &lt; parents_.size(); ++i)
            parents_[i] = i;
    }
    
    bool Union(int u, int v) {
        int pu = Find(u);
        int pv = Find(v);
        if (pu == pv) return false;
        
        if (ranks_[pu] &gt; ranks_[pv]) {
            parents_[pv] = pu;
        } else if (ranks_[pv] &gt; ranks_[pu]) {
            parents_[pu] = pv;
        } else {
            parents_[pu] = pv;
            ++ranks_[pv];
        }
 
        return true;
    }
    
    int Find(int id) {        
        if (id != parents_[id])
            parents_[id] = Find(parents_[id]);        
        return parents_[id];
    }
    
private:
    vector&lt;int&gt; parents_;
    vector&lt;int&gt; ranks_;
};
 
class Solution {
public:
    int findCircleNum(vector&lt;vector&lt;int&gt;&gt;&amp; M) {
        int n = M.size();
        UnionFindSet s(n);
        for (int i = 0; i &lt; n; ++i)
            for (int j = i + 1; j &lt; n; ++j)
                if (M[i][j] == 1) s.Union(i, j);
        
        unordered_set&lt;int&gt; circles;
        for (int i = 0; i &lt; n; ++i)
            circles.insert(s.Find(i));
        
        return circles.size();
    }
};</pre><p></div></div></p>
<p>&nbsp;</p>
<h1><strong>Related Problems</strong></h1>
<ul>
<li><a href="http://zxi.mytechroad.com/blog/searching/leetcode-200-number-of-islands/">[解题报告] LeetCode 200. Number of Islands</a></li>
<li><a href="http://zxi.mytechroad.com/blog/graph/leetcode-695-max-area-of-island/">[解题报告] LeetCode 695. Max Area of Island</a></li>
<li><a href="http://zxi.mytechroad.com/blog/tree/leetcode-684-redundant-connection/">[解题报告] LeetCode 684. Redundant Connection</a></li>
<li><a href="http://zxi.mytechroad.com/blog/graph/leetcode-685-redundant-connection-ii/">[解题报告] LeetCode 685. Redundant Connection II</a></li>
<li><a href="http://zxi.mytechroad.com/blog/hashtable/leetcode-737-sentence-similarity-ii/">[解题报告] LeetCode 737. Sentence Similarity II</a></li>
</ul>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/graph/leetcode-547-friend-circles/">花花酱 LeetCode 547. Friend Circles</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/graph/leetcode-547-friend-circles/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 200. Number of Islands</title>
		<link>https://zxi.mytechroad.com/blog/searching/leetcode-200-number-of-islands/</link>
					<comments>https://zxi.mytechroad.com/blog/searching/leetcode-200-number-of-islands/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Thu, 21 Sep 2017 02:23:43 +0000</pubDate>
				<category><![CDATA[Graph]]></category>
		<category><![CDATA[Search]]></category>
		<category><![CDATA[connected components]]></category>
		<category><![CDATA[DFS]]></category>
		<category><![CDATA[easy]]></category>
		<category><![CDATA[island]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=373</guid>

					<description><![CDATA[<p>Problem: Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/searching/leetcode-200-number-of-islands/">花花酱 LeetCode 200. Number of Islands</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/XSmgFKe-XYU?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></p>
<p><strong>Problem:</strong></p>
<p>Given a 2d grid map of <code>'1'</code>s (land) and <code>'0'</code>s (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.</p>
<p><i><b>Example 1:</b></i></p><pre class="crayon-plain-tag">11110
11010
11000
00000</pre><p>Answer: 1</p>
<p><i><b>Example 2:</b></i></p><pre class="crayon-plain-tag">11000
11000
00100
00011</pre><p></p>
<h1><strong>Idea: DFS</strong></h1>
<p>Use DFS to find a connected component (an island) and mark all the nodes to 0.</p>
<p><a href="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/200-ep65-1.png"><img class="alignnone size-full wp-image-377" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/200-ep65-1.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/200-ep65-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/200-ep65-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/200-ep65-1-768x432.png 768w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/200-ep65-1-624x351.png 624w" sizes="(max-width: 960px) 100vw, 960px" /></a></p>
<p>Time complexity: O(mn)</p>
<p>Space complexity: O(mn)</p>
<h1><strong>Solution</strong></h1>
<p><div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">// Author: Huahua
// Time complexity: O(mn)
// Running time: 6 ms
class Solution {
public:
    int numIslands(vector&lt;vector&lt;char&gt;&gt;&amp; grid) {
        if (grid.empty()) return 0;
        int m = grid.size();
        int n = grid[0].size();
        int ans = 0;
        for (int y = 0; y &lt; m; ++y)
            for (int x = 0; x &lt; n; ++x) {
                ans += grid[y][x] - '0';
                dfs(grid, x, y, m, n);
            }
        return ans;                
    }   
private:
    void dfs(vector&lt;vector&lt;char&gt;&gt;&amp; grid, int x, int y, int m, int n) {
        if (x &lt; 0 || y &lt; 0 || x &gt;= n || y &gt;= m || grid[y][x] == '0')
            return;
        grid[y][x] = '0';
        dfs(grid, x + 1, y, m, n);
        dfs(grid, x - 1, y, m, n);
        dfs(grid, x, y + 1, m, n);
        dfs(grid, x, y - 1, m, n);
    }
};</pre><p></div><h2 class="tabtitle">Java</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">// Author: Huahua
// Time Complexity: O(mn)
// Running time: 13 ms
class Solution {
    public int numIslands(char[][] grid) {
        int m = grid.length;
        if (m == 0) return 0;
        int n = grid[0].length;
        
        int ans = 0;
        for (int y = 0; y &lt; m; ++y)
            for (int x = 0; x &lt; n; ++x)
                if (grid[y][x] == '1') {
                    ++ans;
                    dfs(grid, x, y, n, m);
                }
        
        return ans;
    }
    
    private void dfs(char[][] grid, int x, int y, int n, int m) {
        if (x &lt; 0 || y &lt; 0 || x &gt;= n || y &gt;= m || grid[y][x] == '0')
            return;
        grid[y][x] = '0';
        dfs(grid, x + 1, y, n, m);
        dfs(grid, x - 1, y, n, m);
        dfs(grid, x, y + 1, n, m);
        dfs(grid, x, y - 1, n, m);
    }
}</pre><p></div><h2 class="tabtitle">Python</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">"""
Author: Huahua
Time Complexity: O(mn)
Running Time: 102 ms
"""
class Solution(object):
    def numIslands(self, grid):
        """
        :type grid: List[List[str]]
        :rtype: int
        """
        m = len(grid)
        if m == 0: return 0
        n = len(grid[0])
        
        ans = 0
        for y in xrange(m):
            for x in xrange(n):
                if grid[y][x] == '1':
                    ans += 1
                    self.__dfs(grid, x, y, n, m)
        return ans
    
    def __dfs(self, grid, x, y, n, m):
        if x &lt; 0 or y &lt; 0 or x &gt;=n or y &gt;= m or grid[y][x] == '0':
            return
        grid[y][x] = '0'
        self.__dfs(grid, x + 1, y, n, m)
        self.__dfs(grid, x - 1, y, n, m)
        self.__dfs(grid, x, y + 1, n, m)
        self.__dfs(grid, x, y - 1, n, m)</pre><p></div></div></p>
<h1><strong>Related Problems</strong></h1>
<ul>
<li><a href="http://zxi.mytechroad.com/blog/graph/leetcode-695-max-area-of-island/">[解题报告] LeetCode 695. Max Area of Island</a></li>
<li><a href="http://zxi.mytechroad.com/blog/graph/leetcode-547-friend-circles/">[解题报告] LeetCode 547. Friend Circles</a></li>
<li><a href="https://zxi.mytechroad.com/blog/graph/leetcode-827-making-a-large-island/">花花酱 LeetCode 827. Making A Large Island</a></li>
<li><a href="https://zxi.mytechroad.com/blog/graph/leetcode-934-shortest-bridge/">花花酱 LeetCode 934. Shortest Bridge</a></li>
</ul>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/searching/leetcode-200-number-of-islands/">花花酱 LeetCode 200. Number of Islands</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/searching/leetcode-200-number-of-islands/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
