<?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>bitmask Archives - Huahua&#039;s Tech Road</title>
	<atom:link href="https://zxi.mytechroad.com/blog/tag/bitmask/feed/" rel="self" type="application/rss+xml" />
	<link>https://zxi.mytechroad.com/blog/tag/bitmask/</link>
	<description></description>
	<lastBuildDate>Sun, 11 Sep 2022 17:59:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.0.8</generator>

<image>
	<url>https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/cropped-photo-32x32.jpg</url>
	<title>bitmask Archives - Huahua&#039;s Tech Road</title>
	<link>https://zxi.mytechroad.com/blog/tag/bitmask/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>花花酱 LeetCode 2405. Optimal Partition of String</title>
		<link>https://zxi.mytechroad.com/blog/greedy/leetcode-2405-optimal-partition-of-string/</link>
					<comments>https://zxi.mytechroad.com/blog/greedy/leetcode-2405-optimal-partition-of-string/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 11 Sep 2022 15:05:35 +0000</pubDate>
				<category><![CDATA[Greedy]]></category>
		<category><![CDATA[bitmask]]></category>
		<category><![CDATA[greedy]]></category>
		<category><![CDATA[hashtable]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=9807</guid>

					<description><![CDATA[<p>Given a string&#160;s, partition the string into one or more&#160;substrings&#160;such that the characters in each substring are&#160;unique. That is, no letter appears in a single&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/greedy/leetcode-2405-optimal-partition-of-string/">花花酱 LeetCode 2405. Optimal Partition of String</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-embed 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 2405. Optimal Partition of String- 刷题找工作 EP401" width="500" height="281" src="https://www.youtube.com/embed/cKjQNbcSX0s?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<p>Given a string&nbsp;<code>s</code>, partition the string into one or more&nbsp;<strong>substrings</strong>&nbsp;such that the characters in each substring are&nbsp;<strong>unique</strong>. That is, no letter appears in a single substring more than&nbsp;<strong>once</strong>.</p>



<p>Return&nbsp;<em>the&nbsp;<strong>minimum</strong>&nbsp;number of substrings in such a partition.</em></p>



<p>Note that each character should belong to exactly one substring in a partition.</p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> s = "abacaba"
<strong>Output:</strong> 4
<strong>Explanation:</strong>
Two possible partitions are ("a","ba","cab","a") and ("ab","a","ca","ba").
It can be shown that 4 is the minimum number of substrings needed.
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> s = "ssssss"
<strong>Output:</strong> 6
<strong>Explanation:
</strong>The only valid partition is ("s","s","s","s","s","s").
</pre>



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



<ul><li><code>1 &lt;= s.length &lt;= 10<sup>5</sup></code></li><li><code>s</code>&nbsp;consists of only English lowercase letters.</li></ul>



<h2><strong>Solution: Greedy</strong></h2>



<figure class="wp-block-image size-full"><a href="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/09/lc-2405-ep401-s1.png"><img width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/09/lc-2405-ep401-s1.png" alt="" class="wp-image-9812" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/09/lc-2405-ep401-s1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/09/lc-2405-ep401-s1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/09/lc-2405-ep401-s1-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/09/lc-2405-ep401-s2.png"><img width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/09/lc-2405-ep401-s2.png" alt="" class="wp-image-9813" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2022/09/lc-2405-ep401-s2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/09/lc-2405-ep401-s2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2022/09/lc-2405-ep401-s2-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></a></figure>



<p>Extend the cur string as long as possible unless a duplicate character occurs.</p>



<p>You can use hashtable / array or bitmask to mark whether a character has been seen so far.</p>



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



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

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  int partitionString(string s) {
    unordered_set&lt;char&gt; m;
    int ans = 0;
    for (char c : s) {
      if (m.insert(c).second) continue;
      m.clear();
      m.insert(c);
      ++ans;
    }
    return ans + 1;
  }
};</pre>
</div></div>



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

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  int partitionString(string s) {
    vector&lt;int&gt; m(26);
    int ans = 0;
    for (char c : s) {
      if (++m[c - 'a'] == 1) continue;
      fill(begin(m), end(m), 0);
      m[c - 'a'] = 1;
      ++ans;
    }
    return ans + 1;
  }
};</pre>
</div></div>



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

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  int partitionString(string s) {
    int mask = 0;
    int ans = 0;
    for (char c : s) {
      if (mask &amp; (1 &lt;&lt; (c - 'a'))) {
        mask = 0;        
        ++ans;
      }
      mask |= 1 &lt;&lt; (c - 'a');
    }
    return ans + 1;
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/greedy/leetcode-2405-optimal-partition-of-string/">花花酱 LeetCode 2405. Optimal Partition of String</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/greedy/leetcode-2405-optimal-partition-of-string/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[<p>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;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/searching/leetcode-2151-maximum-good-people-based-on-statements/">花花酱 LeetCode 2151. Maximum Good People Based on Statements</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>There are two types of persons:</p>



<ul><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><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 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 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><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><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="crayon-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>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/searching/leetcode-2151-maximum-good-people-based-on-statements/">花花酱 LeetCode 2151. Maximum Good People Based on Statements</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/searching/leetcode-2151-maximum-good-people-based-on-statements/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2135. Count Words Obtained After Adding a Letter</title>
		<link>https://zxi.mytechroad.com/blog/hashtable/leetcode-2135-count-words-obtained-after-adding-a-letter/</link>
					<comments>https://zxi.mytechroad.com/blog/hashtable/leetcode-2135-count-words-obtained-after-adding-a-letter/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Tue, 18 Jan 2022 03:12:42 +0000</pubDate>
				<category><![CDATA[Hashtable]]></category>
		<category><![CDATA[bitmask]]></category>
		<category><![CDATA[hashtable]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[string]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=9428</guid>

					<description><![CDATA[<p>You are given two&#160;0-indexed&#160;arrays of strings&#160;startWords&#160;and&#160;targetWords. Each string consists of&#160;lowercase English letters&#160;only. For each string in&#160;targetWords, check if it is possible to choose a string&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/hashtable/leetcode-2135-count-words-obtained-after-adding-a-letter/">花花酱 LeetCode 2135. Count Words Obtained After Adding a Letter</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>You are given two&nbsp;<strong>0-indexed</strong>&nbsp;arrays of strings&nbsp;<code>startWords</code>&nbsp;and&nbsp;<code>targetWords</code>. Each string consists of&nbsp;<strong>lowercase English letters</strong>&nbsp;only.</p>



<p>For each string in&nbsp;<code>targetWords</code>, check if it is possible to choose a string from&nbsp;<code>startWords</code>&nbsp;and perform a&nbsp;<strong>conversion operation</strong>&nbsp;on it to be equal to that from&nbsp;<code>targetWords</code>.</p>



<p>The&nbsp;<strong>conversion operation</strong>&nbsp;is described in the following two steps:</p>



<ol><li><strong>Append</strong>&nbsp;any lowercase letter that is&nbsp;<strong>not present</strong>&nbsp;in the string to its end.<ul><li>For example, if the string is&nbsp;<code>"abc"</code>, the letters&nbsp;<code>'d'</code>,&nbsp;<code>'e'</code>, or&nbsp;<code>'y'</code>&nbsp;can be added to it, but not&nbsp;<code>'a'</code>. If&nbsp;<code>'d'</code>&nbsp;is added, the resulting string will be&nbsp;<code>"abcd"</code>.</li></ul></li><li><strong>Rearrange</strong>&nbsp;the letters of the new string in&nbsp;<strong>any</strong>&nbsp;arbitrary order.<ul><li>For example,&nbsp;<code>"abcd"</code>&nbsp;can be rearranged to&nbsp;<code>"acbd"</code>,&nbsp;<code>"bacd"</code>,&nbsp;<code>"cbda"</code>, and so on. Note that it can also be rearranged to&nbsp;<code>"abcd"</code>&nbsp;itself.</li></ul></li></ol>



<p>Return&nbsp;<em>the&nbsp;<strong>number of strings</strong>&nbsp;in&nbsp;</em><code>targetWords</code><em>&nbsp;that can be obtained by performing the operations on&nbsp;<strong>any</strong>&nbsp;string of&nbsp;</em><code>startWords</code>.</p>



<p><strong>Note</strong>&nbsp;that you will only be verifying if the string in&nbsp;<code>targetWords</code>&nbsp;can be obtained from a string in&nbsp;<code>startWords</code>&nbsp;by performing the operations. The strings in&nbsp;<code>startWords</code>&nbsp;<strong>do not</strong>&nbsp;actually change during this process.</p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> startWords = ["ant","act","tack"], targetWords = ["tack","act","acti"]
<strong>Output:</strong> 2
<strong>Explanation:</strong>
- In order to form targetWords[0] = "tack", we use startWords[1] = "act", append 'k' to it, and rearrange "actk" to "tack".
- There is no string in startWords that can be used to obtain targetWords[1] = "act".
  Note that "act" does exist in startWords, but we <strong>must</strong> append one letter to the string before rearranging it.
- In order to form targetWords[2] = "acti", we use startWords[1] = "act", append 'i' to it, and rearrange "acti" to "acti" itself.
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> startWords = ["ab","a"], targetWords = ["abc","abcd"]
<strong>Output:</strong> 1
<strong>Explanation:</strong>
- In order to form targetWords[0] = "abc", we use startWords[0] = "ab", add 'c' to it, and rearrange it to "abc".
- There is no string in startWords that can be used to obtain targetWords[1] = "abcd".
</pre>



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



<ul><li><code>1 &lt;= startWords.length, targetWords.length &lt;= 5 * 10<sup>4</sup></code></li><li><code>1 &lt;= startWords[i].length, targetWords[j].length &lt;= 26</code></li><li>Each string of&nbsp;<code>startWords</code>&nbsp;and&nbsp;<code>targetWords</code>&nbsp;consists of lowercase English letters only.</li><li>No letter occurs more than once in any string of&nbsp;<code>startWords</code>&nbsp;or&nbsp;<code>targetWords</code>.</li></ul>



<h2><strong>Solution: Bitmask w/ Hashtable</strong></h2>



<p>Since there is no duplicate letters in each word, we can use a bitmask to represent a word.</p>



<p>Step 1: For each word in startWords, we obtain its bitmask and insert it into a hashtable.<br>Step 2: For each word in targetWords, enumerate it&#8217;s letter and unset 1 bit (skip one letter) and see whether it&#8217;s in the hashtable or not.</p>



<p>E.g. for target word &#8220;abc&#8221;, its bitmask is 0&#8230;0111, and we test whether &#8220;ab&#8221; or &#8220;ac&#8221; or &#8220;bc&#8221; in the hashtable or not.</p>



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



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

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  int wordCount(vector&lt;string&gt;&amp; startWords, vector&lt;string&gt;&amp; targetWords) {
    unordered_set&lt;int&gt; s;
    auto getKey = [](const string&amp; s) {      
      return accumulate(begin(s), end(s), 0, [](int key, char c) { return key | (1 &lt;&lt; (c - 'a')); });
    };
    
    for (const string&amp; w : startWords)
      s.insert(getKey(w));
        
    return accumulate(begin(targetWords), end(targetWords), 0, [&amp;](int ans, const string&amp; w) {
      const int key = getKey(w);
      return ans + any_of(begin(w), end(w), [&amp;](char c) { return s.count(key ^ (1 &lt;&lt; (c - 'a'))); });
    });
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/hashtable/leetcode-2135-count-words-obtained-after-adding-a-letter/">花花酱 LeetCode 2135. Count Words Obtained After Adding a Letter</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/hashtable/leetcode-2135-count-words-obtained-after-adding-a-letter/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1915. Number of Wonderful Substrings</title>
		<link>https://zxi.mytechroad.com/blog/hashtable/leetcode-1915-number-of-wonderful-substrings/</link>
					<comments>https://zxi.mytechroad.com/blog/hashtable/leetcode-1915-number-of-wonderful-substrings/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sat, 25 Dec 2021 11:11:08 +0000</pubDate>
				<category><![CDATA[Hashtable]]></category>
		<category><![CDATA[bitmask]]></category>
		<category><![CDATA[hashtable]]></category>
		<category><![CDATA[prefix]]></category>
		<category><![CDATA[substring]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=9230</guid>

					<description><![CDATA[<p>A&#160;wonderful&#160;string is a string where&#160;at most one&#160;letter appears an&#160;odd&#160;number of times. For example,&#160;"ccjjc"&#160;and&#160;"abab"&#160;are wonderful, but&#160;"ab"&#160;is not. Given a string&#160;word&#160;that consists of the first ten lowercase&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/hashtable/leetcode-1915-number-of-wonderful-substrings/">花花酱 LeetCode 1915. Number of Wonderful Substrings</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>A&nbsp;<strong>wonderful</strong>&nbsp;string is a string where&nbsp;<strong>at most one</strong>&nbsp;letter appears an&nbsp;<strong>odd</strong>&nbsp;number of times.</p>



<ul><li>For example,&nbsp;<code>"ccjjc"</code>&nbsp;and&nbsp;<code>"abab"</code>&nbsp;are wonderful, but&nbsp;<code>"ab"</code>&nbsp;is not.</li></ul>



<p>Given a string&nbsp;<code>word</code>&nbsp;that consists of the first ten lowercase English letters (<code>'a'</code>&nbsp;through&nbsp;<code>'j'</code>), return&nbsp;<em>the&nbsp;<strong>number of wonderful non-empty substrings</strong>&nbsp;in&nbsp;</em><code>word</code><em>. If the same substring appears multiple times in&nbsp;</em><code>word</code><em>, then count&nbsp;<strong>each occurrence</strong>&nbsp;separately.</em></p>



<p>A&nbsp;<strong>substring</strong>&nbsp;is a contiguous sequence of characters in a string.</p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> word = "aba"
<strong>Output:</strong> 4
<strong>Explanation:</strong> The four wonderful substrings are underlined below:
- "<strong>a</strong>ba" -&gt; "a"
- "a<strong>b</strong>a" -&gt; "b"
- "ab<strong>a</strong>" -&gt; "a"
- "<strong>aba</strong>" -&gt; "aba"
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> word = "aabb"
<strong>Output:</strong> 9
<strong>Explanation:</strong> The nine wonderful substrings are underlined below:
- "<strong><u>a</u></strong>abb" -&gt; "a"
- "<strong>aa</strong>bb" -&gt; "aa"
- "<strong>aab</strong>b" -&gt; "aab"
- "<strong>aabb</strong>" -&gt; "aabb"
- "a<strong>a</strong>bb" -&gt; "a"
- "a<strong>abb</strong>" -&gt; "abb"
- "aa<strong>b</strong>b" -&gt; "b"
- "aa<strong>bb</strong>" -&gt; "bb"
- "aab<strong>b</strong>" -&gt; "b"
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> word = "he"
<strong>Output:</strong> 2
<strong>Explanation:</strong> The two wonderful substrings are underlined below:
- "<strong><u>h</u></strong>e" -&gt; "h"
- "h<strong><u>e</u></strong>" -&gt; "e"
</pre>



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



<ul><li><code>1 &lt;= word.length &lt;= 10<sup>5</sup></code></li><li><code>word</code>&nbsp;consists of lowercase English letters from&nbsp;<code>'a'</code>&nbsp;to&nbsp;<code>'j'</code>.</li></ul>



<h2><strong>Solution: Prefix Bitmask + Hashtable</strong></h2>



<p>Similar to <a href="https://zxi.mytechroad.com/blog/hashtable/leetcode-1371-find-the-longest-substring-containing-vowels-in-even-counts/" data-type="post" data-id="6400">花花酱 LeetCode 1371. Find the Longest Substring Containing Vowels in Even Counts</a>, we use   a bitmask to represent the occurrence (odd or even) of each letter and use a hashtable to store the frequency of each bitmask seen so far.<br><br>1. &#8220;0000000000&#8221; means all letters occur even times.<br>2. &#8220;0000000101&#8221; means <meta charset="utf-8">all letters occur even times expect letter &#8216;a&#8217; and &#8216;c&#8217; that occur odd times.</p>



<p>We scan the word from left to right and update the bitmask: bitmask ^= (1 &lt;&lt; (c-&#8216;a&#8217;)). <br>However, the bitmask only represents the state of the prefix, i.e. word[0:i], then how can we count substrings? The answer is hashtable.  If the same bitmask occurs c times before, which means there are c indices that word[0~j1], word[0~j2], &#8230;, word[0~jc] have the same state as word[0~i] that means for word[j1+1~i], word[j2+1~i], &#8230;, word[jc+1~i], all letters occurred even times. <br>For the &#8220;at most one odd&#8221; case, we toggle each bit of the bitmask and check how many times it occurred before.</p>



<p>ans += freq[mask] + sum(freq[mask ^ (1 &lt;&lt; i)] for i in range(k))</p>



<p>Time complexity: O(n*k)<br>Space complexity: O(2<sup>k</sup>)<br>where k = j &#8211; a + 1 = 10</p>



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

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  long long wonderfulSubstrings(string word) {
    constexpr int l = 'j' - 'a' + 1;
    vector&lt;int&gt; count(1 &lt;&lt; l);
    count[0] = 1;
    int mask = 0;
    long long ans = 0;
    for (char c : word) {
      mask ^= 1 &lt;&lt; (c - 'a'); 
      for (int i = 0; i &lt; l; ++i)
        ans += count[mask ^ (1 &lt;&lt; i)]; // one odd.
      ans += count[mask]++; // all even.
    }
    return ans;
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/hashtable/leetcode-1915-number-of-wonderful-substrings/">花花酱 LeetCode 1915. Number of Wonderful Substrings</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/hashtable/leetcode-1915-number-of-wonderful-substrings/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1900. The Earliest and Latest Rounds Where Players Compete</title>
		<link>https://zxi.mytechroad.com/blog/recursion/leetcode-1900-the-earliest-and-latest-rounds-where-players-compete/</link>
					<comments>https://zxi.mytechroad.com/blog/recursion/leetcode-1900-the-earliest-and-latest-rounds-where-players-compete/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Thu, 12 Aug 2021 04:21:46 +0000</pubDate>
				<category><![CDATA[Recursion]]></category>
		<category><![CDATA[bitmask]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[recursion]]></category>
		<category><![CDATA[simulation]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=8574</guid>

					<description><![CDATA[<p>There is a tournament where&#160;n&#160;players are participating. The players are standing in a single row and are numbered from&#160;1&#160;to&#160;n&#160;based on their&#160;initial&#160;standing position (player&#160;1&#160;is the first&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/recursion/leetcode-1900-the-earliest-and-latest-rounds-where-players-compete/">花花酱 LeetCode 1900. The Earliest and Latest Rounds Where Players Compete</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>There is a tournament where&nbsp;<code>n</code>&nbsp;players are participating. The players are standing in a single row and are numbered from&nbsp;<code>1</code>&nbsp;to&nbsp;<code>n</code>&nbsp;based on their&nbsp;<strong>initial</strong>&nbsp;standing position (player&nbsp;<code>1</code>&nbsp;is the first player in the row, player&nbsp;<code>2</code>&nbsp;is the second player in the row, etc.).</p>



<p>The tournament consists of multiple rounds (starting from round number&nbsp;<code>1</code>). In each round, the&nbsp;<code>i<sup>th</sup></code>&nbsp;player from the front of the row competes against the&nbsp;<code>i<sup>th</sup></code>&nbsp;player from the end of the row, and the winner advances to the next round. When the number of players is odd for the current round, the player in the middle automatically advances to the next round.</p>



<ul><li>For example, if the row consists of players&nbsp;<code>1, 2, 4, 6, 7</code><ul><li>Player&nbsp;<code>1</code>&nbsp;competes against player&nbsp;<code>7</code>.</li><li>Player&nbsp;<code>2</code>&nbsp;competes against player&nbsp;<code>6</code>.</li><li>Player&nbsp;<code>4</code>&nbsp;automatically advances to the next round.</li></ul></li></ul>



<p>After each round is over, the winners are lined back up in the row based on the&nbsp;<strong>original ordering</strong>&nbsp;assigned to them initially (ascending order).</p>



<p>The players numbered&nbsp;<code>firstPlayer</code>&nbsp;and&nbsp;<code>secondPlayer</code>&nbsp;are the best in the tournament. They can win against any other player before they compete against each other. If any two other players compete against each other, either of them might win, and thus you may&nbsp;<strong>choose</strong>&nbsp;the outcome of this round.</p>



<p>Given the integers&nbsp;<code>n</code>,&nbsp;<code>firstPlayer</code>, and&nbsp;<code>secondPlayer</code>, return&nbsp;<em>an integer array containing two values, the&nbsp;<strong>earliest</strong>&nbsp;possible round number and the&nbsp;<strong>latest</strong>&nbsp;possible round number in which these two players will compete against each other, respectively</em>.</p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> n = 11, firstPlayer = 2, secondPlayer = 4
<strong>Output:</strong> [3,4]
<strong>Explanation:</strong>
One possible scenario which leads to the earliest round number:
First round: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
Second round: 2, 3, 4, 5, 6, 11
Third round: 2, 3, 4
One possible scenario which leads to the latest round number:
First round: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
Second round: 1, 2, 3, 4, 5, 6
Third round: 1, 2, 4
Fourth round: 2, 4
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> n = 5, firstPlayer = 1, secondPlayer = 5
<strong>Output:</strong> [1,1]
<strong>Explanation:</strong> The players numbered 1 and 5 compete in the first round.
There is no way to make them compete in any other round.
</pre>



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



<ul><li><code>2 &lt;= n &lt;= 28</code></li><li><code>1 &lt;= firstPlayer &lt; secondPlayer &lt;= n</code></li></ul>



<h2><strong>Solution 1: Simulation using recursion</strong></h2>



<p>All possible paths, <br>Time complexity: O(n<sup>2</sup>*2<sup>n</sup>)<br>Space complexity: O(logn)</p>



<p>dfs(s, i, j, d) := let i battle with j at round d, given s (binary mask of dead players).</p>



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

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  vector&lt;int&gt; earliestAndLatest(int n, int a, int b) {
    vector&lt;int&gt; ans{INT_MAX, INT_MIN};    
    function&lt;void(int, int, int, int)&gt; dfs = [&amp;](int s, int i, int j, int d) {
      while (i &lt; j &amp;&amp; s &gt;&gt; i &amp; 1) ++i;
      while (i &lt; j &amp;&amp; s &gt;&gt; j &amp; 1) --j;
      if (i &gt;= j) {
        return dfs(s, 1, n, d + 1);
      } else if (i == a &amp;&amp; j == b) {
        ans[0] = min(ans[0], d);
        ans[1] = max(ans[1], d);
      } else {
        if (i != a &amp;&amp; i != b)
          dfs(s | (1 &lt;&lt; i), i + 1, j - 1, d);
        if (j != a &amp;&amp; j != b)
          dfs(s | (1 &lt;&lt; j), i + 1, j - 1, d);
      }
    };
    dfs(0, 1, n, 1);
    return ans;
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/recursion/leetcode-1900-the-earliest-and-latest-rounds-where-players-compete/">花花酱 LeetCode 1900. The Earliest and Latest Rounds Where Players Compete</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/recursion/leetcode-1900-the-earliest-and-latest-rounds-where-players-compete/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1723. Find Minimum Time to Finish All Jobs</title>
		<link>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1723-find-minimum-time-to-finish-all-jobs/</link>
					<comments>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1723-find-minimum-time-to-finish-all-jobs/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 10 Jan 2021 19:30:53 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[all subsets]]></category>
		<category><![CDATA[bitmask]]></category>
		<category><![CDATA[dp]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=7975</guid>

					<description><![CDATA[<p>You are given an integer array&#160;jobs, where&#160;jobs[i]&#160;is the amount of time it takes to complete the&#160;ith&#160;job. There are&#160;k&#160;workers that you can assign jobs to. Each&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1723-find-minimum-time-to-finish-all-jobs/">花花酱 LeetCode 1723. Find Minimum Time to Finish All Jobs</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>You are given an integer array&nbsp;<code>jobs</code>, where&nbsp;<code>jobs[i]</code>&nbsp;is the amount of time it takes to complete the&nbsp;<code>i<sup>th</sup></code>&nbsp;job.</p>



<p>There are&nbsp;<code>k</code>&nbsp;workers that you can assign jobs to. Each job should be assigned to&nbsp;<strong>exactly</strong>&nbsp;one worker. The&nbsp;<strong>working time</strong>&nbsp;of a worker is the sum of the time it takes to complete all jobs assigned to them. Your goal is to devise an optimal assignment such that the&nbsp;<strong>maximum working time</strong>&nbsp;of any worker is&nbsp;<strong>minimized</strong>.</p>



<p><em>Return the&nbsp;<strong>minimum</strong>&nbsp;possible&nbsp;<strong>maximum working time</strong>&nbsp;of any assignment.</em></p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> jobs = [3,2,3], k = 3
<strong>Output:</strong> 3
<strong>Explanation:</strong> By assigning each person one job, the maximum time is 3.
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> jobs = [1,2,4,7,8], k = 2
<strong>Output:</strong> 11
<strong>Explanation:</strong> Assign the jobs the following way:
Worker 1: 1, 2, 8 (working time = 1 + 2 + 8 = 11)
Worker 2: 4, 7 (working time = 4 + 7 = 11)
The maximum working time is 11.</pre>



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



<ul><li><code>1 &lt;= k &lt;= jobs.length &lt;= 12</code></li><li><code>1 &lt;= jobs[i] &lt;= 10<sup>7</sup></code></li></ul>



<h2><strong>Solution 1: All subsets</strong></h2>



<p>dp[i][t] := min of max working time by assigning a subset of jobs s to the first i workers.</p>



<p>dp[i][t] = min{max(dp[i &#8211; 1][s], cost[s ^ t])} where s is a subset of t.</p>



<p>Time complexity: O(k*3^n)<br>Space complexity: O(k*2^n)</p>



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

<pre class="crayon-plain-tag">// Author: Huahua
// Author: Huahua
class Solution {
public:
  int minimumTimeRequired(vector&lt;int&gt;&amp; jobs, int k) {    
    const int n = jobs.size();
    int dp[13][4096];
    memset(dp, 0x7f, sizeof(dp));
    dp[0][0] = 0;
    
    vector&lt;int&gt; cost(1 &lt;&lt; n);
    for (int t = 0; t &lt; 1 &lt;&lt; n; ++t) {
      for (int j = 0; j &lt; n; ++j)
        if (t &gt;&gt; j &amp; 1) cost[t] += jobs[j];
      dp[1][t] = cost[t]; // do jobs t by one worker
    }
    
    for (int i = 2; i &lt;= k; ++i)
      for (int t = 0; t &lt; 1 &lt;&lt; n; ++t)
        for (int s = t; s; s = (s - 1) &amp; t)
          dp[i][t] = min(dp[i][t], max(dp[i - 1][s], cost[t ^ s]));
    return dp[k][(1 &lt;&lt; n) - 1];
  }
};</pre>
</div></div>



<h2><strong>Solution 2: Search + Pruning</strong></h2>



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



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

<pre class="crayon-plain-tag">class Solution {
public:
  int minimumTimeRequired(vector&lt;int&gt;&amp; jobs, int k) {
    vector&lt;int&gt; times(k);
    int ans = INT_MAX;
    function&lt;void(int, int)&gt; dfs = [&amp;](int i, int cur) {
      if (cur &gt;= ans) return;
      if (i == jobs.size()) {
        ans = cur;
        return;
      }
      unordered_set&lt;int&gt; seen;
      for (int j = 0; j &lt; k; ++j) {
        if (!seen.insert(times[j]).second) continue;
        times[j] += jobs[i];
        dfs(i + 1, max(cur, times[j]));
        times[j] -= jobs[i];
      }
    };
    sort(rbegin(jobs), rend(jobs));
    dfs(0, 0);
    return ans;
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1723-find-minimum-time-to-finish-all-jobs/">花花酱 LeetCode 1723. Find Minimum Time to Finish All Jobs</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1723-find-minimum-time-to-finish-all-jobs/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1681. Minimum Incompatibility</title>
		<link>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1681-minimum-incompatibility/</link>
					<comments>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1681-minimum-incompatibility/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Mon, 07 Dec 2020 03:35:28 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[bitmask]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[TSP]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=7777</guid>

					<description><![CDATA[<p>You are given an integer array&#160;nums​​​ and an integer&#160;k. You are asked to distribute this array into&#160;k&#160;subsets of&#160;equal size&#160;such that there are no two equal&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1681-minimum-incompatibility/">花花酱 LeetCode 1681. Minimum Incompatibility</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="花花酱 LeetCode 1681. Minimum Incompatibility - 刷题找工作 EP374" width="500" height="281" src="https://www.youtube.com/embed/03KwgvDgxKg?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<p>You are given an integer array&nbsp;<code>nums</code>​​​ and an integer&nbsp;<code>k</code>. You are asked to distribute this array into&nbsp;<code>k</code>&nbsp;subsets of&nbsp;<strong>equal size</strong>&nbsp;such that there are no two equal elements in the same subset.</p>



<p>A subset&#8217;s&nbsp;<strong>incompatibility</strong>&nbsp;is the difference between the maximum and minimum elements in that array.</p>



<p>Return&nbsp;<em>the&nbsp;<strong>minimum possible sum of incompatibilities</strong>&nbsp;of the&nbsp;</em><code>k</code>&nbsp;<em>subsets after distributing the array optimally, or return&nbsp;</em><code>-1</code><em>&nbsp;if it is not possible.</em></p>



<p>A subset is a group integers that appear in the array with no particular order.</p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [1,2,1,4], k = 2
<strong>Output:</strong> 4
<strong>Explanation:</strong> The optimal distribution of subsets is [1,2] and [1,4].
The incompatibility is (2-1) + (4-1) = 4.
Note that [1,1] and [2,4] would result in a smaller sum, but the first subset contains 2 equal elements.</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [6,3,8,1,3,1,2,2], k = 4
<strong>Output:</strong> 6
<strong>Explanation:</strong> The optimal distribution of subsets is [1,2], [2,3], [6,8], and [1,3].
The incompatibility is (2-1) + (3-2) + (8-6) + (3-1) = 6.
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [5,3,3,6,3,3], k = 3
<strong>Output:</strong> -1
<strong>Explanation:</strong> It is impossible to distribute nums into 3 subsets where no two elements are equal in the same subset.
</pre>



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



<ul><li><code>1 &lt;= k &lt;= nums.length &lt;= 16</code></li><li><code>nums.length</code>&nbsp;is divisible by&nbsp;<code>k</code></li><li><code>1 &lt;= nums[i] &lt;= nums.length</code></li></ul>



<h2><strong>Solution: TSP</strong></h2>



<figure class="wp-block-image size-large"><img width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/12/1681-ep374-1.png" alt="" class="wp-image-7781" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/12/1681-ep374-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/12/1681-ep374-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/12/1681-ep374-1-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></figure>



<figure class="wp-block-image size-large"><img width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/12/1681-ep374-2.png" alt="" class="wp-image-7782" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/12/1681-ep374-2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/12/1681-ep374-2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/12/1681-ep374-2-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></figure>



<p>dp[s][i] := min cost to distribute a set of numbers represented as a binary mask s, the last number in the set is the i-th number.</p>



<p>Init: <br>1.dp[*][*] = inf <br>2. dp[1 &lt;&lt;i][i] = 0, cost of selecting a single number is zero.<br><br>Transition: <br>1. dp[s | (1 &lt;&lt; j)][j] = dp[s][i] if s % (n / k) == 0, we start a new group, no extra cost.<br>2. dp[s | (1 &lt;&lt; j)][j] = dp[s][i] + nums[j] &#8211; nums[i] if nums[j] &gt; nums[i]. In the same group, we require the selected numbers are monotonically increasing. Each cost is nums[j] &#8211; nums[i].<br>e.g. 1, 3, 7, 20, cost is (3 &#8211; 1) + (7 &#8211; 3) + (20 &#8211; 7) = 20 &#8211; 1 = 19.</p>



<p>Ans: min(dp[(1 &lt;&lt; n) &#8211; 1])</p>



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



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

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  int minimumIncompatibility(vector&lt;int&gt;&amp; nums, int k) {
    const int n = nums.size(); 
    const int c = n / k;
    int dp[1 &lt;&lt; 16][16];
    memset(dp, 0x7f, sizeof(dp));
    for (int i = 0; i &lt; n; ++i) dp[1 &lt;&lt; i][i] = 0;
    for (int s = 0; s &lt; 1 &lt;&lt; n; ++s)
      for (int i = 0; i &lt; n; ++i) {
        if ((s &amp; (1 &lt;&lt; i)) == 0) continue;
        for (int j = 0; j &lt; n; ++j) {
          if ((s &amp; (1 &lt;&lt; j))) continue;
          const int t = s | (1 &lt;&lt; j);
          if (__builtin_popcount(s) % c == 0) {
            dp[t][j] = min(dp[t][j], dp[s][i]);
          } else if (nums[j] &gt; nums[i]) {           
            dp[t][j] = min(dp[t][j], 
                           dp[s][i] + nums[j] - nums[i]);            
          }
        }        
    }
    int ans = *min_element(begin(dp[(1 &lt;&lt; n) - 1]), 
                           end(dp[(1 &lt;&lt; n) - 1]));
    return ans &gt; 1e9 ? - 1 : ans;
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1681-minimum-incompatibility/">花花酱 LeetCode 1681. Minimum Incompatibility</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1681-minimum-incompatibility/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1655. Distribute Repeating Integers</title>
		<link>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1655-distribute-repeating-integers/</link>
					<comments>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1655-distribute-repeating-integers/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sat, 14 Nov 2020 20:21:41 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[bitmask]]></category>
		<category><![CDATA[DFS]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[search]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=7655</guid>

					<description><![CDATA[<p>You are given an array of&#160;n&#160;integers,&#160;nums, where there are at most&#160;50&#160;unique values in the array. You are also given an array of&#160;m&#160;customer order quantities,&#160;quantity, where&#160;quantity[i]&#160;is&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1655-distribute-repeating-integers/">花花酱 LeetCode 1655. Distribute Repeating Integers</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>You are given an array of&nbsp;<code>n</code>&nbsp;integers,&nbsp;<code>nums</code>, where there are at most&nbsp;<code>50</code>&nbsp;unique values in the array. You are also given an array of&nbsp;<code>m</code>&nbsp;customer order quantities,&nbsp;<code>quantity</code>, where&nbsp;<code>quantity[i]</code>&nbsp;is the amount of integers the&nbsp;<code>i<sup>th</sup></code>&nbsp;customer ordered. Determine if it is possible to distribute&nbsp;<code>nums</code>&nbsp;such that:</p>



<ul><li>The&nbsp;<code>i<sup>th</sup></code>&nbsp;customer gets&nbsp;<strong>exactly</strong>&nbsp;<code>quantity[i]</code>&nbsp;integers,</li><li>The integers the&nbsp;<code>i<sup>th</sup></code>&nbsp;customer gets are&nbsp;<strong>all equal</strong>, and</li><li>Every customer is satisfied.</li></ul>



<p>Return&nbsp;<code>true</code><em>&nbsp;if it is possible to distribute&nbsp;</em><code>nums</code><em>&nbsp;according to the above conditions</em>.</p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [1,2,3,4], quantity = [2]
<strong>Output:</strong> false
<strong>Explanation:</strong> The 0th customer cannot be given two different integers.
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [1,2,3,3], quantity = [2]
<strong>Output:</strong> true
<strong>Explanation:</strong> The 0th customer is given [3,3]. The integers [1,2] are not used.
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [1,1,2,2], quantity = [2,2]
<strong>Output:</strong> true
<strong>Explanation:</strong> The 0th customer is given [1,1], and the 1st customer is given [2,2].
</pre>



<p><strong>Example 4:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [1,1,2,3], quantity = [2,2]
<strong>Output:</strong> false
<strong>Explanation:</strong> Although the 0th customer could be given [1,1], the 1st customer cannot be satisfied.</pre>



<p><strong>Example 5:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [1,1,1,1,1], quantity = [2,3]
<strong>Output:</strong> true
<strong>Explanation:</strong> The 0th customer is given [1,1], and the 1st customer is given [1,1,1].
</pre>



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



<ul><li><code>n == nums.length</code></li><li><code>1 &lt;= n &lt;= 10<sup>5</sup></code></li><li><code>1 &lt;= nums[i] &lt;= 1000</code></li><li><code>m == quantity.length</code></li><li><code>1 &lt;= m &lt;= 10</code></li><li><code>1 &lt;= quantity[i] &lt;= 10<sup>5</sup></code></li><li>There are at most&nbsp;<code>50</code>&nbsp;unique values in&nbsp;<code>nums</code>.</li></ul>



<h2><strong>Solution1: Backtracking</strong></h2>



<p>Time complexity: O(|vals|^m) <br>Space complexity: O(|vals| + m)</p>



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

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  bool canDistribute(vector&lt;int&gt;&amp; nums, vector&lt;int&gt;&amp; quantity) {
    unordered_map&lt;int, int&gt; m;
    for (int x : nums) ++m[x];
    vector&lt;int&gt; cnt;
    for (const auto&amp; [x, c] : m) cnt.push_back(c);
    
    const int q = quantity.size();
    const int n = cnt.size();
    function&lt;bool(int)&gt; dfs = [&amp;](int d) {
      if (d == q) return true;
      for (int i = 0; i &lt; n; ++i) 
        if (cnt[i] &gt;= quantity[d]) {
          cnt[i] -= quantity[d];
          if (dfs(d + 1)) return true;
          cnt[i] += quantity[d];
        }
      return false;
    };
    
    sort(rbegin(cnt), rend(cnt));
    sort(rbegin(quantity), rend(quantity));
    
    return dfs(0);
  }
};</pre>
</div></div>



<h2><strong>Solution 2: Bitmask + all subsets</strong></h2>



<p>dp(mask, i) := whether we can distribute to a subset of customers represented as a bit mask, using the i-th to (n-1)-th numbers.</p>



<p>Time complexity: O(2^m * m * |vals|) = O(2^10 * 10 * 50)<br>Space complexity: O(2^m * |vals|)</p>



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

<pre class="crayon-plain-tag">class Solution {
public:
  bool canDistribute(vector&lt;int&gt;&amp; nums, vector&lt;int&gt;&amp; quantity) {
    vector&lt;int&gt; cnt;
    unordered_map&lt;int, int&gt; freq;
    for (int x : nums) ++freq[x]; 
    for (const auto&amp; [x, f] : freq) cnt.push_back(f);
    
    const int n = cnt.size();
    const int m = quantity.size();        
    
    vector&lt;vector&lt;optional&lt;bool&gt;&gt;&gt; cache(1 &lt;&lt; m, vector&lt;optional&lt;bool&gt;&gt;(n));
    
    vector&lt;int&gt; sums(1 &lt;&lt; m);
    for (int mask = 0; mask &lt; 1 &lt;&lt; m; ++mask)
      for (int i = 0; i &lt; m; ++i)
        if (mask &amp; (1 &lt;&lt; i))
          sums[mask] += quantity[i];
    
    function&lt;bool(int, int)&gt; dp = [&amp;](int mask, int i) -&gt; bool {
      if (mask == 0) return true;
      if (i == n) return false;
      
      auto&amp; ans = cache[mask][i];
      
      if (ans.has_value()) return ans.value();
      
      int cur = mask;
      while (cur) {
        if (sums[cur] &lt;= cnt[i] &amp;&amp; dp(mask ^ cur, i + 1)) {
          ans = true;
          return true;
        }
        cur = (cur - 1) &amp; mask;
      }
      
      ans = dp(mask, i + 1);
      return ans.value();
    };
    
    return dp((1 &lt;&lt; m) - 1, 0);
  }
};</pre>

</div><h2 class="tabtitle">Python3</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag"># Author: Huahua
class Solution:
  def canDistribute(self, nums: List[int], 
                    quantity: List[int]) -&gt; bool:    
    cnts = list(Counter(nums).values())
    m = len(quantity)
    n = len(cnts)
    sums = [0] * (1 &lt;&lt; m)
    for mask in range(1 &lt;&lt; m):
      for i in range(m):
        if mask &amp; (1 &lt;&lt; i): sums[mask] += quantity[i]
    
    @lru_cache(None)
    def dp(mask: int, i: int) -&gt; bool:
      if not mask: return True
      if i &lt; 0: return False
      
      cur = mask
      while cur:
        if sums[cur] &lt;= cnts[i] and dp(mask ^ cur, i - 1):
          return True
        cur = (cur - 1) &amp; mask
      
      return dp(mask, i - 1)
    
    return dp((1 &lt;&lt; m) - 1, n - 1)</pre>
</div></div>



<p>Bottom up:</p>



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

<pre class="crayon-plain-tag">class Solution {
public:
  bool canDistribute(vector&lt;int&gt;&amp; nums, vector&lt;int&gt;&amp; quantity) {
    vector&lt;int&gt; cnt;
    unordered_map&lt;int, int&gt; freq;
    for (int x : nums) ++freq[x]; 
    for (const auto&amp; [x, f] : freq) cnt.push_back(f);
    
    const int n = cnt.size();
    const int m = quantity.size();            
    
    vector&lt;int&gt; sums(1 &lt;&lt; m);
    for (int mask = 0; mask &lt; 1 &lt;&lt; m; ++mask)
      for (int i = 0; i &lt; m; ++i)
        if (mask &amp; (1 &lt;&lt; i))
          sums[mask] += quantity[i];
    
    // dp[mask][i] := use first i types to satisfy mask customers.
    vector&lt;vector&lt;int&gt;&gt; dp(1 &lt;&lt; m, vector&lt;int&gt;(n + 1));
    dp[0][0] = 1;    
    for (int mask = 0; mask &lt; 1 &lt;&lt; m; ++mask)
      for (int i = 0; i &lt; n; ++i) {
        dp[mask][i + 1] |= dp[mask][i];
        for (int cur = mask; cur; cur = (cur - 1) &amp; mask)
          if (sums[cur] &lt;= cnt[i] &amp;&amp; dp[mask ^ cur][i])
            dp[mask][i + 1] = 1;
      }
    
    return dp[(1 &lt;&lt; m) - 1][n];
  }
};</pre>
</div></div>



<p></p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1655-distribute-repeating-integers/">花花酱 LeetCode 1655. Distribute Repeating Integers</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1655-distribute-repeating-integers/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1595. Minimum Cost to Connect Two Groups of Points</title>
		<link>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1595-minimum-cost-to-connect-two-groups-of-points/</link>
					<comments>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1595-minimum-cost-to-connect-two-groups-of-points/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Wed, 23 Sep 2020 08:37:56 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[bitmask]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[hard]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=7411</guid>

					<description><![CDATA[<p>You are given two groups of points&#160;where the first group&#160;has&#160;size1&#160;points,&#160;the second group&#160;has&#160;size2&#160;points,&#160;and&#160;size1&#160;&#62;=&#160;size2. The&#160;cost&#160;of the connection between any two points&#160;are given in an&#160;size1&#160;x&#160;size2&#160;matrix where&#160;cost[i][j]&#160;is the cost&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1595-minimum-cost-to-connect-two-groups-of-points/">花花酱 LeetCode 1595. Minimum Cost to Connect Two Groups of Points</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="花花酱 LeetCode 1595. Minimum Cost to Connect Two Groups of Points - 刷题找工作 EP358" width="500" height="281" src="https://www.youtube.com/embed/ba-3-B4IMII?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<p>You are given two groups of points&nbsp;where the first group&nbsp;has&nbsp;<code>size<sub>1</sub></code>&nbsp;points,&nbsp;the second group&nbsp;has&nbsp;<code>size<sub>2</sub></code>&nbsp;points,&nbsp;and&nbsp;<code>size<sub>1</sub>&nbsp;&gt;=&nbsp;size<sub>2</sub></code>.</p>



<p>The&nbsp;<code>cost</code>&nbsp;of the connection between any two points&nbsp;are given in an&nbsp;<code>size<sub>1</sub>&nbsp;x&nbsp;size<sub>2</sub></code>&nbsp;matrix where&nbsp;<code>cost[i][j]</code>&nbsp;is the cost of connecting point&nbsp;<code>i</code>&nbsp;of the first group and point&nbsp;<code>j</code>&nbsp;of the second group. The groups are connected if&nbsp;<strong>each point in both&nbsp;groups is&nbsp;connected to one or more points in the opposite&nbsp;group</strong>. In other words, each&nbsp;point in the first group must be connected to at least one point in the second group, and each&nbsp;point in the second group must be connected to at least one point in the first group.</p>



<p>Return&nbsp;<em>the minimum cost it takes to connect the two groups</em>.</p>



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



<figure class="wp-block-image"><img src="https://assets.leetcode.com/uploads/2020/09/03/ex1.jpg" alt=""/></figure>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> cost = [[15, 96], [36, 2]]
<strong>Output:</strong> 17
<strong>Explanation</strong>: The optimal way of connecting the groups is:
1--A
2--B
This results in a total cost of 17.
</pre>



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



<figure class="wp-block-image"><img src="https://assets.leetcode.com/uploads/2020/09/03/ex2.jpg" alt=""/></figure>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> cost = [[1, 3, 5], [4, 1, 1], [1, 5, 3]]
<strong>Output:</strong> 4
<strong>Explanation</strong>: The optimal way of connecting the groups is:
1--A
2--B
2--C
3--A
This results in a total cost of 4.
Note that there are multiple points connected to point 2 in the first group and point A in the second group. This does not matter as there is no limit to the number of points that can be connected. We only care about the minimum total cost.
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> cost = [[2, 5, 1], [3, 4, 7], [8, 1, 2], [6, 2, 4], [3, 8, 8]]
<strong>Output:</strong> 10
</pre>



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



<ul><li><code>size<sub>1</sub>&nbsp;== cost.length</code></li><li><code>size<sub>2</sub>&nbsp;== cost[i].length</code></li><li><code>1 &lt;=&nbsp;size<sub>1</sub>,&nbsp;size<sub>2</sub>&nbsp;&lt;= 12</code></li><li><code>size<sub>1</sub>&nbsp;&gt;=&nbsp;size<sub>2</sub></code></li><li><code>0 &lt;= cost[i][j] &lt;= 100</code></li></ul>



<h2><strong>Solution 1: Bistmask DP</strong></h2>



<figure class="wp-block-image size-large"><img width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/09/1595-ep358-1.png" alt="" class="wp-image-7414" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/09/1595-ep358-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/09/1595-ep358-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/09/1595-ep358-1-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></figure>



<figure class="wp-block-image size-large"><img width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/09/1595-ep358-2.png" alt="" class="wp-image-7415" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/09/1595-ep358-2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/09/1595-ep358-2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/09/1595-ep358-2-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></figure>



<p>dp[i][s] := min cost to connect first i (1-based) points in group1 and a set of points (represented by a bitmask s) in group2.</p>



<p>ans = dp[m][1 &lt;&lt; n &#8211; 1]</p>



<p>dp[i][s | (1 &lt;&lt; j)] := min(dp[i][s] + cost[i][j], dp[i-1][s] + cost[i][j])</p>



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



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

<pre class="crayon-plain-tag">class Solution {
public:
  int connectTwoGroups(vector&lt;vector&lt;int&gt;&gt;&amp; cost) {
    constexpr int kInf = 1e9;
    const int m = cost.size();
    const int n = cost[0].size();
    // dp[i][s] := min cost to connect first i points in group1 
    // and points (bitmask s) in group2.
    vector&lt;vector&lt;int&gt;&gt; dp(m + 1, vector&lt;int&gt;(1 &lt;&lt; n, kInf));
    dp[0][0] = 0;
    for (int i = 0; i &lt; m; ++i)
      for (int j = 0; j &lt; n; ++j)
        for (int s = 0; s &lt; 1 &lt;&lt; n; ++s)
          dp[i + 1][s | (1 &lt;&lt; j)] = min({dp[i + 1][s | (1 &lt;&lt; j)], 
                                         dp[i + 1][s] + cost[i][j],
                                         dp[i][s] + cost[i][j]});
    return dp[m].back();
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1595-minimum-cost-to-connect-two-groups-of-points/">花花酱 LeetCode 1595. Minimum Cost to Connect Two Groups of Points</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1595-minimum-cost-to-connect-two-groups-of-points/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1542. Find Longest Awesome Substring</title>
		<link>https://zxi.mytechroad.com/blog/hashtable/leetcode-1542-find-longest-awesome-substring/</link>
					<comments>https://zxi.mytechroad.com/blog/hashtable/leetcode-1542-find-longest-awesome-substring/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Mon, 10 Aug 2020 07:34:23 +0000</pubDate>
				<category><![CDATA[Hashtable]]></category>
		<category><![CDATA[bitmask]]></category>
		<category><![CDATA[hashtable]]></category>
		<category><![CDATA[prefix]]></category>
		<category><![CDATA[xor]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=7222</guid>

					<description><![CDATA[<p>Given a string&#160;s. An&#160;awesome&#160;substring is a non-empty substring of&#160;s&#160;such that we can make any number of swaps in order to make it palindrome. Return the&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/hashtable/leetcode-1542-find-longest-awesome-substring/">花花酱 LeetCode 1542. Find Longest Awesome Substring</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="花花酱 LeetCode 1542. Find Longest Awesome Substring - 刷题找工作 EP349" width="500" height="281" src="https://www.youtube.com/embed/b0oxAd94FOg?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<p>Given a string&nbsp;<code>s</code>. An&nbsp;<em>awesome</em>&nbsp;substring is a non-empty substring of&nbsp;<code>s</code>&nbsp;such that we can make any number of swaps in order to make it palindrome.</p>



<p>Return the length of the maximum length&nbsp;<strong>awesome substring</strong>&nbsp;of&nbsp;<code>s</code>.</p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> s = "3242415"
<strong>Output:</strong> 5
<strong>Explanation:</strong> "24241" is the longest awesome substring, we can form the palindrome "24142" with some swaps.
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> s = "12345678"
<strong>Output:</strong> 1
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> s = "213123"
<strong>Output:</strong> 6
<strong>Explanation:</strong> "213123" is the longest awesome substring, we can form the palindrome "231132" with some swaps.
</pre>



<p><strong>Example 4:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> s = "00"
<strong>Output:</strong> 2
</pre>



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



<ul><li><code>1 &lt;= s.length &lt;= 10^5</code></li><li><code>s</code>&nbsp;consists only of digits.</li></ul>



<h2><strong>Solution: Prefix mask + Hashtable</strong></h2>



<figure class="wp-block-image size-large"><img width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/08/1542-ep349.png" alt="" class="wp-image-7233" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/08/1542-ep349.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/08/1542-ep349-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/08/1542-ep349-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></figure>



<figure class="wp-block-image size-large"><img width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/08/1542-ep349-2.png" alt="" class="wp-image-7234" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/08/1542-ep349-2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/08/1542-ep349-2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/08/1542-ep349-2-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></figure>



<p>For a palindrome all digits must occurred even times expect one. We can use a 10 bit mask to track the occurrence of each digit for prefix s[0~i]. 0 is even, 1 is odd.</p>



<p>We use a hashtable to track the <strong>first index</strong> of each prefix state.<br>If s[0~i] and s[0~j] have the same state which means every digits in s[i+1~j] occurred even times (zero is also even) and it&#8217;s an awesome string. Then (j &#8211; (i+1)  + 1) = j &#8211; i is the length of the palindrome. So far so good.</p>



<p>But we still need to consider the case when there is a digit with odd occurrence. We can enumerate all possible ones from 0 to 9, and temporarily flip the bit of the digit and see whether that state happened before. </p>



<p>fisrt_index[0] = -1, first_index[*] = inf<br>ans = max(ans, j &#8211; first_index[mask])</p>



<p>Time complexity: O(n)<br>Space complexity: O(2^10) = O(1)</p>



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

<pre class="crayon-plain-tag">class Solution {
public:
  int longestAwesome(string s) {
    constexpr int kInf = 1e9;
    vector&lt;int&gt; idx(1024, kInf);
    idx[0] = -1;
    int mask = 0; // prefix's state 0:even, 1:odd
    int ans = 0;
    for (int i = 0; i &lt; s.length(); ++i) {
      mask ^= (1 &lt;&lt; (s[i] - '0'));
      ans = max(ans, i - idx[mask]);
      // One digit with odd count is allowed.
      for (int j = 0; j &lt; 10; ++j)
        ans = max(ans, i - idx[mask ^ (1 &lt;&lt; j)]);
      idx[mask] = min(idx[mask], i);
    }
    return ans;
  }
};</pre>

</div><h2 class="tabtitle">Java</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
  public int longestAwesome(String s) {
    final int n = s.length();
    int[] idx = new int[1024];
    Arrays.fill(idx, n);
    idx[0] = -1;
    int mask = 0;
    int ans = 0;
    for (int i = 0; i &lt; n; ++i) {
      mask ^= (1 &lt;&lt; (s.charAt(i) - '0'));
      ans = Math.max(ans, i - idx[mask]);      
      for (int j = 0; j &lt; 10; ++j)
        ans = Math.max(ans, 
                       i - idx[mask ^ (1 &lt;&lt; j)]);
      idx[mask] = Math.min(idx[mask], i);
    }
    return ans;
  }
}</pre>

</div><h2 class="tabtitle">Python3</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag"># Author: Huahua
class Solution:
  def longestAwesome(self, s: str) -&gt; int:  
    idx = [-1] + [len(s)] * 1023
    ans, mask = 0, 0
    for i, c in enumerate(s):
      mask ^= 1 &lt;&lt; (ord(c) - ord('0'))
      ans = max([ans, i - idx[mask]]
                + [i - idx[mask ^ (1 &lt;&lt; j)] for j in range(10)])
      idx[mask] = min(idx[mask], i)
    return ans</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/hashtable/leetcode-1542-find-longest-awesome-substring/">花花酱 LeetCode 1542. Find Longest Awesome Substring</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/hashtable/leetcode-1542-find-longest-awesome-substring/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1494. Parallel Courses II</title>
		<link>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1494-parallel-courses-ii/</link>
					<comments>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1494-parallel-courses-ii/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 28 Jun 2020 05:41:08 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[bitmask]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[NP]]></category>
		<category><![CDATA[state compression]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=6982</guid>

					<description><![CDATA[<p>Given the integer&#160;n&#160;representing the number of courses at some university labeled from&#160;1&#160;to&#160;n, and the array&#160;dependencies&#160;where&#160;dependencies[i] = [xi, yi]&#160;&#160;represents a prerequisite relationship, that is, the course&#160;xi&#160;must&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1494-parallel-courses-ii/">花花酱 LeetCode 1494. Parallel Courses II</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Given the integer&nbsp;<code>n</code>&nbsp;representing the number of courses at some university labeled from&nbsp;<code>1</code>&nbsp;to&nbsp;<code>n</code>, and the array&nbsp;<code>dependencies</code>&nbsp;where&nbsp;<code>dependencies[i] = [x<sub>i</sub>, y<sub>i</sub>]</code>&nbsp;&nbsp;represents a prerequisite relationship, that is, the course&nbsp;<code>x<sub>i</sub></code>&nbsp;must be taken before the course&nbsp;<code>y<sub>i</sub></code>. &nbsp;Also, you are given the&nbsp;integer&nbsp;<code>k</code>.</p>



<p>In one semester you can take&nbsp;<strong>at most</strong>&nbsp;<code>k</code>&nbsp;courses as long as you have taken all the prerequisites for the courses you are taking.</p>



<p><em>Return the minimum number of semesters to take all courses</em>.&nbsp;It is guaranteed that you can take all courses in some way.</p>



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



<figure class="wp-block-image"><img src="https://assets.leetcode.com/uploads/2020/05/22/leetcode_parallel_courses_1.png" alt=""/></figure>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> n = 4, dependencies = [[2,1],[3,1],[1,4]], k = 2
<strong>Output:</strong> 3 
<strong>Explanation:</strong> The figure above represents the given graph. In this case we can take courses 2 and 3 in the first semester, then take course 1 in the second semester and finally take course 4 in the third semester.
</pre>



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



<figure class="wp-block-image"><img src="https://assets.leetcode.com/uploads/2020/05/22/leetcode_parallel_courses_2.png" alt=""/></figure>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> n = 5, dependencies = [[2,1],[3,1],[4,1],[1,5]], k = 2
<strong>Output:</strong> 4 
<strong>Explanation:</strong> The figure above represents the given graph. In this case one optimal way to take all courses is: take courses 2 and 3 in the first semester and take course 4 in the second semester, then take course 1 in the third semester and finally take course 5 in the fourth semester.
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> n = 11, dependencies = [], k = 2
<strong>Output:</strong> 6
</pre>



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



<ul><li><code>1 &lt;= n &lt;= 15</code></li><li><code>1 &lt;= k &lt;= n</code></li><li><code>0 &lt;=&nbsp;dependencies.length &lt;= n * (n-1) / 2</code></li><li><code>dependencies[i].length == 2</code></li><li><code>1 &lt;= x<sub>i</sub>, y<sub>i</sub>&nbsp;&lt;= n</code></li><li><code>x<sub>i</sub>&nbsp;!= y<sub>i</sub></code></li><li>All prerequisite relationships are distinct, that is,&nbsp;<code>dependencies[i] != dependencies[j]</code>.</li><li>The given graph is a directed acyclic graph.</li></ul>



<h2><strong>Solution: DP</strong> <strong>/ Bitmask</strong></h2>



<p>NOTE: This is a NP problem, any polynomial-time algorithm is incorrect otherwise P = NP.</p>



<p>Variant 1:<br>dp[m] := whether state m is reachable, where m is the bitmask of courses studied.<br>For each semester, we enumerate all possible states from 0 to 2^n &#8211; 1, if that state is reachable, then we choose c (c &lt;= k) courses from n and check whether we can study those courses.<br>If we can study those courses, we have a new reachable state, we set dp[m | courses] = true.</p>



<p>Time complexity: O(n*2^n*2^n) = O(n*n^4) &lt;&#8211; This will be much smaller in practice.<br>and can be reduced to O(n*3^n).<br>Space complexity: O(2^n)</p>



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

<pre class="crayon-plain-tag">// Author: Huahua, 52 ms, 14.5 MB
class Solution {
public:
  int minNumberOfSemesters(int n, vector&lt;vector&lt;int&gt;&gt;&amp; dependencies, int k) {    
    const int S = 1 &lt;&lt; n;
    vector&lt;int&gt; deps(n); // deps[i] = dependency mask for course i.
    for (const auto&amp; d : dependencies)
      deps[d[1] - 1] |= 1 &lt;&lt; (d[0] - 1);    
    // dp(i)[s] := reachable(s) at semester i.
    vector&lt;int&gt; dp(S);
    dp[0] = 1;
    for (int d = 1; d &lt;= n; ++d) { // at most n semesters.
      vector&lt;int&gt; tmp(S); // start a new semesters.
      for (int s = 0; s &lt; S; ++s) {
        if (!dp[s]) continue; // not a reachable state.
        int mask = 0;
        for (int i = 0; i &lt; n; ++i)
          if (!(s &amp; (1 &lt;&lt; i)) &amp;&amp; (s &amp; deps[i]) == deps[i]) 
            mask |= (1 &lt;&lt; i);
        // Prunning, take all.
        if (__builtin_popcount(mask) &lt;= k) {
          tmp[s | mask] = 1;         
        } else {
          // Try all subsets. 
          for (int c = mask; c; c = (c - 1) &amp; mask)
            if (__builtin_popcount(c) &lt;= k) {
              tmp[s | c] = 1;
            }
        }
        if (tmp.back()) return d;
      }
      dp.swap(tmp);      
    }
    return -1;
  }
};</pre>
</div></div>



<p>Variant 2:<br>dp[m] := min semesters to reach state m.<br>dp[m | c] = min{dp[m | c], dp[m] + 1}, if we can reach m | c from m.<br>This allows us to get rid of enumerate n semesters.<br>Time complexity: O(2^n*2^n) &lt;&#8211; This will be much smaller in practice.<br>and can be reduced to O(3^n).<br>Space complexity: O(2^n)</p>



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

<pre class="crayon-plain-tag">// Author: Huahua, 16 ms, 8.5 MB
class Solution {
public:
  int minNumberOfSemesters(int n, vector&lt;vector&lt;int&gt;&gt;&amp; dependencies, int k) {
    const int kInf = 1e9;
    const int S = 1 &lt;&lt; n;
    vector&lt;int&gt; deps(n); // deps[i] = dependency mask for course i.
    for (const auto&amp; d : dependencies)
      deps[d[1] - 1] |= 1 &lt;&lt; (d[0] - 1);    
    // dp[m] := min semesters to reach state m.
    vector&lt;int&gt; dp(S, kInf);
    dp[0] = 0;
    for (int s = 0; s &lt; S; ++s) {
      if (dp[s] == kInf) continue; // not reachable.
      // Generate a mask of courses we can study under state s.
      int mask = 0;
      for (int i = 0; i &lt; n; ++i)
        if (!(s &amp; (1 &lt;&lt; i)) &amp;&amp; (s &amp; deps[i]) == deps[i])
          mask |= (1 &lt;&lt; i);
      // Prunning, take all.
      if (__builtin_popcount(mask) &lt;= k) {
        dp[s | mask] = min(dp[s | mask], dp[s] + 1);       
      } else {
        // Try all subsets.
        for (int c = mask; c; c = (c - 1) &amp; mask)
          if (__builtin_popcount(c) &lt;= k)
            dp[s | c] = min(dp[s | c], dp[s] + 1);
      }
      // Early termination?
      if (dp.back() != kInf) return dp.back();
    }
    return dp.back();
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1494-parallel-courses-ii/">花花酱 LeetCode 1494. Parallel Courses II</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1494-parallel-courses-ii/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
