<?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>hard &#8211; Huahua&#8217;s Tech Road</title>
	<atom:link href="https://zxi.mytechroad.com/blog/tag/hard/feed/" rel="self" type="application/rss+xml" />
	<link>https://zxi.mytechroad.com/blog</link>
	<description></description>
	<lastBuildDate>Sat, 29 Apr 2023 19:33:18 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.7.4</generator>

<image>
	<url>https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/cropped-photo-32x32.jpg</url>
	<title>hard &#8211; Huahua&#8217;s Tech Road</title>
	<link>https://zxi.mytechroad.com/blog</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>花花酱 LeetCode 2642. Design Graph With Shortest Path Calculator</title>
		<link>https://zxi.mytechroad.com/blog/graph/leetcode-2642-design-graph-with-shortest-path-calculator/</link>
					<comments>https://zxi.mytechroad.com/blog/graph/leetcode-2642-design-graph-with-shortest-path-calculator/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sat, 29 Apr 2023 19:16:35 +0000</pubDate>
				<category><![CDATA[Graph]]></category>
		<category><![CDATA[dijkstra]]></category>
		<category><![CDATA[floyd-warshall]]></category>
		<category><![CDATA[graph]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[shortest path]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=10015</guid>

					<description><![CDATA[There is a&#160;directed weighted&#160;graph that consists of&#160;n&#160;nodes numbered from&#160;0&#160;to&#160;n - 1. The edges of the graph are initially represented by the given array&#160;edges&#160;where&#160;edges[i] = [fromi,&#8230;]]></description>
										<content:encoded><![CDATA[
<p>There is a&nbsp;<strong>directed weighted</strong>&nbsp;graph that consists of&nbsp;<code>n</code>&nbsp;nodes numbered from&nbsp;<code>0</code>&nbsp;to&nbsp;<code>n - 1</code>. The edges of the graph are initially represented by the given array&nbsp;<code>edges</code>&nbsp;where&nbsp;<code>edges[i] = [from<sub>i</sub>, to<sub>i</sub>, edgeCost<sub>i</sub>]</code>&nbsp;meaning that there is an edge from&nbsp;<code>from<sub>i</sub></code>&nbsp;to&nbsp;<code>to<sub>i</sub></code>&nbsp;with the cost&nbsp;<code>edgeCost<sub>i</sub></code>.</p>



<p>Implement the&nbsp;<code>Graph</code>&nbsp;class:</p>



<ul class="wp-block-list"><li><code>Graph(int n, int[][] edges)</code>&nbsp;initializes the object with&nbsp;<code>n</code>&nbsp;nodes and the given edges.</li><li><code>addEdge(int[] edge)</code>&nbsp;adds an edge to the list of edges where&nbsp;<code>edge = [from, to, edgeCost]</code>. It is guaranteed that there is no edge between the two nodes before adding this one.</li><li><code>int shortestPath(int node1, int node2)</code>&nbsp;returns the&nbsp;<strong>minimum</strong>&nbsp;cost of a path from&nbsp;<code>node1</code>&nbsp;to&nbsp;<code>node2</code>. If no path exists, return&nbsp;<code>-1</code>. The cost of a path is the sum of the costs of the edges in the path.</li></ul>



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



<figure class="wp-block-image"><img decoding="async" src="https://assets.leetcode.com/uploads/2023/01/11/graph3drawio-2.png" alt=""/></figure>



<pre class="wp-block-preformatted;crayon:false"><strong>Input</strong>
["Graph", "shortestPath", "shortestPath", "addEdge", "shortestPath"]
[[4, [[0, 2, 5], [0, 1, 2], [1, 2, 1], [3, 0, 3]]], [3, 2], [0, 3], [[1, 3, 4]], [0, 3]]
<strong>Output</strong>
[null, 6, -1, null, 6]
</pre>



<p><strong>Explanation</strong> </p>



<pre class="wp-block-preformatted;crayon:false">Graph g = new Graph(4, [[0, 2, 5], [0, 1, 2], [1, 2, 1], [3, 0, 3]]); g.shortestPath(3, 2); // return 6. The shortest path from 3 to 2 in the first diagram above is 3 -> 0 -> 1 -> 2 with a total cost of 3 + 2 + 1 = 6.
g.shortestPath(0, 3); // return -1. There is no path from 0 to 3. 
g.addEdge([1, 3, 4]); // We add an edge from node 1 to node 3, and we get the second diagram above. 
g.shortestPath(0, 3); // return 6. The shortest path from 0 to 3 now is 0 -> 1 -> 3 with a total cost of 2 + 4 = 6.</pre>



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



<ul class="wp-block-list"><li><code>1 &lt;= n &lt;= 100</code></li><li><code>0 &lt;= edges.length &lt;= n * (n - 1)</code></li><li><code>edges[i].length == edge.length == 3</code></li><li><code>0 &lt;= from<sub>i</sub>, to<sub>i</sub>, from, to, node1, node2 &lt;= n - 1</code></li><li><code>1 &lt;= edgeCost<sub>i</sub>, edgeCost &lt;= 10<sup>6</sup></code></li><li>There are no repeated edges and no self-loops in the graph at any point.</li><li>At most&nbsp;<code>100</code>&nbsp;calls will be made for&nbsp;<code>addEdge</code>.</li><li>At most&nbsp;<code>100</code>&nbsp;calls will be made for&nbsp;<code>shortestPath</code>.</li></ul>



<h2 class="wp-block-heading"><strong>Solution 1: Floyd-Washall</strong></h2>



<p>Time complexity:<br>Init O(n<sup>3</sup>)<br>addEdge O(n<sup>2</sup>)<br>shortestPath O(1)</p>



<p>Space complexity: O(1)</p>



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

<pre class="urvanov-syntax-highlighter-plain-tag">// Author: Huahua
class Graph {
public:
  Graph(int n, vector&lt;vector&lt;int&gt;&gt;&amp; edges):
  n_(n),
  d_(n, vector&lt;long&gt;(n, 1e18)) {
    for (int i = 0; i &lt; n; ++i)
      d_[i][i] = 0;
    for (const vector&lt;int&gt;&amp; e : edges)
      d_[e[0]][e[1]] = e[2];    
    for (int k = 0; k &lt; n; ++k)
      for (int i = 0; i &lt; n; ++i)
        for (int j = 0; j &lt; n; ++j)
          d_[i][j] = min(d_[i][j], d_[i][k] + d_[k][j]);
  }
  
  void addEdge(vector&lt;int&gt; edge) {    
    for (int i = 0; i &lt; n_; ++i)
      for (int j = 0; j &lt; n_; ++j)
        d_[i][j] = min(d_[i][j], d_[i][edge[0]] + edge[2] + d_[edge[1]][j]);
  }
  
  int shortestPath(int node1, int node2) {
    return d_[node1][node2] &gt;= 1e18 ? -1 : d_[node1][node2];
  }
private:
  int n_;
  vector&lt;vector&lt;long&gt;&gt; d_;
};</pre>
</div></div>



<h2 class="wp-block-heading"><strong>Solution 2: Dijkstra</strong></h2>



<p>Time complexity: <br>Init: O(|E|) ~ O(n<sup>2</sup>)<br>AddEdge: O(1)<br>ShortestPath: O(|V|*log(|E|)) ~ O(n*logn)</p>



<p>Space complexity: O(E|) ~ O(n<sup>2</sup>)</p>



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

<pre class="urvanov-syntax-highlighter-plain-tag">// Author: Huahua
class Graph {
public:
    Graph(int n, vector&lt;vector&lt;int&gt;&gt;&amp; edges): n_(n), g_(n) {
      for (const auto&amp; e : edges)
        g_[e[0]].emplace_back(e[1], e[2]);
    }
    
    void addEdge(vector&lt;int&gt; edge) {
      g_[edge[0]].emplace_back(edge[1], edge[2]);
    }
    
    int shortestPath(int node1, int node2) {
      vector&lt;int&gt; dist(n_, INT_MAX);
      dist[node1] = 0;
      priority_queue&lt;pair&lt;int, int&gt;, vector&lt;pair&lt;int, int&gt;&gt;, greater&lt;&gt;&gt; q;
      q.emplace(0, node1);
      while (!q.empty()) {
        const auto [d, u] = q.top(); q.pop();        
        if (u == node2) return d;
        for (const auto&amp; [v, c] : g_[u])
          if (dist[u] + c &lt; dist[v]) {
            dist[v] = dist[u] + c;
            q.emplace(dist[v], v);
          }
      }
      return -1;
    }
private:
  int n_;
  vector&lt;vector&lt;pair&lt;int, int&gt;&gt;&gt; g_;
};</pre>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/graph/leetcode-2642-design-graph-with-shortest-path-calculator/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2435. Paths in Matrix Whose Sum Is Divisible by K</title>
		<link>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-2435-paths-in-matrix-whose-sum-is-divisible-by-k/</link>
					<comments>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-2435-paths-in-matrix-whose-sum-is-divisible-by-k/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Tue, 11 Oct 2022 01:04:27 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[grid]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[paths]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=9854</guid>

					<description><![CDATA[You are given a&#160;0-indexed&#160;m x n&#160;integer matrix&#160;grid&#160;and an integer&#160;k. You are currently at position&#160;(0, 0)&#160;and you want to reach position&#160;(m - 1, n - 1)&#160;moving&#8230;]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="花花酱 LeetCode 2435. Paths in Matrix Whose Sum Is Divisible by K - 刷题找工作 EP403" width="500" height="281" src="https://www.youtube.com/embed/Gj8mvPsRkBI?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p>You are given a&nbsp;<strong>0-indexed</strong>&nbsp;<code>m x n</code>&nbsp;integer matrix&nbsp;<code>grid</code>&nbsp;and an integer&nbsp;<code>k</code>. You are currently at position&nbsp;<code>(0, 0)</code>&nbsp;and you want to reach position&nbsp;<code>(m - 1, n - 1)</code>&nbsp;moving only&nbsp;<strong>down</strong>&nbsp;or&nbsp;<strong>right</strong>.</p>



<p>Return<em>&nbsp;the number of paths where the sum of the elements on the path is divisible by&nbsp;</em><code>k</code>. Since the answer may be very large, return it&nbsp;<strong>modulo</strong>&nbsp;<code>10<sup>9</sup>&nbsp;+ 7</code>.</p>



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



<figure class="wp-block-image"><img decoding="async" src="https://assets.leetcode.com/uploads/2022/08/13/image-20220813183124-1.png" alt=""/></figure>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> grid = [[5,2,4],[3,0,5],[0,7,2]], k = 3
<strong>Output:</strong> 2
<strong>Explanation:</strong> There are two paths where the sum of the elements on the path is divisible by k.
The first path highlighted in red has a sum of 5 + 2 + 4 + 5 + 2 = 18 which is divisible by 3.
The second path highlighted in blue has a sum of 5 + 3 + 0 + 5 + 2 = 15 which is divisible by 3.
</pre>



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



<figure class="wp-block-image"><img decoding="async" src="https://assets.leetcode.com/uploads/2022/08/17/image-20220817112930-3.png" alt=""/></figure>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> grid = [[0,0]], k = 5
<strong>Output:</strong> 1
<strong>Explanation:</strong> The path highlighted in red has a sum of 0 + 0 = 0 which is divisible by 5.
</pre>



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



<figure class="wp-block-image"><img decoding="async" src="https://assets.leetcode.com/uploads/2022/08/12/image-20220812224605-3.png" alt=""/></figure>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> grid = [[7,3,4,9],[2,3,6,2],[2,3,7,0]], k = 1
<strong>Output:</strong> 10
<strong>Explanation:</strong> Every integer is divisible by 1 so the sum of the elements on every possible path is divisible by k.
</pre>



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



<ul class="wp-block-list"><li><code>m == grid.length</code></li><li><code>n == grid[i].length</code></li><li><code>1 &lt;= m, n &lt;= 5 * 10<sup>4</sup></code></li><li><code>1 &lt;= m * n &lt;= 5 * 10<sup>4</sup></code></li><li><code>0 &lt;= grid[i][j] &lt;= 100</code></li><li><code>1 &lt;= k &lt;= 50</code></li></ul>



<h2 class="wp-block-heading"><strong>Solution: DP</strong></h2>



<figure class="wp-block-image size-full"><a href="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/10/2435-ep403-1.png"><img fetchpriority="high" decoding="async" width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/10/2435-ep403-1.png" alt="" class="wp-image-9858" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/10/2435-ep403-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/10/2435-ep403-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/10/2435-ep403-1-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></a></figure>



<figure class="wp-block-image size-full"><a href="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/10/2435-ep403-2.png"><img decoding="async" width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/10/2435-ep403-2.png" alt="" class="wp-image-9859" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/10/2435-ep403-2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/10/2435-ep403-2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/10/2435-ep403-2-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></a></figure>



<figure class="wp-block-image size-full"><a href="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/10/2435-ep403-3.png"><img loading="lazy" decoding="async" width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/10/2435-ep403-3.png" alt="" class="wp-image-9861" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/10/2435-ep403-3.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/10/2435-ep403-3-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/10/2435-ep403-3-768x432.png 768w" sizes="auto, (max-width: 960px) 100vw, 960px" /></a></figure>



<p>Let dp[i][j][r] := # of paths from (0,0) to (i,j) with path sum % k == r.<br><br>init: dp[0][0][grid[0][0] % k] = 1</p>



<p>dp[i][j][(r + grid[i][j]) % k] = dp[i-1][j][r] + dp[i][j-1][r]</p>



<p>ans = dp[m-1][n-1][0]</p>



<p>Time complexity: O(m*n*k)<br>Space complexity: O(m*n*k) -&gt; O(n*k)</p>



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

<pre class="urvanov-syntax-highlighter-plain-tag">// Author: Huahua
class Solution {
public:
  int numberOfPaths(vector&lt;vector&lt;int&gt;&gt;&amp; grid, int k) {
    const int kMod = 1e9 + 7;
    const int m = grid.size();
    const int n = grid[0].size();
    vector&lt;vector&lt;vector&lt;int&gt;&gt;&gt; dp(m, vector&lt;vector&lt;int&gt;&gt;(n, vector&lt;int&gt;(k)));
    dp[0][0][grid[0][0] % k] = 1;
    for (int i = 0; i &lt; m; ++i)
      for (int j = 0; j &lt; n; ++j) {
        if (i == 0 &amp;&amp; j == 0) continue;
        for (int r = 0; r &lt; k; ++r)
          dp[i][j][(r + grid[i][j]) % k] = 
            ((j ? dp[i][j - 1][r] : 0) + (i ? dp[i - 1][j][r] : 0)) % kMod;          
      }
    return dp[m - 1][n - 1][0];
  }
};</pre>
</div></div>



<p>Related Problems:</p>



<ul class="wp-block-list"><li><a href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-62-unique-paths/" data-type="post" data-id="187">花花酱 LeetCode 62. Unique Paths</a></li></ul>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-2435-paths-in-matrix-whose-sum-is-divisible-by-k/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2416. Sum of Prefix Scores of Strings</title>
		<link>https://zxi.mytechroad.com/blog/tree/leetcode-2416-sum-of-prefix-scores-of-strings/</link>
					<comments>https://zxi.mytechroad.com/blog/tree/leetcode-2416-sum-of-prefix-scores-of-strings/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 18 Sep 2022 19:44:55 +0000</pubDate>
				<category><![CDATA[Tree]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[prefix]]></category>
		<category><![CDATA[tire]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=9832</guid>

					<description><![CDATA[You are given an array&#160;words&#160;of size&#160;n&#160;consisting of&#160;non-empty&#160;strings. We define the&#160;score&#160;of a string&#160;word&#160;as the&#160;number&#160;of strings&#160;words[i]&#160;such that&#160;word&#160;is a&#160;prefix&#160;of&#160;words[i]. For example, if&#160;words = ["a", "ab", "abc", "cab"], then&#8230;]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="花花酱 LeetCode 2416. Sum of Prefix Scores of Strings - 刷题找工作 EP402" width="500" height="281" src="https://www.youtube.com/embed/OJ0PMH6M2MQ?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p>You are given an array&nbsp;<code>words</code>&nbsp;of size&nbsp;<code>n</code>&nbsp;consisting of&nbsp;<strong>non-empty</strong>&nbsp;strings.</p>



<p>We define the&nbsp;<strong>score</strong>&nbsp;of a string&nbsp;<code>word</code>&nbsp;as the&nbsp;<strong>number</strong>&nbsp;of strings&nbsp;<code>words[i]</code>&nbsp;such that&nbsp;<code>word</code>&nbsp;is a&nbsp;<strong>prefix</strong>&nbsp;of&nbsp;<code>words[i]</code>.</p>



<ul class="wp-block-list"><li>For example, if&nbsp;<code>words = ["a", "ab", "abc", "cab"]</code>, then the score of&nbsp;<code>"ab"</code>&nbsp;is&nbsp;<code>2</code>, since&nbsp;<code>"ab"</code>&nbsp;is a prefix of both&nbsp;<code>"ab"</code>&nbsp;and&nbsp;<code>"abc"</code>.</li></ul>



<p>Return&nbsp;<em>an array&nbsp;</em><code>answer</code><em>&nbsp;of size&nbsp;</em><code>n</code><em>&nbsp;where&nbsp;</em><code>answer[i]</code><em>&nbsp;is the&nbsp;<strong>sum</strong>&nbsp;of scores of every&nbsp;<strong>non-empty</strong>&nbsp;prefix of&nbsp;</em><code>words[i]</code>.</p>



<p><strong>Note</strong>&nbsp;that a string is considered as a prefix of itself.</p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> words = ["abc","ab","bc","b"]
<strong>Output:</strong> [5,4,3,2]
<strong>Explanation:</strong> The answer for each string is the following:
- "abc" has 3 prefixes: "a", "ab", and "abc".
- There are 2 strings with the prefix "a", 2 strings with the prefix "ab", and 1 string with the prefix "abc".
The total is answer[0] = 2 + 2 + 1 = 5.
- "ab" has 2 prefixes: "a" and "ab".
- There are 2 strings with the prefix "a", and 2 strings with the prefix "ab".
The total is answer[1] = 2 + 2 = 4.
- "bc" has 2 prefixes: "b" and "bc".
- There are 2 strings with the prefix "b", and 1 string with the prefix "bc".
The total is answer[2] = 2 + 1 = 3.
- "b" has 1 prefix: "b".
- There are 2 strings with the prefix "b".
The total is answer[3] = 2.
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> words = ["abcd"]
<strong>Output:</strong> [4]
<strong>Explanation:</strong>
"abcd" has 4 prefixes: "a", "ab", "abc", and "abcd".
Each prefix has a score of one, so the total is answer[0] = 1 + 1 + 1 + 1 = 4.
</pre>



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



<ul class="wp-block-list"><li><code>1 &lt;= words.length &lt;= 1000</code></li><li><code>1 &lt;= words[i].length &lt;= 1000</code></li><li><code>words[i]</code>&nbsp;consists of lowercase English letters.</li></ul>



<h2 class="wp-block-heading"><strong>Solution: Trie</strong></h2>



<figure class="wp-block-image size-full"><a href="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/09/lc-2416-ep402-s1.png"><img loading="lazy" decoding="async" width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/09/lc-2416-ep402-s1.png" alt="" class="wp-image-9836" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/09/lc-2416-ep402-s1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/09/lc-2416-ep402-s1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/09/lc-2416-ep402-s1-768x432.png 768w" sizes="auto, (max-width: 960px) 100vw, 960px" /></a></figure>



<figure class="wp-block-image size-full"><a href="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/09/lc-2416-ep402-s2.png"><img loading="lazy" decoding="async" width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/09/lc-2416-ep402-s2.png" alt="" class="wp-image-9837" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/09/lc-2416-ep402-s2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/09/lc-2416-ep402-s2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/09/lc-2416-ep402-s2-768x432.png 768w" sizes="auto, (max-width: 960px) 100vw, 960px" /></a></figure>



<figure class="wp-block-image size-full"><a href="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/09/lc-2416-ep402-s3.png"><img loading="lazy" decoding="async" width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/09/lc-2416-ep402-s3.png" alt="" class="wp-image-9839" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/09/lc-2416-ep402-s3.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/09/lc-2416-ep402-s3-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/09/lc-2416-ep402-s3-768x432.png 768w" sizes="auto, (max-width: 960px) 100vw, 960px" /></a></figure>



<p>Insert all the words into a tire whose node val is the number of substrings that have the current prefix.</p>



<p>During query time, sum up the values along the prefix path.</p>



<p>Time complexity: O(sum(len(word))<br>Space complexity: O(sum(len(word))</p>



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

<pre class="urvanov-syntax-highlighter-plain-tag">// Author: Huahua
struct Trie {
  Trie* ch[26] = {};
  int cnt = 0;
  void insert(string_view s) {
    Trie* cur = this;
    for (char c : s) {
      if (!cur-&gt;ch[c - 'a']) 
        cur-&gt;ch[c - 'a'] = new Trie();
      cur = cur-&gt;ch[c - 'a'];
      ++cur-&gt;cnt;
    }
  }
  int query(string_view s) {
    Trie* cur = this;
    int ans = 0;
    for (char c : s) {
      cur = cur-&gt;ch[c - 'a'];
      ans += cur-&gt;cnt;
    }
    return ans;
  }
};
class Solution {
public:
  vector&lt;int&gt; sumPrefixScores(vector&lt;string&gt;&amp; words) {
    Trie* root = new Trie();
    for (const string&amp; w : words)
      root-&gt;insert(w);
    vector&lt;int&gt; ans;
    for (const string&amp; w : words)
      ans.push_back(root-&gt;query(w));
    return ans;
  }
};</pre>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/tree/leetcode-2416-sum-of-prefix-scores-of-strings/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2407. Longest Increasing Subsequence II</title>
		<link>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-2407-longest-increasing-subsequence-ii/</link>
					<comments>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-2407-longest-increasing-subsequence-ii/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Mon, 12 Sep 2022 05:16:09 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[range query]]></category>
		<category><![CDATA[segment tree]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=9817</guid>

					<description><![CDATA[You are given an integer array&#160;nums&#160;and an integer&#160;k. Find the longest subsequence of&#160;nums&#160;that meets the following requirements: The subsequence is&#160;strictly increasing&#160;and The difference between adjacent&#8230;]]></description>
										<content:encoded><![CDATA[
<p>You are given an integer array&nbsp;<code>nums</code>&nbsp;and an integer&nbsp;<code>k</code>.</p>



<p>Find the longest subsequence of&nbsp;<code>nums</code>&nbsp;that meets the following requirements:</p>



<ul class="wp-block-list"><li>The subsequence is&nbsp;<strong>strictly increasing</strong>&nbsp;and</li><li>The difference between adjacent elements in the subsequence is&nbsp;<strong>at most</strong>&nbsp;<code>k</code>.</li></ul>



<p>Return<em>&nbsp;the length of the&nbsp;<strong>longest</strong>&nbsp;<strong>subsequence</strong>&nbsp;that meets the requirements.</em></p>



<p>A&nbsp;<strong>subsequence</strong>&nbsp;is an array that can be derived from another array by deleting some or no elements without changing the order of the remaining elements.</p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [4,2,1,4,3,4,5,8,15], k = 3
<strong>Output:</strong> 5
<strong>Explanation:</strong>
The longest subsequence that meets the requirements is [1,3,4,5,8].
The subsequence has a length of 5, so we return 5.
Note that the subsequence [1,3,4,5,8,15] does not meet the requirements because 15 - 8 = 7 is larger than 3.
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [7,4,5,1,8,12,4,7], k = 5
<strong>Output:</strong> 4
<strong>Explanation:</strong>
The longest subsequence that meets the requirements is [4,5,8,12].
The subsequence has a length of 4, so we return 4.
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [1,5], k = 1
<strong>Output:</strong> 1
<strong>Explanation:</strong>
The longest subsequence that meets the requirements is [1].
The subsequence has a length of 1, so we return 1.
</pre>



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



<ul class="wp-block-list"><li><code>1 &lt;= nums.length &lt;= 10<sup>5</sup></code></li><li><code>1 &lt;= nums[i], k &lt;= 10<sup>5</sup></code></li></ul>



<h2 class="wp-block-heading"><strong>Solution: DP + Segment Tree | Max range query</strong></h2>



<p>Let dp[i] := length of LIS end with number i.<br>dp[i] = 1 + max(dp[i-k:i])</p>



<p>Naive dp takes O(n*k) time which will cause TLE.</p>



<p>We can use segment tree to speed up the max range query to log(m), where m is the max value of the array.</p>



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



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

<pre class="urvanov-syntax-highlighter-plain-tag">// Author: Huahua
class Solution {
public:
  int lengthOfLIS(vector&lt;int&gt;&amp; nums, int k) {
    const int n = *max_element(begin(nums), end(nums));
    vector&lt;int&gt; dp(2 * (n + 1));
    auto query = [&amp;](int l, int r) -&gt; int {
      int ans = 0;
      for (l += n, r += n; l &lt; r; l &gt;&gt;= 1, r &gt;&gt;= 1) {
        if (l &amp; 1) ans = max(ans, dp[l++]);      
        if (r &amp; 1) ans = max(ans, dp[--r]);
      }
      return ans;
    };
    auto update = [&amp;](int i, int val) -&gt; void {
      dp[i += n] = val;
      while (i &gt; 1) {
        i &gt;&gt;= 1;
        dp[i] = max(dp[i * 2], dp[i * 2 + 1]);
      }
    };        
    int ans = 0;
    for (int x : nums) {
      int cur = 1 + query(max(1, x - k), x);
      update(x, cur);
      ans = max(ans, cur);
    }
    return ans;
  }
};</pre>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-2407-longest-increasing-subsequence-ii/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2267. Check if There Is a Valid Parentheses String Path</title>
		<link>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-2267-check-if-there-is-a-valid-parentheses-string-path/</link>
					<comments>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-2267-check-if-there-is-a-valid-parentheses-string-path/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Tue, 10 May 2022 15:20:01 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[parentheses]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=9734</guid>

					<description><![CDATA[A parentheses string is a&#160;non-empty&#160;string consisting only of&#160;'('&#160;and&#160;')'. It is&#160;valid&#160;if&#160;any&#160;of the following conditions is&#160;true: It is&#160;(). It can be written as&#160;AB&#160;(A&#160;concatenated with&#160;B), where&#160;A&#160;and&#160;B&#160;are valid parentheses&#8230;]]></description>
										<content:encoded><![CDATA[
<p>A parentheses string is a&nbsp;<strong>non-empty</strong>&nbsp;string consisting only of&nbsp;<code>'('</code>&nbsp;and&nbsp;<code>')'</code>. It is&nbsp;<strong>valid</strong>&nbsp;if&nbsp;<strong>any</strong>&nbsp;of the following conditions is&nbsp;<strong>true</strong>:</p>



<ul class="wp-block-list"><li>It is&nbsp;<code>()</code>.</li><li>It can be written as&nbsp;<code>AB</code>&nbsp;(<code>A</code>&nbsp;concatenated with&nbsp;<code>B</code>), where&nbsp;<code>A</code>&nbsp;and&nbsp;<code>B</code>&nbsp;are valid parentheses strings.</li><li>It can be written as&nbsp;<code>(A)</code>, where&nbsp;<code>A</code>&nbsp;is a valid parentheses string.</li></ul>



<p>You are given an&nbsp;<code>m x n</code>&nbsp;matrix of parentheses&nbsp;<code>grid</code>. A&nbsp;<strong>valid parentheses string path</strong>&nbsp;in the grid is a path satisfying&nbsp;<strong>all</strong>&nbsp;of the following conditions:</p>



<ul class="wp-block-list"><li>The path starts from the upper left cell&nbsp;<code>(0, 0)</code>.</li><li>The path ends at the bottom-right cell&nbsp;<code>(m - 1, n - 1)</code>.</li><li>The path only ever moves&nbsp;<strong>down</strong>&nbsp;or&nbsp;<strong>right</strong>.</li><li>The resulting parentheses string formed by the path is&nbsp;<strong>valid</strong>.</li></ul>



<p>Return&nbsp;<code>true</code>&nbsp;<em>if there exists a&nbsp;<strong>valid parentheses string path</strong>&nbsp;in the grid.</em>&nbsp;Otherwise, return&nbsp;<code>false</code>.</p>



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



<figure class="wp-block-image"><img decoding="async" src="https://assets.leetcode.com/uploads/2022/03/15/example1drawio.png" alt=""/></figure>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> grid = [["(","(","("],[")","(",")"],["(","(",")"],["(","(",")"]]
<strong>Output:</strong> true
<strong>Explanation:</strong> The above diagram shows two possible paths that form valid parentheses strings.
The first path shown results in the valid parentheses string "()(())".
The second path shown results in the valid parentheses string "((()))".
Note that there may be other valid parentheses string paths.
</pre>



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



<figure class="wp-block-image"><img decoding="async" src="https://assets.leetcode.com/uploads/2022/03/15/example2drawio.png" alt=""/></figure>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> grid = [[")",")"],["(","("]]
<strong>Output:</strong> false
<strong>Explanation:</strong> The two possible paths form the parentheses strings "))(" and ")((". Since neither of them are valid parentheses strings, we return false.
</pre>



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



<ul class="wp-block-list"><li><code>m == grid.length</code></li><li><code>n == grid[i].length</code></li><li><code>1 &lt;= m, n &lt;= 100</code></li><li><code>grid[i][j]</code>&nbsp;is either&nbsp;<code>'('</code>&nbsp;or&nbsp;<code>')'</code>.</li></ul>



<h2 class="wp-block-heading"><strong>Solution: DP</strong></h2>



<p>Let dp(i, j, b) denote whether there is a path from (i,j) to (m-1, n-1) given b open parentheses.<br>if we are at (m &#8211; 1, n &#8211; 1) and b == 0 then we found a valid path.<br>dp(i, j, b) = dp(i + 1, j, b&#8217;) or dp(i, j + 1, b&#8217;) where b&#8217; = b + 1 if  grid[i][j] == &#8216;(&#8216; else -1</p>



<p>Time complexity: O(m*n*(m + n))<br><meta charset="utf-8">Space complexity: O(m*n*(m + n))</p>



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

<pre class="urvanov-syntax-highlighter-plain-tag"># Author: Huahua
class Solution:
  def hasValidPath(self, grid: List[List[str]]) -&gt; bool:
    m, n = len(grid), len(grid[0])    
    
    @cache
    def dp(i: int, j: int, b: int) -&gt; bool:
      if b &lt; 0 or i == m or j == n: return False
      b += 1 if grid[i][j] == '(' else -1      
      if i == m - 1 and j == n - 1 and b == 0: return True      
      return dp(i + 1, j, b) or dp(i, j + 1, b)
    
    return dp(0, 0, 0)</pre>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-2267-check-if-there-is-a-valid-parentheses-string-path/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2251. Number of Flowers in Full Bloom</title>
		<link>https://zxi.mytechroad.com/blog/tree/leetcode-2251-number-of-flowers-in-full-bloom/</link>
					<comments>https://zxi.mytechroad.com/blog/tree/leetcode-2251-number-of-flowers-in-full-bloom/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Thu, 28 Apr 2022 05:10:51 +0000</pubDate>
				<category><![CDATA[Tree]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[sweep line]]></category>
		<category><![CDATA[treemap]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=9692</guid>

					<description><![CDATA[You are given a&#160;0-indexed&#160;2D integer array&#160;flowers, where&#160;flowers[i] = [starti, endi]&#160;means the&#160;ith&#160;flower will be in&#160;full bloom&#160;from&#160;starti&#160;to&#160;endi&#160;(inclusive). You are also given a&#160;0-indexed&#160;integer array&#160;persons&#160;of size&#160;n, where&#160;persons[i]&#160;is the time&#8230;]]></description>
										<content:encoded><![CDATA[
<p>You are given a&nbsp;<strong>0-indexed</strong>&nbsp;2D integer array&nbsp;<code>flowers</code>, where&nbsp;<code>flowers[i] = [start<sub>i</sub>, end<sub>i</sub>]</code>&nbsp;means the&nbsp;<code>i<sup>th</sup></code>&nbsp;flower will be in&nbsp;<strong>full bloom</strong>&nbsp;from&nbsp;<code>start<sub>i</sub></code>&nbsp;to&nbsp;<code>end<sub>i</sub></code>&nbsp;(<strong>inclusive</strong>). You are also given a&nbsp;<strong>0-indexed</strong>&nbsp;integer array&nbsp;<code>persons</code>&nbsp;of size&nbsp;<code>n</code>, where&nbsp;<code>persons[i]</code>&nbsp;is the time that the&nbsp;<code>i<sup>th</sup></code>&nbsp;person will arrive to see the flowers.</p>



<p>Return&nbsp;<em>an integer array&nbsp;</em><code>answer</code><em>&nbsp;of size&nbsp;</em><code>n</code><em>, where&nbsp;</em><code>answer[i]</code><em>&nbsp;is the&nbsp;<strong>number</strong>&nbsp;of flowers that are in full bloom when the&nbsp;</em><code>i<sup>th</sup></code><em>&nbsp;person arrives.</em></p>



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



<figure class="wp-block-image"><img decoding="async" src="https://assets.leetcode.com/uploads/2022/03/02/ex1new.jpg" alt=""/></figure>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> flowers = [[1,6],[3,7],[9,12],[4,13]], persons = [2,3,7,11]
<strong>Output:</strong> [1,2,2,2]
<strong>Explanation: </strong>The figure above shows the times when the flowers are in full bloom and when the people arrive.
For each person, we return the number of flowers in full bloom during their arrival.
</pre>



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



<figure class="wp-block-image"><img decoding="async" src="https://assets.leetcode.com/uploads/2022/03/02/ex2new.jpg" alt=""/></figure>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> flowers = [[1,10],[3,3]], persons = [3,3,2]
<strong>Output:</strong> [2,2,1]
<strong>Explanation:</strong> The figure above shows the times when the flowers are in full bloom and when the people arrive.
For each person, we return the number of flowers in full bloom during their arrival.
</pre>



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



<ul class="wp-block-list"><li><code>1 &lt;= flowers.length &lt;= 5 * 10<sup>4</sup></code></li><li><code>flowers[i].length == 2</code></li><li><code>1 &lt;= start<sub>i</sub>&nbsp;&lt;= end<sub>i</sub>&nbsp;&lt;= 10<sup>9</sup></code></li><li><code>1 &lt;= persons.length &lt;= 5 * 10<sup>4</sup></code></li><li><code>1 &lt;= persons[i] &lt;= 10<sup>9</sup></code></li></ul>



<h2 class="wp-block-heading"><strong>Solution: Prefix Sum + Binary Search</strong></h2>



<p>Use a treemap to store the counts (ordered by time t), when a flower begins to bloom at start, we increase m[start], when it dies at end, we decrease m[end+1]. prefix_sum[t] indicates the # of blooming flowers at time t.</p>



<p>For each people, use binary search to find the latest # of flowers before his arrival.</p>



<p>Time complexity: O(nlogn + mlogn)<br>Space complexity: O(n)</p>



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

<pre class="urvanov-syntax-highlighter-plain-tag">// Author: Huahua
class Solution {
public:
  vector&lt;int&gt; fullBloomFlowers(vector&lt;vector&lt;int&gt;&gt;&amp; flowers, vector&lt;int&gt;&amp; persons) {
    map&lt;int, int&gt; m{{0, 0}};
    for (const auto&amp; f : flowers)
      ++m[f[0]], --m[f[1] + 1];    
    int sum = 0;
    for (auto&amp; [t, c] : m)
      c = sum += c;    
    vector&lt;int&gt; ans;    
    for (int t : persons)      
      ans.push_back(prev(m.upper_bound(t))-&gt;second);
    return ans;
  }
};</pre>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/tree/leetcode-2251-number-of-flowers-in-full-bloom/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2242. Maximum Score of a Node Sequence</title>
		<link>https://zxi.mytechroad.com/blog/greedy/leetcode-2242-maximum-score-of-a-node-sequence/</link>
					<comments>https://zxi.mytechroad.com/blog/greedy/leetcode-2242-maximum-score-of-a-node-sequence/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 17 Apr 2022 06:16:40 +0000</pubDate>
				<category><![CDATA[Greedy]]></category>
		<category><![CDATA[graph]]></category>
		<category><![CDATA[greedy]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[heap]]></category>
		<category><![CDATA[set]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=9662</guid>

					<description><![CDATA[There is an&#160;undirected&#160;graph with&#160;n&#160;nodes, numbered from&#160;0&#160;to&#160;n - 1. You are given a&#160;0-indexed&#160;integer array&#160;scores&#160;of length&#160;n&#160;where&#160;scores[i]&#160;denotes the score of node&#160;i. You are also given a 2D integer&#8230;]]></description>
										<content:encoded><![CDATA[
<p>There is an&nbsp;<strong>undirected</strong>&nbsp;graph with&nbsp;<code>n</code>&nbsp;nodes, numbered from&nbsp;<code>0</code>&nbsp;to&nbsp;<code>n - 1</code>.</p>



<p>You are given a&nbsp;<strong>0-indexed</strong>&nbsp;integer array&nbsp;<code>scores</code>&nbsp;of length&nbsp;<code>n</code>&nbsp;where&nbsp;<code>scores[i]</code>&nbsp;denotes the score of node&nbsp;<code>i</code>. You are also given a 2D integer array&nbsp;<code>edges</code>&nbsp;where&nbsp;<code>edges[i] = [a<sub>i</sub>, b<sub>i</sub>]</code>&nbsp;denotes that there exists an&nbsp;<strong>undirected</strong>&nbsp;edge connecting nodes&nbsp;<code>a<sub>i</sub></code>&nbsp;and&nbsp;<code>b<sub>i</sub></code>.</p>



<p>A node sequence is&nbsp;<strong>valid</strong>&nbsp;if it meets the following conditions:</p>



<ul class="wp-block-list"><li>There is an edge connecting every pair of&nbsp;<strong>adjacent</strong>&nbsp;nodes in the sequence.</li><li>No node appears more than once in the sequence.</li></ul>



<p>The score of a node sequence is defined as the&nbsp;<strong>sum</strong>&nbsp;of the scores of the nodes in the sequence.</p>



<p>Return&nbsp;<em>the&nbsp;<strong>maximum score</strong>&nbsp;of a valid node sequence with a length of&nbsp;</em><code>4</code><em>.&nbsp;</em>If no such sequence exists, return<em>&nbsp;</em><code>-1</code>.</p>



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



<figure class="wp-block-image"><img decoding="async" src="https://assets.leetcode.com/uploads/2022/04/15/ex1new3.png" alt=""/></figure>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> scores = [5,2,9,8,4], edges = [[0,1],[1,2],[2,3],[0,2],[1,3],[2,4]]
<strong>Output:</strong> 24
<strong>Explanation:</strong> The figure above shows the graph and the chosen node sequence [0,1,2,3].
The score of the node sequence is 5 + 2 + 9 + 8 = 24.
It can be shown that no other node sequence has a score of more than 24.
Note that the sequences [3,1,2,0] and [1,0,2,3] are also valid and have a score of 24.
The sequence [0,3,2,4] is not valid since no edge connects nodes 0 and 3.
</pre>



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



<figure class="wp-block-image"><img decoding="async" src="https://assets.leetcode.com/uploads/2022/03/17/ex2.png" alt=""/></figure>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> scores = [9,20,6,4,11,12], edges = [[0,3],[5,3],[2,4],[1,3]]
<strong>Output:</strong> -1
<strong>Explanation:</strong> The figure above shows the graph.
There are no valid node sequences of length 4, so we return -1.
</pre>



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



<ul class="wp-block-list"><li><code>n == scores.length</code></li><li><code>4 &lt;= n &lt;= 5 * 10<sup>4</sup></code></li><li><code>1 &lt;= scores[i] &lt;= 10<sup>8</sup></code></li><li><code>0 &lt;= edges.length &lt;= 5 * 10<sup>4</sup></code></li><li><code>edges[i].length == 2</code></li><li><code>0 &lt;= a<sub>i</sub>, b<sub>i</sub>&nbsp;&lt;= n - 1</code></li><li><code>a<sub>i</sub>&nbsp;!= b<sub>i</sub></code></li><li>There are no duplicate edges.</li></ul>



<h2 class="wp-block-heading"><strong>Solution: Greedy / Top3 neighbors</strong></h2>



<figure class="wp-block-image size-full"><a href="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/04/lc2242-ep396-1.png"><img loading="lazy" decoding="async" width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/04/lc2242-ep396-1.png" alt="" class="wp-image-9667" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/04/lc2242-ep396-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/04/lc2242-ep396-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/04/lc2242-ep396-1-768x432.png 768w" sizes="auto, (max-width: 960px) 100vw, 960px" /></a></figure>



<figure class="wp-block-image size-full"><a href="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/04/lc2242-ep396-2.png"><img loading="lazy" decoding="async" width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/04/lc2242-ep396-2.png" alt="" class="wp-image-9668" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/04/lc2242-ep396-2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/04/lc2242-ep396-2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/04/lc2242-ep396-2-768x432.png 768w" sizes="auto, (max-width: 960px) 100vw, 960px" /></a></figure>



<figure class="wp-block-image size-full"><a href="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/04/lc2242-ep396-3.png"><img loading="lazy" decoding="async" width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/04/lc2242-ep396-3.png" alt="" class="wp-image-9669" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/04/lc2242-ep396-3.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/04/lc2242-ep396-3-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/04/lc2242-ep396-3-768x432.png 768w" sizes="auto, (max-width: 960px) 100vw, 960px" /></a></figure>



<figure class="wp-block-image size-full"><a href="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/04/lc2242-ep396-4.png"><img loading="lazy" decoding="async" width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/04/lc2242-ep396-4.png" alt="" class="wp-image-9671" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/04/lc2242-ep396-4.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/04/lc2242-ep396-4-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/04/lc2242-ep396-4-768x432.png 768w" sizes="auto, (max-width: 960px) 100vw, 960px" /></a></figure>



<figure class="wp-block-image size-full"><a href="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/04/lc2242-ep396-5.png"><img loading="lazy" decoding="async" width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/04/lc2242-ep396-5.png" alt="" class="wp-image-9673" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/04/lc2242-ep396-5.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/04/lc2242-ep396-5-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/04/lc2242-ep396-5-768x432.png 768w" sizes="auto, (max-width: 960px) 100vw, 960px" /></a></figure>



<p>Since |E| is already 5*10<sup>4</sup>, we can&#8217;t enumerate all possible sequences. We must do in O(|E|) or O(|E|log|E|).</p>



<p>Enumerate all the edges, we have a pair of node a, b. To get the optimal answer, we just need to find the largest neighbor of a and b, which we call c, d respectively. Just need to make sure a, b, c, d are unique. i.e. c != d, c != b and d != a. Since the a&#8217;s largest neighbor can be either b or d. We can&#8217;t just store the largest neighbor, but top 3 instead for each node to avoid duplications.</p>



<p>Time complexity: O(|E|*9)<br>Space complexity: O(|V|*3)</p>



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

<pre class="urvanov-syntax-highlighter-plain-tag">// Author: Huahua
class Solution {
public:
  int maximumScore(vector&lt;int&gt;&amp; scores, vector&lt;vector&lt;int&gt;&gt;&amp; edges) {
    const int n = scores.size();
    vector&lt;set&lt;pair&lt;int, int&gt;&gt;&gt; top3(n);
    for (const auto&amp; e : edges) {      
      top3[e[0]].emplace(scores[e[1]], e[1]);
      top3[e[1]].emplace(scores[e[0]], e[0]);
      if (top3[e[0]].size() &gt; 3) top3[e[0]].erase(begin(top3[e[0]]));
      if (top3[e[1]].size() &gt; 3) top3[e[1]].erase(begin(top3[e[1]]));
    }
    int ans = -1;
    for (const auto&amp; e : edges) {
      const int a = e[0], b = e[1], sa = scores[a], sb = scores[b];
      for (const auto&amp; [sc, c] : top3[a])
        for (const auto&amp; [sd, d] : top3[b])          
          if (sa + sb + sc + sd &gt; ans &amp;&amp; c != b &amp;&amp; c != d &amp;&amp; d != a)
            ans = sa + sb + sc + sd;
    }
    return ans;
  }
};</pre>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/greedy/leetcode-2242-maximum-score-of-a-node-sequence/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2227. Encrypt and Decrypt Strings</title>
		<link>https://zxi.mytechroad.com/blog/data-structure/leetcode-2227-encrypt-and-decrypt-strings/</link>
					<comments>https://zxi.mytechroad.com/blog/data-structure/leetcode-2227-encrypt-and-decrypt-strings/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 03 Apr 2022 09:39:44 +0000</pubDate>
				<category><![CDATA[Data Structure]]></category>
		<category><![CDATA[data structure]]></category>
		<category><![CDATA[dictionary]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[string]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=9626</guid>

					<description><![CDATA[You are given a character array&#160;keys&#160;containing&#160;unique&#160;characters and a string array&#160;values&#160;containing strings of length 2. You are also given another string array&#160;dictionary&#160;that contains all permitted original&#8230;]]></description>
										<content:encoded><![CDATA[
<p>You are given a character array&nbsp;<code>keys</code>&nbsp;containing&nbsp;<strong>unique</strong>&nbsp;characters and a string array&nbsp;<code>values</code>&nbsp;containing strings of length 2. You are also given another string array&nbsp;<code>dictionary</code>&nbsp;that contains all permitted original strings after decryption. You should implement a data structure that can encrypt or decrypt a&nbsp;<strong>0-indexed</strong>&nbsp;string.</p>



<p>A string is&nbsp;<strong>encrypted</strong>&nbsp;with the following process:</p>



<ol class="wp-block-list"><li>For each character&nbsp;<code>c</code>&nbsp;in the string, we find the index&nbsp;<code>i</code>&nbsp;satisfying&nbsp;<code>keys[i] == c</code>&nbsp;in&nbsp;<code>keys</code>.</li><li>Replace&nbsp;<code>c</code>&nbsp;with&nbsp;<code>values[i]</code>&nbsp;in the string.</li></ol>



<p>A string is&nbsp;<strong>decrypted</strong>&nbsp;with the following process:</p>



<ol class="wp-block-list"><li>For each substring&nbsp;<code>s</code>&nbsp;of length 2 occurring at an even index in the string, we find an&nbsp;<code>i</code>&nbsp;such that&nbsp;<code>values[i] == s</code>. If there are multiple valid&nbsp;<code>i</code>, we choose&nbsp;<strong>any</strong>&nbsp;one of them. This means a string could have multiple possible strings it can decrypt to.</li><li>Replace&nbsp;<code>s</code>&nbsp;with&nbsp;<code>keys[i]</code>&nbsp;in the string.</li></ol>



<p>Implement the&nbsp;<code>Encrypter</code>&nbsp;class:</p>



<ul class="wp-block-list"><li><code>Encrypter(char[] keys, String[] values, String[] dictionary)</code>&nbsp;Initializes the&nbsp;<code>Encrypter</code>&nbsp;class with&nbsp;<code>keys, values</code>, and&nbsp;<code>dictionary</code>.</li><li><code>String encrypt(String word1)</code>&nbsp;Encrypts&nbsp;<code>word1</code>&nbsp;with the encryption process described above and returns the encrypted string.</li><li><code>int decrypt(String word2)</code>&nbsp;Returns the number of possible strings&nbsp;<code>word2</code>&nbsp;could decrypt to that also appear in&nbsp;<code>dictionary</code>.</li></ul>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input</strong>
["Encrypter", "encrypt", "decrypt"]
[[['a', 'b', 'c', 'd'], ["ei", "zf", "ei", "am"], ["abcd", "acbd", "adbc", "badc", "dacb", "cadb", "cbda", "abad"]], ["abcd"], ["eizfeiam"]]
<strong>Output</strong>
</pre>


<p>[null, &#8220;eizfeiam&#8221;, 2]</p>



<p><strong>Explanation</strong> Encrypter encrypter = new Encrypter([[&#8216;a&#8217;, &#8216;b&#8217;, &#8216;c&#8217;, &#8216;d&#8217;], [&#8220;ei&#8221;, &#8220;zf&#8221;, &#8220;ei&#8221;, &#8220;am&#8221;], [&#8220;abcd&#8221;, &#8220;acbd&#8221;, &#8220;adbc&#8221;, &#8220;badc&#8221;, &#8220;dacb&#8221;, &#8220;cadb&#8221;, &#8220;cbda&#8221;, &#8220;abad&#8221;]); encrypter.encrypt(&#8220;abcd&#8221;); // return &#8220;eizfeiam&#8221;. &nbsp; // &#8216;a&#8217; maps to &#8220;ei&#8221;, &#8216;b&#8217; maps to &#8220;zf&#8221;, &#8216;c&#8217; maps to &#8220;ei&#8221;, and &#8216;d&#8217; maps to &#8220;am&#8221;. encrypter.decrypt(&#8220;eizfeiam&#8221;); // return 2. // &#8220;ei&#8221; can map to &#8216;a&#8217; or &#8216;c&#8217;, &#8220;zf&#8221; maps to &#8216;b&#8217;, and &#8220;am&#8221; maps to &#8216;d&#8217;. // Thus, the possible strings after decryption are &#8220;abad&#8221;, &#8220;cbad&#8221;, &#8220;abcd&#8221;, and &#8220;cbcd&#8221;. // 2 of those strings, &#8220;abad&#8221; and &#8220;abcd&#8221;, appear in dictionary, so the answer is 2.</p>



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



<ul class="wp-block-list"><li><code>1 &lt;= keys.length == values.length &lt;= 26</code></li><li><code>values[i].length == 2</code></li><li><code>1 &lt;= dictionary.length &lt;= 100</code></li><li><code>1 &lt;= dictionary[i].length &lt;= 100</code></li><li>All&nbsp;<code>keys[i]</code>&nbsp;and&nbsp;<code>dictionary[i]</code>&nbsp;are&nbsp;<strong>unique</strong>.</li><li><code>1 &lt;= word1.length &lt;= 2000</code></li><li><code>1 &lt;= word2.length &lt;= 200</code></li><li>All&nbsp;<code>word1[i]</code>&nbsp;appear in&nbsp;<code>keys</code>.</li><li><code>word2.length</code>&nbsp;is even.</li><li><code>keys</code>,&nbsp;<code>values[i]</code>,&nbsp;<code>dictionary[i]</code>,&nbsp;<code>word1</code>, and&nbsp;<code>word2</code>&nbsp;only contain lowercase English letters.</li><li>At most&nbsp;<code>200</code>&nbsp;calls will be made to&nbsp;<code>encrypt</code>&nbsp;and&nbsp;<code>decrypt</code>&nbsp;<strong>in total</strong>.</li></ul>



<h2 class="wp-block-heading"><strong>Solution: </strong></h2>



<p>For encryption, follow the instruction. Time complexity: O(len(word)) = O(2000)<br>For decryption, try all words in the dictionary and encrypt them and compare the encrypted string with the word to decrypt. Time <meta charset="utf-8">complexity: O(sum(len(word_in_dict))) = O(100*100)</p>



<p>Worst case: 200 calls to decryption, T = 200 * O(100 * 100) = O(2*10<sup>6</sup>)</p>



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

<pre class="urvanov-syntax-highlighter-plain-tag">// Author: Huahua
class Encrypter {
public:
  Encrypter(vector&lt;char&gt;&amp; keys, 
            vector&lt;string&gt;&amp; values, 
            vector&lt;string&gt;&amp; dictionary):
        vals(26),
        dict(dictionary) {
    for (size_t i = 0; i &lt; keys.size(); ++i)
      vals[keys[i] - 'a'] = values[i];  
  }

  string encrypt(string word1) {
    string ans;
    for (char c : word1)
      ans += vals[c - 'a'];
    return ans;
  }

  int decrypt(string word2) {
    return count_if(begin(dict), end(dict), [&amp;](const string&amp; w){ 
      return encrypt(w) == word2;
    });    
  }
private:
  vector&lt;string&gt; vals;
  vector&lt;string&gt; dict;
};</pre>
</div></div>



<h2 class="wp-block-heading"><strong>Optimization</strong></h2>



<p>Pre-compute answer for all the words in dictionary.</p>



<p>decrypt: Time complexity: O(1)</p>



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

<pre class="urvanov-syntax-highlighter-plain-tag">// Author: Huahua
class Encrypter {
public:
  Encrypter(vector&lt;char&gt;&amp; keys, 
            vector&lt;string&gt;&amp; values, 
            vector&lt;string&gt;&amp; dictionary):
        vals(26) {
    for (size_t i = 0; i &lt; keys.size(); ++i)
      vals[keys[i] - 'a'] = values[i];  
    for (const string&amp; w : dictionary)
      ++counts[encrypt(w)];
  }

  string encrypt(string word1) {
    string ans;
    for (char c : word1)
      ans += vals[c - 'a'];
    return ans;
  }

  int decrypt(string word2) {
    auto it = counts.find(word2);
    return it == counts.end() ? 0 : it-&gt;second;
  }
private:
  vector&lt;string&gt; vals;  
  unordered_map&lt;string, int&gt; counts;
};</pre>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/data-structure/leetcode-2227-encrypt-and-decrypt-strings/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2223. Sum of Scores of Built Strings</title>
		<link>https://zxi.mytechroad.com/blog/string/leetcode-2223-sum-of-scores-of-built-strings/</link>
					<comments>https://zxi.mytechroad.com/blog/string/leetcode-2223-sum-of-scores-of-built-strings/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 03 Apr 2022 01:48:46 +0000</pubDate>
				<category><![CDATA[String]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[string]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=9613</guid>

					<description><![CDATA[You are&#160;building&#160;a string&#160;s&#160;of length&#160;n&#160;one&#160;character at a time,&#160;prepending&#160;each new character to the&#160;front&#160;of the string. The strings are labeled from&#160;1&#160;to&#160;n, where the string with length&#160;i&#160;is labeled&#160;si. For&#8230;]]></description>
										<content:encoded><![CDATA[
<p>You are&nbsp;<strong>building</strong>&nbsp;a string&nbsp;<code>s</code>&nbsp;of length&nbsp;<code>n</code>&nbsp;<strong>one</strong>&nbsp;character at a time,&nbsp;<strong>prepending</strong>&nbsp;each new character to the&nbsp;<strong>front</strong>&nbsp;of the string. The strings are labeled from&nbsp;<code>1</code>&nbsp;to&nbsp;<code>n</code>, where the string with length&nbsp;<code>i</code>&nbsp;is labeled&nbsp;<code>s<sub>i</sub></code>.</p>



<ul class="wp-block-list"><li>For example, for&nbsp;<code>s = "abaca"</code>,&nbsp;<code>s<sub>1</sub>&nbsp;== "a"</code>,&nbsp;<code>s<sub>2</sub>&nbsp;== "ca"</code>,&nbsp;<code>s<sub>3</sub>&nbsp;== "aca"</code>, etc.</li></ul>



<p>The&nbsp;<strong>score</strong>&nbsp;of&nbsp;<code>s<sub>i</sub></code>&nbsp;is the length of the&nbsp;<strong>longest common prefix</strong>&nbsp;between&nbsp;<code>s<sub>i</sub></code>&nbsp;and&nbsp;<code>s<sub>n</sub></code>&nbsp;(Note that&nbsp;<code>s == s<sub>n</sub></code>).</p>



<p>Given the final string&nbsp;<code>s</code>, return<em>&nbsp;the&nbsp;<strong>sum</strong>&nbsp;of the&nbsp;<strong>score</strong>&nbsp;of every&nbsp;</em><code>s<sub>i</sub></code>.</p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> s = "babab"
<strong>Output:</strong> 9
<strong>Explanation:</strong>
For s<sub>1</sub> == "b", the longest common prefix is "b" which has a score of 1.
For s<sub>2</sub> == "ab", there is no common prefix so the score is 0.
For s<sub>3</sub> == "bab", the longest common prefix is "bab" which has a score of 3.
For s<sub>4</sub> == "abab", there is no common prefix so the score is 0.
For s<sub>5</sub> == "babab", the longest common prefix is "babab" which has a score of 5.
The sum of the scores is 1 + 0 + 3 + 0 + 5 = 9, so we return 9.</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> s = "azbazbzaz"
<strong>Output:</strong> 14
<strong>Explanation:</strong> 
For s<sub>2</sub> == "az", the longest common prefix is "az" which has a score of 2.
For s<sub>6</sub> == "azbzaz", the longest common prefix is "azb" which has a score of 3.
For s<sub>9</sub> == "azbazbzaz", the longest common prefix is "azbazbzaz" which has a score of 9.
For all other s<sub>i</sub>, the score is 0.
The sum of the scores is 2 + 3 + 9 = 14, so we return 14.
</pre>



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



<ul class="wp-block-list"><li><code>1 &lt;= s.length &lt;= 10<sup>5</sup></code></li><li><code>s</code>&nbsp;consists of lowercase English letters.</li></ul>



<h2 class="wp-block-heading"><strong>Solution: Z-Function</strong></h2>



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



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

<pre class="urvanov-syntax-highlighter-plain-tag">// Author: Huahua
class Solution {
public:
  long long sumScores(string s) {
    auto zFunc = [](string_view s) {
      const int n = s.length();
      vector&lt;long long&gt; z(n);
      for (long long i = 1, l = 0, r = 0; i &lt; n; ++i) {
        if (i &lt;= r)
          z[i] = min(r - i + 1, z[i - l]);
        while (i + z[i] &lt; n &amp;&amp; s[z[i]] == s[i + z[i]])
          ++z[i];
        if (i + z[i] - 1 &gt; r) {
          l = i;
          r = i + z[i] - 1;
        }      
      }
      return accumulate(begin(z), end(z), 0LL);
    };    
    return zFunc(s) + s.length();
  }
};</pre>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/string/leetcode-2223-sum-of-scores-of-built-strings/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2218. Maximum Value of K Coins From Piles</title>
		<link>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-2218-maximum-value-of-k-coins-from-piles/</link>
					<comments>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-2218-maximum-value-of-k-coins-from-piles/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Tue, 29 Mar 2022 04:51:27 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[hard]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=9596</guid>

					<description><![CDATA[There are&#160;n&#160;piles&#160;of coins on a table. Each pile consists of a&#160;positive number&#160;of coins of assorted denominations. In one move, you can choose any coin on&#160;top&#160;of&#8230;]]></description>
										<content:encoded><![CDATA[
<p>There are&nbsp;<code>n</code>&nbsp;<strong>piles</strong>&nbsp;of coins on a table. Each pile consists of a&nbsp;<strong>positive number</strong>&nbsp;of coins of assorted denominations.</p>



<p>In one move, you can choose any coin on&nbsp;<strong>top</strong>&nbsp;of any pile, remove it, and add it to your wallet.</p>



<p>Given a list&nbsp;<code>piles</code>, where&nbsp;<code>piles[i]</code>&nbsp;is a list of integers denoting the composition of the&nbsp;<code>i<sup>th</sup></code>&nbsp;pile from&nbsp;<strong>top to bottom</strong>, and a positive integer&nbsp;<code>k</code>, return&nbsp;<em>the&nbsp;<strong>maximum total value</strong>&nbsp;of coins you can have in your wallet if you choose&nbsp;<strong>exactly</strong></em>&nbsp;<code>k</code>&nbsp;<em>coins optimally</em>.</p>



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



<figure class="wp-block-image"><img decoding="async" src="https://assets.leetcode.com/uploads/2019/11/09/e1.png" alt=""/></figure>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> piles = [[1,100,3],[7,8,9]], k = 2
<strong>Output:</strong> 101
<strong>Explanation:</strong>
The above diagram shows the different ways we can choose k coins.
The maximum total we can obtain is 101.
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> piles = [[100],[100],[100],[100],[100],[100],[1,1,1,1,1,1,700]], k = 7
<strong>Output:</strong> 706
<strong>Explanation:
</strong>The maximum total can be obtained if we choose all coins from the last pile.
</pre>



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



<ul class="wp-block-list"><li><code>n == piles.length</code></li><li><code>1 &lt;= n &lt;= 1000</code></li><li><code>1 &lt;= piles[i][j] &lt;= 10<sup>5</sup></code></li><li><code>1 &lt;= k &lt;= sum(piles[i].length) &lt;= 2000</code></li></ul>



<h2 class="wp-block-heading"><strong>Solution: DP</strong></h2>



<p>let dp(i, k) be the maximum value of picking k elements using piles[i:n].</p>



<p>dp(i, k) = max(dp(i + 1, k), sum(piles[i][0~j]) + dp(i + 1, k &#8211; j &#8211; 1)), 0 &lt;= j &lt; len(piles[i])</p>



<p>Time complexity: O(n * m), m = sum(piles[i]) &lt;= 2000<br>Space complexity: O(n * k)</p>



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

<pre class="urvanov-syntax-highlighter-plain-tag"># Author: Huahua
class Solution:
  def maxValueOfCoins(self, piles: List[List[int]], k: int) -&gt; int:
    n = len(piles)
    
    @cache
    def dp(i: int, k: int) -&gt; int:
      &quot;&quot;&quot;Max value of picking k elements using piles[i:n].&quot;&quot;&quot;
      if i == n: return 0
      ans, cur = dp(i + 1, k), 0      
      for j in range(min(len(piles[i]), k)):        
        ans = max(ans, (cur := cur + piles[i][j]) + dp(i + 1, k - j - 1))
      return ans
    
    return dp(0, k)</pre>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-2218-maximum-value-of-k-coins-from-piles/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2197. Replace Non-Coprime Numbers in Array</title>
		<link>https://zxi.mytechroad.com/blog/stack/leetcode-2197-replace-non-coprime-numbers-in-array/</link>
					<comments>https://zxi.mytechroad.com/blog/stack/leetcode-2197-replace-non-coprime-numbers-in-array/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Tue, 08 Mar 2022 12:18:45 +0000</pubDate>
				<category><![CDATA[Stack]]></category>
		<category><![CDATA[co-prime]]></category>
		<category><![CDATA[gcd]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[lcm]]></category>
		<category><![CDATA[stack]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=9561</guid>

					<description><![CDATA[You are given an array of integers&#160;nums. Perform the following steps: Find&#160;any&#160;two&#160;adjacent&#160;numbers in&#160;nums&#160;that are&#160;non-coprime. If no such numbers are found,&#160;stop&#160;the process. Otherwise, delete the two&#8230;]]></description>
										<content:encoded><![CDATA[
<p>You are given an array of integers&nbsp;<code>nums</code>. Perform the following steps:</p>



<ol class="wp-block-list"><li>Find&nbsp;<strong>any</strong>&nbsp;two&nbsp;<strong>adjacent</strong>&nbsp;numbers in&nbsp;<code>nums</code>&nbsp;that are&nbsp;<strong>non-coprime</strong>.</li><li>If no such numbers are found,&nbsp;<strong>stop</strong>&nbsp;the process.</li><li>Otherwise, delete the two numbers and&nbsp;<strong>replace</strong>&nbsp;them with their&nbsp;<strong>LCM (Least Common Multiple)</strong>.</li><li><strong>Repeat</strong>&nbsp;this process as long as you keep finding two adjacent non-coprime numbers.</li></ol>



<p>Return&nbsp;<em>the&nbsp;<strong>final</strong>&nbsp;modified array.</em>&nbsp;It can be shown that replacing adjacent non-coprime numbers in&nbsp;<strong>any</strong>&nbsp;arbitrary order will lead to the same result.</p>



<p>The test cases are generated such that the values in the final array are&nbsp;<strong>less than or equal</strong>&nbsp;to&nbsp;<code>10<sup>8</sup></code>.</p>



<p>Two values&nbsp;<code>x</code>&nbsp;and&nbsp;<code>y</code>&nbsp;are&nbsp;<strong>non-coprime</strong>&nbsp;if&nbsp;<code>GCD(x, y) &gt; 1</code>&nbsp;where&nbsp;<code>GCD(x, y)</code>&nbsp;is the&nbsp;<strong>Greatest Common Divisor</strong>&nbsp;of&nbsp;<code>x</code>&nbsp;and&nbsp;<code>y</code>.</p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [6,4,3,2,7,6,2]
<strong>Output:</strong> [12,7,6]
<strong>Explanation:</strong> 
- (6, 4) are non-coprime with LCM(6, 4) = 12. Now, nums = [<strong><u>12</u></strong>,3,2,7,6,2].
- (12, 3) are non-coprime with LCM(12, 3) = 12. Now, nums = [<strong><u>12</u></strong>,2,7,6,2].
- (12, 2) are non-coprime with LCM(12, 2) = 12. Now, nums = [<strong><u>12</u></strong>,7,6,2].
- (6, 2) are non-coprime with LCM(6, 2) = 6. Now, nums = [12,7,<strong>6</strong>].
There are no more adjacent non-coprime numbers in nums.
Thus, the final modified array is [12,7,6].
Note that there are other ways to obtain the same resultant array.
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [2,2,1,1,3,3,3]
<strong>Output:</strong> [2,1,1,3]
<strong>Explanation:</strong> 
- (3, 3) are non-coprime with LCM(3, 3) = 3. Now, nums = [2,2,1,1,<strong>3</strong>,3].
- (3, 3) are non-coprime with LCM(3, 3) = 3. Now, nums = [2,2,1,1,<strong>3</strong>].
- (2, 2) are non-coprime with LCM(2, 2) = 2. Now, nums = [<strong>2</strong>,1,1,3].
There are no more adjacent non-coprime numbers in nums.
Thus, the final modified array is [2,1,1,3].
Note that there are other ways to obtain the same resultant array.
</pre>



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



<ul class="wp-block-list"><li><code>1 &lt;= nums.length &lt;= 10<sup>5</sup></code></li><li><code>1 &lt;= nums[i] &lt;= 10<sup>5</sup></code></li><li>The test cases are generated such that the values in the final array are&nbsp;<strong>less than or equal</strong>&nbsp;to&nbsp;<code>10<sup>8</sup></code>.</li></ul>



<h2 class="wp-block-heading"><strong>Solution: Stack</strong></h2>



<p>&#8220;&#8221;&#8221;It can be shown that replacing adjacent non-coprime numbers in&nbsp;<strong>any</strong>&nbsp;arbitrary order will lead to the same result.&#8221;&#8221;&#8221;</p>



<p>So that we can do it in one pass from left to right using a stack/vector.</p>



<p>Push the current number onto stack, and merge top two if they are not co-prime.</p>



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



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

<pre class="urvanov-syntax-highlighter-plain-tag">// Author: Huahua
class Solution {
public:
  vector&lt;int&gt; replaceNonCoprimes(vector&lt;int&gt;&amp; nums) {
    vector&lt;int&gt; ans;
    for (int x : nums) {
      ans.push_back(x);
      while (ans.size() &gt; 1) {
        const int n1 = ans[ans.size() - 1]; 
        const int n2 = ans[ans.size() - 2]; 
        const int d = gcd(n1, n2);
        if (d == 1) break;
        ans.pop_back();
        ans.pop_back();
        ans.push_back(n1 / d * n2);
      }
    }
    return ans;
  }
};</pre>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/stack/leetcode-2197-replace-non-coprime-numbers-in-array/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2183. Count Array Pairs Divisible by K</title>
		<link>https://zxi.mytechroad.com/blog/math/leetcode-2183-count-array-pairs-divisible-by-k/</link>
					<comments>https://zxi.mytechroad.com/blog/math/leetcode-2183-count-array-pairs-divisible-by-k/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sat, 05 Mar 2022 03:49:45 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[gcd]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[math]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=9531</guid>

					<description><![CDATA[Given a&#160;0-indexed&#160;integer array&#160;nums&#160;of length&#160;n&#160;and an integer&#160;k, return&#160;the&#160;number of pairs&#160;(i, j)&#160;such that: 0 &#60;= i &#60; j &#60;= n - 1&#160;and nums[i] * nums[j]&#160;is divisible by&#160;k.&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Given a&nbsp;<strong>0-indexed</strong>&nbsp;integer array&nbsp;<code>nums</code>&nbsp;of length&nbsp;<code>n</code>&nbsp;and an integer&nbsp;<code>k</code>, return&nbsp;<em>the&nbsp;<strong>number of pairs</strong></em>&nbsp;<code>(i, j)</code>&nbsp;<em>such that:</em></p>



<ul class="wp-block-list"><li><code>0 &lt;= i &lt; j &lt;= n - 1</code>&nbsp;<em>and</em></li><li><code>nums[i] * nums[j]</code>&nbsp;<em>is divisible by</em>&nbsp;<code>k</code>.</li></ul>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [1,2,3,4,5], k = 2
<strong>Output:</strong> 7
<strong>Explanation:</strong> 
The 7 pairs of indices whose corresponding products are divisible by 2 are
(0, 1), (0, 3), (1, 2), (1, 3), (1, 4), (2, 3), and (3, 4).
Their products are 2, 4, 6, 8, 10, 12, and 20 respectively.
Other pairs such as (0, 2) and (2, 4) have products 3 and 15 respectively, which are not divisible by 2.    
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [1,2,3,4], k = 5
<strong>Output:</strong> 0
<strong>Explanation:</strong> There does not exist any pair of indices whose corresponding product is divisible by 5.
</pre>



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



<ul class="wp-block-list"><li><code>1 &lt;= nums.length &lt;= 10<sup>5</sup></code></li><li><code>1 &lt;= nums[i], k &lt;= 10<sup>5</sup></code></li></ul>



<h2 class="wp-block-heading"><strong>Solution: Math</strong></h2>



<p>a * b % k == 0 &lt;=> gcd(a, k) * gcd(b, k) == 0</p>



<p>Use a counter of gcd(x, k) so far to compute the number of pairs.</p>



<p>Time complexity: O(n*f), where f is the number of gcds, f &lt;= 128 for x &lt;= 1e5<br>Space complexity: O(<meta charset="utf-8">f)</p>



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

<pre class="urvanov-syntax-highlighter-plain-tag">// Author: Huahua
class Solution {
public:
  long long countPairs(vector&lt;int&gt;&amp; nums, int k) {
    unordered_map&lt;int, int&gt; m;
    long long ans = 0;
    for (int x : nums) {
      long long d1 = gcd(x, k);
      for (const auto&amp; [d2, c] : m)
        if (d1 * d2 % k == 0) ans += c;
      ++m[d1];
    }
    return ans;
  }
};</pre>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/math/leetcode-2183-count-array-pairs-divisible-by-k/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2188. Minimum Time to Finish the Race</title>
		<link>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-2188-minimum-time-to-finish-the-race/</link>
					<comments>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-2188-minimum-time-to-finish-the-race/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Mon, 28 Feb 2022 12:56:59 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[preprocessing]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=9516</guid>

					<description><![CDATA[You are given a&#160;0-indexed&#160;2D integer array&#160;tires&#160;where&#160;tires[i] = [fi, ri]&#160;indicates that the&#160;ith&#160;tire can finish its&#160;xth&#160;successive lap in&#160;fi&#160;* ri(x-1)&#160;seconds. For example, if&#160;fi&#160;= 3&#160;and&#160;ri&#160;= 2, then the tire&#8230;]]></description>
										<content:encoded><![CDATA[
<p>You are given a&nbsp;<strong>0-indexed</strong>&nbsp;2D integer array&nbsp;<code>tires</code>&nbsp;where&nbsp;<code>tires[i] = [f<sub>i</sub>, r<sub>i</sub>]</code>&nbsp;indicates that the&nbsp;<code>i<sup>th</sup></code>&nbsp;tire can finish its&nbsp;<code>x<sup>th</sup></code>&nbsp;successive lap in&nbsp;<code>f<sub>i</sub>&nbsp;* r<sub>i</sub><sup>(x-1)</sup></code>&nbsp;seconds.</p>



<ul class="wp-block-list"><li>For example, if&nbsp;<code>f<sub>i</sub>&nbsp;= 3</code>&nbsp;and&nbsp;<code>r<sub>i</sub>&nbsp;= 2</code>, then the tire would finish its&nbsp;<code>1<sup>st</sup></code>&nbsp;lap in&nbsp;<code>3</code>&nbsp;seconds, its&nbsp;<code>2<sup>nd</sup></code>&nbsp;lap in&nbsp;<code>3 * 2 = 6</code>&nbsp;seconds, its&nbsp;<code>3<sup>rd</sup></code>&nbsp;lap in&nbsp;<code>3 * 2<sup>2</sup>&nbsp;= 12</code>&nbsp;seconds, etc.</li></ul>



<p>You are also given an integer&nbsp;<code>changeTime</code>&nbsp;and an integer&nbsp;<code>numLaps</code>.</p>



<p>The race consists of&nbsp;<code>numLaps</code>&nbsp;laps and you may start the race with&nbsp;<strong>any</strong>&nbsp;tire. You have an&nbsp;<strong>unlimited</strong>&nbsp;supply of each tire and after every lap, you may&nbsp;<strong>change</strong>&nbsp;to any given tire (including the current tire type) if you wait&nbsp;<code>changeTime</code>&nbsp;seconds.</p>



<p>Return<em>&nbsp;the&nbsp;<strong>minimum</strong>&nbsp;time to finish the race.</em></p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> tires = [[2,3],[3,4]], changeTime = 5, numLaps = 4
<strong>Output:</strong> 21
<strong>Explanation:</strong> 
Lap 1: Start with tire 0 and finish the lap in 2 seconds.
Lap 2: Continue with tire 0 and finish the lap in 2 * 3 = 6 seconds.
Lap 3: Change tires to a new tire 0 for 5 seconds and then finish the lap in another 2 seconds.
Lap 4: Continue with tire 0 and finish the lap in 2 * 3 = 6 seconds.
Total time = 2 + 6 + 5 + 2 + 6 = 21 seconds.
The minimum time to complete the race is 21 seconds.
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> tires = [[1,10],[2,2],[3,4]], changeTime = 6, numLaps = 5
<strong>Output:</strong> 25
<strong>Explanation:</strong> 
Lap 1: Start with tire 1 and finish the lap in 2 seconds.
Lap 2: Continue with tire 1 and finish the lap in 2 * 2 = 4 seconds.
Lap 3: Change tires to a new tire 1 for 6 seconds and then finish the lap in another 2 seconds.
Lap 4: Continue with tire 1 and finish the lap in 2 * 2 = 4 seconds.
Lap 5: Change tires to tire 0 for 6 seconds then finish the lap in another 1 second.
Total time = 2 + 4 + 6 + 2 + 4 + 6 + 1 = 25 seconds.
The minimum time to complete the race is 25 seconds. 
</pre>



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



<ul class="wp-block-list"><li><code>1 &lt;= tires.length &lt;= 10<sup>5</sup></code></li><li><code>tires[i].length == 2</code></li><li><code>1 &lt;= f<sub>i</sub>, changeTime &lt;= 10<sup>5</sup></code></li><li><code>2 &lt;= r<sub>i</sub>&nbsp;&lt;= 10<sup>5</sup></code></li><li><code>1 &lt;= numLaps &lt;= 1000</code></li></ul>



<h2 class="wp-block-heading"><strong>Solution: DP</strong></h2>



<p>Observation: since ri &gt;= 2, we must change tire within 20 laps, otherwise it will be slower.</p>



<p>pre-compute the time to finish k laps using each type of tire (k &lt; 20), find min for each lap.</p>



<p>dp[i] = best[i], i &lt; 20,<br>dp[i] = min{dp[i &#8211; j] + changeTime + best[j]}, i &gt; 20</p>



<p>Time complexity: O(n)<br>Space complexity: O(n) -&gt; O(20)</p>



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

<pre class="urvanov-syntax-highlighter-plain-tag">// Author: Huahua
class Solution {
public:
  int minimumFinishTime(vector&lt;vector&lt;int&gt;&gt;&amp; tires, int changeTime, int numLaps) {
    constexpr int kMax = 20;
    vector&lt;long&gt; best(kMax, INT_MAX);
    for (const auto&amp; t : tires)
      for (long i = 1, l = t[0], s = t[0]; i &lt; kMax &amp;&amp; l &lt; t[0] + changeTime; ++i, l *= t[1], s += l)
        best[i] = min(best[i], s);
    vector&lt;long&gt; dp(numLaps + 1, INT_MAX);    
    for (int i = 1; i &lt;= numLaps; ++i)
      for (int j = 1; j &lt;= min(i, kMax - 1); ++j)
        dp[i] = min(dp[i], best[j] + (i &gt; j) * (changeTime + dp[i - j]));
    return dp[numLaps];
  }
};</pre>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-2188-minimum-time-to-finish-the-race/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2151. Maximum Good People Based on Statements</title>
		<link>https://zxi.mytechroad.com/blog/searching/leetcode-2151-maximum-good-people-based-on-statements/</link>
					<comments>https://zxi.mytechroad.com/blog/searching/leetcode-2151-maximum-good-people-based-on-statements/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sat, 05 Feb 2022 02:13:31 +0000</pubDate>
				<category><![CDATA[Search]]></category>
		<category><![CDATA[bitmask]]></category>
		<category><![CDATA[combination]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[subsets]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=9477</guid>

					<description><![CDATA[There are two types of persons: The&#160;good person: The person who always tells the truth. The&#160;bad person: The person who might tell the truth and&#8230;]]></description>
										<content:encoded><![CDATA[
<p>There are two types of persons:</p>



<ul class="wp-block-list"><li>The&nbsp;<strong>good person</strong>: The person who always tells the truth.</li><li>The&nbsp;<strong>bad person</strong>: The person who might tell the truth and might lie.</li></ul>



<p>You are given a&nbsp;<strong>0-indexed</strong>&nbsp;2D integer array&nbsp;<code>statements</code>&nbsp;of size&nbsp;<code>n x n</code>&nbsp;that represents the statements made by&nbsp;<code>n</code>&nbsp;people about each other. More specifically,&nbsp;<code>statements[i][j]</code>&nbsp;could be one of the following:</p>



<ul class="wp-block-list"><li><code>0</code>&nbsp;which represents a statement made by person&nbsp;<code>i</code>&nbsp;that person&nbsp;<code>j</code>&nbsp;is a&nbsp;<strong>bad</strong>&nbsp;person.</li><li><code>1</code>&nbsp;which represents a statement made by person&nbsp;<code>i</code>&nbsp;that person&nbsp;<code>j</code>&nbsp;is a&nbsp;<strong>good</strong>&nbsp;person.</li><li><code>2</code>&nbsp;represents that&nbsp;<strong>no statement</strong>&nbsp;is made by person&nbsp;<code>i</code>&nbsp;about person&nbsp;<code>j</code>.</li></ul>



<p>Additionally, no person ever makes a statement about themselves. Formally, we have that&nbsp;<code>statements[i][i] = 2</code>&nbsp;for all&nbsp;<code>0 &lt;= i &lt; n</code>.</p>



<p>Return&nbsp;<em>the&nbsp;<strong>maximum</strong>&nbsp;number of people who can be&nbsp;<strong>good</strong>&nbsp;based on the statements made by the&nbsp;</em><code>n</code><em>&nbsp;people</em>.</p>



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



<figure class="wp-block-image"><img decoding="async" src="https://assets.leetcode.com/uploads/2022/01/15/logic1.jpg" alt=""/></figure>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> statements = [[2,1,2],[1,2,2],[2,0,2]]
<strong>Output:</strong> 2
<strong>Explanation:</strong> Each person makes a single statement.
- Person 0 states that person 1 is good.
- Person 1 states that person 0 is good.
- Person 2 states that person 1 is bad.
Let's take person 2 as the key.
- Assuming that person 2 is a good person:
    - Based on the statement made by person 2, person 1 is a bad person.
    - Now we know for sure that person 1 is bad and person 2 is good.
    - Based on the statement made by person 1, and since person 1 is bad, they could be:
        - telling the truth. There will be a contradiction in this case and this assumption is invalid.
        - lying. In this case, person 0 is also a bad person and lied in their statement.
    - <strong>Following that person 2 is a good person, there will be only one good person in the group</strong>.
- Assuming that person 2 is a bad person:
    - Based on the statement made by person 2, and since person 2 is bad, they could be:
        - telling the truth. Following this scenario, person 0 and 1 are both bad as explained before.
            - <strong>Following that person 2 is bad but told the truth, there will be no good persons in the group</strong>.
        - lying. In this case person 1 is a good person.
            - Since person 1 is a good person, person 0 is also a good person.
            - <strong>Following that person 2 is bad and lied, there will be two good persons in the group</strong>.
We can see that at most 2 persons are good in the best case, so we return 2.
Note that there is more than one way to arrive at this conclusion.
</pre>



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



<figure class="wp-block-image"><img decoding="async" src="https://assets.leetcode.com/uploads/2022/01/15/logic2.jpg" alt=""/></figure>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> statements = [[2,0],[0,2]]
<strong>Output:</strong> 1
<strong>Explanation:</strong> Each person makes a single statement.
- Person 0 states that person 1 is bad.
- Person 1 states that person 0 is bad.
Let's take person 0 as the key.
- Assuming that person 0 is a good person:
    - Based on the statement made by person 0, person 1 is a bad person and was lying.
    - <strong>Following that person 0 is a good person, there will be only one good person in the group</strong>.
- Assuming that person 0 is a bad person:
    - Based on the statement made by person 0, and since person 0 is bad, they could be:
        - telling the truth. Following this scenario, person 0 and 1 are both bad.
            - <strong>Following that person 0 is bad but told the truth, there will be no good persons in the group</strong>.
        - lying. In this case person 1 is a good person.
            - <strong>Following that person 0 is bad and lied, there will be only one good person in the group</strong>.
We can see that at most, one person is good in the best case, so we return 1.
Note that there is more than one way to arrive at this conclusion.
</pre>



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



<ul class="wp-block-list"><li><code>n == statements.length == statements[i].length</code></li><li><code>2 &lt;= n &lt;= 15</code></li><li><code>statements[i][j]</code>&nbsp;is either&nbsp;<code>0</code>,&nbsp;<code>1</code>, or&nbsp;<code>2</code>.</li><li><code>statements[i][i] == 2</code></li></ul>



<h2 class="wp-block-heading"><strong>Solution: Combination / Bitmask</strong></h2>



<p>Enumerate all subsets of n people and assume they are good people. Check whether their statements have any conflicts. We can ignore the statements from bad people since those can be either true or false and does not affect our checks.</p>



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



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

<pre class="urvanov-syntax-highlighter-plain-tag">// Author: Huahua
class Solution {
public:
  int maximumGood(vector&lt;vector&lt;int&gt;&gt;&amp; statements) {
    const int n = statements.size();
    auto valid = [&amp;](int s) {
      for (int i = 0; i &lt; n; ++i) {
        if (!(s &gt;&gt; i &amp; 1)) continue;
        for (int j = 0; j &lt; n; ++j) {
          const bool good = s &gt;&gt; j &amp; 1;
          if ((good &amp;&amp; statements[i][j] == 0) || (!good &amp;&amp; statements[i][j] == 1))
            return false;
        }
      }
      return true;
    };
    int ans = 0;
    for (int s = 1; s &lt; 1 &lt;&lt; n; ++s)
      if (valid(s)) ans = max(ans, __builtin_popcount(s));
    return ans;
  }
};</pre>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/searching/leetcode-2151-maximum-good-people-based-on-statements/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2141. Maximum Running Time of N Computers</title>
		<link>https://zxi.mytechroad.com/blog/algorithms/binary-search/leetcode-2141-maximum-running-time-of-n-computers/</link>
					<comments>https://zxi.mytechroad.com/blog/algorithms/binary-search/leetcode-2141-maximum-running-time-of-n-computers/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Mon, 31 Jan 2022 00:28:09 +0000</pubDate>
				<category><![CDATA[Binary Search]]></category>
		<category><![CDATA[binary search]]></category>
		<category><![CDATA[gready]]></category>
		<category><![CDATA[hard]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=9446</guid>

					<description><![CDATA[You have&#160;n&#160;computers. You are given the integer&#160;n&#160;and a&#160;0-indexed&#160;integer array&#160;batteries&#160;where the&#160;ith&#160;battery can&#160;run&#160;a computer for&#160;batteries[i]&#160;minutes. You are interested in running&#160;all&#160;n&#160;computers&#160;simultaneously&#160;using the given batteries. Initially, you can insert&#160;at&#8230;]]></description>
										<content:encoded><![CDATA[
<p>You have&nbsp;<code>n</code>&nbsp;computers. You are given the integer&nbsp;<code>n</code>&nbsp;and a&nbsp;<strong>0-indexed</strong>&nbsp;integer array&nbsp;<code>batteries</code>&nbsp;where the&nbsp;<code>i<sup>th</sup></code>&nbsp;battery can&nbsp;<strong>run</strong>&nbsp;a computer for&nbsp;<code>batteries[i]</code>&nbsp;minutes. You are interested in running&nbsp;<strong>all</strong>&nbsp;<code>n</code>&nbsp;computers&nbsp;<strong>simultaneously</strong>&nbsp;using the given batteries.</p>



<p>Initially, you can insert&nbsp;<strong>at most one battery</strong>&nbsp;into each computer. After that and at any integer time moment, you can remove a battery from a computer and insert another battery&nbsp;<strong>any number of times</strong>. The inserted battery can be a totally new battery or a battery from another computer. You may assume that the removing and inserting processes take no time.</p>



<p>Note that the batteries cannot be recharged.</p>



<p>Return&nbsp;<em>the&nbsp;<strong>maximum</strong>&nbsp;number of minutes you can run all the&nbsp;</em><code>n</code><em>&nbsp;computers simultaneously.</em></p>



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



<figure class="wp-block-image"><img decoding="async" src="https://assets.leetcode.com/uploads/2022/01/06/example1-fit.png" alt=""/></figure>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> n = 2, batteries = [3,3,3]
<strong>Output:</strong> 4
<strong>Explanation:</strong> 
Initially, insert battery 0 into the first computer and battery 1 into the second computer.
After two minutes, remove battery 1 from the second computer and insert battery 2 instead. Note that battery 1 can still run for one minute.
At the end of the third minute, battery 0 is drained, and you need to remove it from the first computer and insert battery 1 instead.
By the end of the fourth minute, battery 1 is also drained, and the first computer is no longer running.
We can run the two computers simultaneously for at most 4 minutes, so we return 4.

</pre>



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



<figure class="wp-block-image"><img decoding="async" src="https://assets.leetcode.com/uploads/2022/01/06/example2.png" alt=""/></figure>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> n = 2, batteries = [1,1,1,1]
<strong>Output:</strong> 2
<strong>Explanation:</strong> 
Initially, insert battery 0 into the first computer and battery 2 into the second computer. 
After one minute, battery 0 and battery 2 are drained so you need to remove them and insert battery 1 into the first computer and battery 3 into the second computer. 
After another minute, battery 1 and battery 3 are also drained so the first and second computers are no longer running.
We can run the two computers simultaneously for at most 2 minutes, so we return 2.
</pre>



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



<ul class="wp-block-list"><li><code>1 &lt;= n &lt;= batteries.length &lt;= 10<sup>5</sup></code></li><li><code>1 &lt;= batteries[i] &lt;= 10<sup>9</sup></code></li></ul>



<h2 class="wp-block-heading"><strong>Solution: Binary Search</strong></h2>



<p>Find the smallest L that we can not run, ans = L &#8211; 1.</p>



<p>For a guessing m, we check the total battery powers T = sum(min(m, batteries[i])), if T >= m * n, it means there is a way (doesn&#8217;t need to figure out how) to run n computers for m minutes by fully unitize those batteries.</p>



<p>Proof: If T >= m*n holds, there are two cases:</p>



<ol class="wp-block-list"><li>There are only n batteries, can not swap, but each of them has power >= m.</li><li>At least one of the batteries have power less than m, but there are more than n batteries and total power is sufficient, we can swap them with others.</li></ol>



<p>Time complexity: O(Slogn) where S = sum(batteries)<br>Space complexity: O(1)</p>



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

<pre class="urvanov-syntax-highlighter-plain-tag">// Author: Huahua
class Solution {
public:
  long long maxRunTime(int n, vector&lt;int&gt;&amp; batteries) {
    long long l = 0;
    long long r = accumulate(begin(batteries), end(batteries), 0LL) + 1;
    while (l &lt; r) {
      long long m = l + (r - l) / 2;
      long long t = 0;
      for (long long b : batteries)
        t += min(m, b);
      if (m * n &gt; t) // smallest m that does not fit.
        r = m;
      else
        l = m + 1;
    }
    return l - 1; // greatest m that fits.
  }
};</pre>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/algorithms/binary-search/leetcode-2141-maximum-running-time-of-n-computers/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
