<?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>subset &#8211; Huahua&#8217;s Tech Road</title>
	<atom:link href="https://zxi.mytechroad.com/blog/tag/subset/feed/" rel="self" type="application/rss+xml" />
	<link>https://zxi.mytechroad.com/blog</link>
	<description></description>
	<lastBuildDate>Thu, 10 Apr 2025 14:21:28 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.7.2</generator>

<image>
	<url>https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/cropped-photo-32x32.jpg</url>
	<title>subset &#8211; Huahua&#8217;s Tech Road</title>
	<link>https://zxi.mytechroad.com/blog</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>花花酱 LeetCode 646. Maximum Length of Pair Chain</title>
		<link>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-646-maximum-length-of-pair-chain/</link>
					<comments>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-646-maximum-length-of-pair-chain/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Thu, 10 Apr 2025 05:25:42 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[Greedy]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[greedy]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[proof]]></category>
		<category><![CDATA[subset]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=10301</guid>

					<description><![CDATA[这题我选DP，因为不需要证明，直接干就行了。 方法1: DP 首先还是需要对pairs的right进行排序。一方面是为了方便chaining，另一方面是可以去重。 然后定义 dp[i] := 以pairs[i]作为结尾，最长的序列的长度。 状态转移：dp[i] = max(dp[j] + 1) where pairs[i].left > pairs[j].right and 0 &#60; j &#60; i. 解释：对于pairs[i]，找一个最优的pairs[j]，满足pairs[i].left >&#8230;]]></description>
										<content:encoded><![CDATA[
<p>这题我选DP，因为不需要证明，直接干就行了。</p>



<p>方法1: DP</p>



<p>首先还是需要对pairs的right进行排序。一方面是为了方便chaining，另一方面是可以去重。</p>



<p>然后定义 dp[i] := 以pairs[i]作为结尾，最长的序列的长度。<br><br>状态转移：dp[i] = max(dp[j] + 1) where pairs[i].left > pairs[j].right and 0 &lt; j &lt; i.</p>



<p>解释：对于pairs[i]，找一个最优的pairs[j]，满足pairs[i].left > pairs[j].right，这样我就可以把pairs[i]追加到以pairs[j]结尾的最长序列后面了，长度+1。</p>



<p>边检条件：dp[0:n] = 1，每个pair以自己作为序列的最后元素，长度为1。</p>



<p>时间复杂度：O(n<sup>2</sup>)<br>空间复杂度：O(n)</p>



<pre class="urvanov-syntax-highlighter-plain-tag">class Solution {
public:
  int findLongestChain(vector&lt;vector&lt;int&gt;&gt;&amp; pairs) {
    sort(begin(pairs), end(pairs), [](const auto&amp; p1, const auto&amp; p2){
      return p1[1] &lt; p2[1];
    });

    const int n = pairs.size();

    vector&lt;int&gt; dp(n, 1);
    for (int i = 0; i &lt; n; ++i)
      for (int j = 0; j &lt; i; ++j)
        if (pairs[i][0] &gt; pairs[j][1])
          dp[i] = max(dp[i], dp[j] + 1);

    return *max_element(begin(dp), end(dp));
  }
};</pre>



<p>方法2: 贪心</p>



<p>和DP一样，对数据进行排序。</p>



<p>每当我看到 cur.left > prev.right，那么就直接把cur接在prev后面。我们需要证明这么做是最优的，而不是跳过它选后面的元素。<br><br>Case 0: cur已经是最后一个元素了，跳过就不是最优解了。<br><br>假设cur后面有next, 因为已经排序过了，我们可以得知 next.right >= cur.right。<br><br>Case 1: next.right == cur.right。这时候选cur和选next对后面的决策来说是一样的，但由于Case 0的存在，我必须选cur。<br><br>Case 2: next.right > cur.right。不管left的情况怎么样，由于right更小，这时候选择cur一定是优于next。</p>



<p>综上所述，看到有元素可以连接起来就贪心的选它就对了。</p>



<p>时间复杂度：O(nlogn)<br>空间复杂度：O(1)</p>



<pre class="urvanov-syntax-highlighter-plain-tag">class Solution {
public:
  int findLongestChain(vector&lt;vector&lt;int&gt;&gt;&amp; pairs) {
    sort(begin(pairs), end(pairs), [](const auto&amp; p1, const auto&amp; p2){
      return p1[1] &lt; p2[1];
    });

    int right = INT_MIN;
    int ans = 0;
    for (const auto&amp; p : pairs)
      if (p[0] &gt; right) {
        right = p[1];
        ++ans;
      }
    return ans;
  }
};</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-646-maximum-length-of-pair-chain/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 368. Largest Divisible Subset</title>
		<link>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-368-largest-divisible-subset/</link>
					<comments>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-368-largest-divisible-subset/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sat, 05 Apr 2025 02:17:49 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[sort]]></category>
		<category><![CDATA[subset]]></category>
		<category><![CDATA[unique]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=10266</guid>

					<description><![CDATA[也算是一道比较经典的DP题了，需要找到一个最大的子集，使得其中元素两两的余数为0。 我们假设有一个集合为{a1, a2, a3, &#8230;, an}, {a1 &#60; a2 &#60; &#8230; &#60; an) 如果 a2 % a1 = 0, a3 % a2 == 0, 那么a3&#8230;]]></description>
										<content:encoded><![CDATA[
<p>也算是一道比较经典的DP题了，需要找到一个最大的子集，使得其中元素两两的余数为0。</p>



<p>我们假设有一个集合为{a1, a2, a3, &#8230;, an}, {a1 &lt; a2 &lt; &#8230; &lt; an)</p>



<p>如果 a2 % a1 = 0,  a3 % a2 == 0, 那么a3 % a1 一定也等于0。也就是说a2是a1的倍数，a3是a2的倍数，那么a3一定也是a1的倍数。所以我们并不需要测试任意两个元素之间的余数为0，我们只需要检测a[i]是否为a[i-1]的倍数即可，如果成立，则可以确保a[i]也是a[i-2], a[i-3], &#8230; a[1]的倍数。这样就可以大大降低问题的复杂度。</p>



<p>接下来就需要dp就发挥威力了。我们将原数组排序，用dp[i]来表示以a[i]结尾（集合中的最大值），能够构建的子集的最大长度。</p>



<p>转移方程：dp[j] = max(dp[j], dp[i] + 1) if nums[j] % nums[i] = 0.</p>



<p>这表示，如果nums[j] 是 nums[i]的倍数，那么我们可以把nums[j]加入以nums[i]结尾的最大子集中，构建一个新的最大子集，长度+1。当然对于j，可能有好多个满足条件的i，我们需要找一个最大的。</p>



<p>举个例子：<br>nums = {2, 3, 4, 12}<br>以3结尾的最大子集{3}，长度为1。由于12%3==0，那么我们可以把12追加到{3} 中，构成{3,12}。<br>以4结尾的最大子集是{2,4}，长度为2。由于12%4==0，那么我们可以把12追加到{2,4} 中，构成{2,4,12} 。得到最优解。</p>



<p>这样我们只需要双重循环，枚举i，再枚举j (0 &lt;= i &lt; j)。时间复杂度：O(n^2)。空间复杂度：O(n)。</p>



<p>最后需要输出一个最大子集，如果不记录递推过程，则需要稍微判断一下。</p>



<pre class="urvanov-syntax-highlighter-plain-tag">class Solution {
public:
  vector&lt;int&gt; largestDivisibleSubset(vector&lt;int&gt;&amp; nums) {
    const int n = nums.size();
    sort(begin(nums), end(nums));
    // dp[i] = max size of subset ends with nums[i]
    vector&lt;int&gt; dp(n);
    for (int i = 0; i &lt; n; ++i)
      for (int j = i + 1; j &lt; n; ++j)
        if (nums[j] % nums[i] == 0)
          dp[j] = max(dp[j], dp[i] + 1);
    int s = *max_element(begin(dp), end(dp));
    vector&lt;int&gt; ans;
    for (int i = n - 1; i &gt;= 0; --i) {
      if (dp[i] == s &amp;&amp; (ans.empty() || ans.back() % nums[i] == 0)) {
        ans.push_back(nums[i]);
        --s;
      }
    }
    return ans;
  }
};</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-368-largest-divisible-subset/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2044. Count Number of Maximum Bitwise-OR Subsets</title>
		<link>https://zxi.mytechroad.com/blog/searching/leetcode-2044-count-number-of-maximum-bitwise-or-subsets/</link>
					<comments>https://zxi.mytechroad.com/blog/searching/leetcode-2044-count-number-of-maximum-bitwise-or-subsets/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Mon, 18 Oct 2021 03:54:32 +0000</pubDate>
				<category><![CDATA[Search]]></category>
		<category><![CDATA[combination]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[subset]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=8610</guid>

					<description><![CDATA[Given an integer array&#160;nums, find the&#160;maximum&#160;possible&#160;bitwise OR&#160;of a subset of&#160;nums&#160;and return&#160;the&#160;number of different non-empty subsets&#160;with the maximum bitwise OR. An array&#160;a&#160;is a&#160;subset&#160;of an array&#160;b&#160;if&#160;a&#160;can be&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Given an integer array&nbsp;<code>nums</code>, find the&nbsp;<strong>maximum</strong>&nbsp;possible&nbsp;<strong>bitwise OR</strong>&nbsp;of a subset of&nbsp;<code>nums</code>&nbsp;and return&nbsp;<em>the&nbsp;<strong>number of different non-empty subsets</strong>&nbsp;with the maximum bitwise OR</em>.</p>



<p>An array&nbsp;<code>a</code>&nbsp;is a&nbsp;<strong>subset</strong>&nbsp;of an array&nbsp;<code>b</code>&nbsp;if&nbsp;<code>a</code>&nbsp;can be obtained from&nbsp;<code>b</code>&nbsp;by deleting some (possibly zero) elements of&nbsp;<code>b</code>. Two subsets are considered&nbsp;<strong>different</strong>&nbsp;if the indices of the elements chosen are different.</p>



<p>The bitwise OR of an array&nbsp;<code>a</code>&nbsp;is equal to&nbsp;<code>a[0]&nbsp;<strong>OR</strong>&nbsp;a[1]&nbsp;<strong>OR</strong>&nbsp;...&nbsp;<strong>OR</strong>&nbsp;a[a.length - 1]</code>&nbsp;(<strong>0-indexed</strong>).</p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [3,1]
<strong>Output:</strong> 2
<strong>Explanation:</strong> The maximum possible bitwise OR of a subset is 3. There are 2 subsets with a bitwise OR of 3:
- [3]
- [3,1]
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [2,2,2]
<strong>Output:</strong> 7
<strong>Explanation:</strong> All non-empty subsets of [2,2,2] have a bitwise OR of 2. There are 2<sup>3</sup> - 1 = 7 total subsets.
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [3,2,1,5]
<strong>Output:</strong> 6
<strong>Explanation:</strong> The maximum possible bitwise OR of a subset is 7. There are 6 subsets with a bitwise OR of 7:
- [3,5]
- [3,1,5]
- [3,2,5]
- [3,2,1,5]
- [2,5]
- [2,1,5]</pre>



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



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



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



<p>Try all possible subsets</p>



<p>Time complexity: O(n*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 countMaxOrSubsets(vector&lt;int&gt;&amp; nums) {
    const int n = nums.size();
    int max_or = 0;
    int count = 0;
    for (int s = 0; s &lt; 1 &lt;&lt; n; ++s) {
      int cur_or = 0;
      for (int i = 0; i &lt; n; ++i)
        if (s &gt;&gt; i &amp; 1) cur_or |= nums[i];
      if (cur_or &gt; max_or) {
        max_or = cur_or;
        count = 1;
      } else if (cur_or == max_or) {
        ++count;
      }
    }
    return count;
  }
};</pre>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/searching/leetcode-2044-count-number-of-maximum-bitwise-or-subsets/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1863. Sum of All Subset XOR Totals</title>
		<link>https://zxi.mytechroad.com/blog/bit/leetcode-1863-sum-of-all-subset-xor-totals/</link>
					<comments>https://zxi.mytechroad.com/blog/bit/leetcode-1863-sum-of-all-subset-xor-totals/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Thu, 05 Aug 2021 05:03:21 +0000</pubDate>
				<category><![CDATA[Array]]></category>
		<category><![CDATA[Bit]]></category>
		<category><![CDATA[subset]]></category>
		<category><![CDATA[xor]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=8464</guid>

					<description><![CDATA[The&#160;XOR total&#160;of an array is defined as the bitwise&#160;XOR&#160;of&#160;all its elements, or&#160;0&#160;if the array is&#160;empty. For example, the&#160;XOR total&#160;of the array&#160;[2,5,6]&#160;is&#160;2 XOR 5 XOR 6&#8230;]]></description>
										<content:encoded><![CDATA[
<p>The&nbsp;<strong>XOR total</strong>&nbsp;of an array is defined as the bitwise&nbsp;<code>XOR</code>&nbsp;of<strong>&nbsp;all its elements</strong>, or&nbsp;<code>0</code>&nbsp;if the array is<strong>&nbsp;empty</strong>.</p>



<ul class="wp-block-list"><li>For example, the&nbsp;<strong>XOR total</strong>&nbsp;of the array&nbsp;<code>[2,5,6]</code>&nbsp;is&nbsp;<code>2 XOR 5 XOR 6 = 1</code>.</li></ul>



<p>Given an array&nbsp;<code>nums</code>, return&nbsp;<em>the&nbsp;<strong>sum</strong>&nbsp;of all&nbsp;<strong>XOR totals</strong>&nbsp;for every&nbsp;<strong>subset</strong>&nbsp;of&nbsp;</em><code>nums</code>.&nbsp;</p>



<p><strong>Note:</strong>&nbsp;Subsets with the&nbsp;<strong>same</strong>&nbsp;elements should be counted&nbsp;<strong>multiple</strong>&nbsp;times.</p>



<p>An array&nbsp;<code>a</code>&nbsp;is a&nbsp;<strong>subset</strong>&nbsp;of an array&nbsp;<code>b</code>&nbsp;if&nbsp;<code>a</code>&nbsp;can be obtained from&nbsp;<code>b</code>&nbsp;by deleting some (possibly zero) elements of&nbsp;<code>b</code>.</p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [1,3]
<strong>Output:</strong> 6
<strong>Explanation: </strong>The 4 subsets of [1,3] are:
- The empty subset has an XOR total of 0.
- [1] has an XOR total of 1.
- [3] has an XOR total of 3.
- [1,3] has an XOR total of 1 XOR 3 = 2.
0 + 1 + 3 + 2 = 6
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [5,1,6]
<strong>Output:</strong> 28
<strong>Explanation: </strong>The 8 subsets of [5,1,6] are:
- The empty subset has an XOR total of 0.
- [5] has an XOR total of 5.
- [1] has an XOR total of 1.
- [6] has an XOR total of 6.
- [5,1] has an XOR total of 5 XOR 1 = 4.
- [5,6] has an XOR total of 5 XOR 6 = 3.
- [1,6] has an XOR total of 1 XOR 6 = 7.
- [5,1,6] has an XOR total of 5 XOR 1 XOR 6 = 2.
0 + 5 + 1 + 6 + 4 + 3 + 7 + 2 = 28
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [3,4,5,6,7,8]
<strong>Output:</strong> 480
<strong>Explanation:</strong> The sum of all XOR totals for every subset is 480.
</pre>



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



<ul class="wp-block-list"><li><code>1 &lt;= nums.length &lt;= 12</code></li><li><code>1 &lt;= nums[i] &lt;= 20</code></li></ul>



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



<p>Use an array A to store all the xor subsets, for a given number x<br>A = A + [x ^ a for a in A]</p>



<p>Time complexity: O(2<sup>n</sup>)<br>Space complexity: O(2<sup>n</sup>)</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 subsetXORSum(self, nums: List[int]) -&gt; int:    
    xors = [0]
    for x in nums:
      xors += [xor ^ x for xor in xors]    
    return sum(xors)</pre>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/bit/leetcode-1863-sum-of-all-subset-xor-totals/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1452. People Whose List of Favorite Companies Is Not a Subset of Another List</title>
		<link>https://zxi.mytechroad.com/blog/hashtable/leetcode-1452-people-whose-list-of-favorite-companies-is-not-a-subset-of-another-list/</link>
					<comments>https://zxi.mytechroad.com/blog/hashtable/leetcode-1452-people-whose-list-of-favorite-companies-is-not-a-subset-of-another-list/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 17 May 2020 04:44:35 +0000</pubDate>
				<category><![CDATA[Hashtable]]></category>
		<category><![CDATA[hashtable]]></category>
		<category><![CDATA[subset]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=6767</guid>

					<description><![CDATA[Given the array&#160;favoriteCompanies&#160;where&#160;favoriteCompanies[i]&#160;is the list of favorites companies for the&#160;ith&#160;person (indexed from 0). Return the indices of people whose list of favorite companies is not&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Given the array&nbsp;<code>favoriteCompanies</code>&nbsp;where&nbsp;<code>favoriteCompanies[i]</code>&nbsp;is the list of favorites companies for the&nbsp;<code>ith</code>&nbsp;person (<strong>indexed from 0</strong>).</p>



<p><em>Return the indices of people whose list of favorite companies is not a&nbsp;<strong>subset</strong>&nbsp;of any other list of favorites companies</em>. You must return the indices&nbsp;in increasing order.</p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> favoriteCompanies = [["leetcode","google","facebook"],["google","microsoft"],["google","facebook"],["google"],["amazon"]]
<strong>Output:</strong> [0,1,4] 
<strong>Explanation:</strong> 
Person with index=2 has favoriteCompanies[2]=["google","facebook"] which is a subset of favoriteCompanies[0]=["leetcode","google","facebook"] corresponding to the person with index 0. 
Person with index=3 has favoriteCompanies[3]=["google"] which is a subset of favoriteCompanies[0]=["leetcode","google","facebook"] and favoriteCompanies[1]=["google","microsoft"]. 
Other lists of favorite companies are not a subset of another list, therefore, the answer is [0,1,4].
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> favoriteCompanies = [["leetcode","google","facebook"],["leetcode","amazon"],["facebook","google"]]
<strong>Output:</strong> [0,1] 
<strong>Explanation:</strong> In this case favoriteCompanies[2]=["facebook","google"] is a subset of favoriteCompanies[0]=["leetcode","google","facebook"], therefore, the answer is [0,1].
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> favoriteCompanies = [["leetcode"],["google"],["facebook"],["amazon"]]
<strong>Output:</strong> [0,1,2,3]
</pre>



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



<ul class="wp-block-list"><li><code>1 &lt;=&nbsp;favoriteCompanies.length &lt;= 100</code></li><li><code>1 &lt;=&nbsp;favoriteCompanies[i].length &lt;= 500</code></li><li><code>1 &lt;=&nbsp;favoriteCompanies[i][j].length &lt;= 20</code></li><li>All strings in&nbsp;<code>favoriteCompanies[i]</code>&nbsp;are&nbsp;<strong>distinct</strong>.</li><li>All lists of favorite companies are&nbsp;<strong>distinct</strong>, that is, If we sort alphabetically each list then&nbsp;<code>favoriteCompanies[i] != favoriteCompanies[j].</code></li><li>All strings consist of lowercase English letters only.</li></ul>



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



<p>Time complexity: O(n*n*m)<br>Space complexity: O(n*m)<br>where n is the # of people, m is the # of companies</p>



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

<pre class="urvanov-syntax-highlighter-plain-tag">// Author: Huahua, 664 ms 58.4 MB
class Solution {
public:
  vector&lt;int&gt; peopleIndexes(vector&lt;vector&lt;string&gt;&gt;&amp; favoriteCompanies) {
    const int n = favoriteCompanies.size();
    vector&lt;unordered_set&lt;string&gt;&gt; m;
    for (const auto&amp; c : favoriteCompanies)
      m.emplace_back(begin(c), end(c));
    vector&lt;int&gt; ans;
    for (int i = 0; i &lt; n; ++i) {
      bool valid = true;
      for (int j = 0; j &lt; n &amp;&amp; valid; ++j) {
        if (i == j) continue;
        bool subset = true;
        for (const auto&amp; s : m[i])
          if (!m[j].count(s)) {
            subset = false;
            break;
          }
        if (subset) {
          valid = false;
          break;
        }
      }
      if (valid)
        ans.push_back(i);
    }
    return ans;
  }
};</pre>
</div></div>



<p>Use int as key to make it faster.</p>



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

<pre class="urvanov-syntax-highlighter-plain-tag">// Author: Huahua, 476 ms, 48.7 MB
class Solution {
public:
  vector&lt;int&gt; peopleIndexes(vector&lt;vector&lt;string&gt;&gt;&amp; favoriteCompanies) {
    const int n = favoriteCompanies.size();
    unordered_map&lt;string, int&gt; ids;
    vector&lt;unordered_set&lt;int&gt;&gt; m;
    for (const auto&amp; companies : favoriteCompanies) {
      m.push_back({});
      for (const auto&amp; c : companies) {
        if (!ids.count(c))
          ids[c] = ids.size();
        m.back().insert(ids[c]);
      }
    }
    vector&lt;int&gt; ans;
    for (int i = 0; i &lt; n; ++i) {
      bool valid = true;
      for (int j = 0; j &lt; n &amp;&amp; valid; ++j) {
        if (i == j) continue;
        bool subset = true;
        for (const auto&amp; s : m[i])
          if (!m[j].count(s)) {
            subset = false;
            break;
          }
        if (subset) {
          valid = false;
          break;
        }
      }
      if (valid) ans.push_back(i);
    }
    return ans;
  }
};</pre>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/hashtable/leetcode-1452-people-whose-list-of-favorite-companies-is-not-a-subset-of-another-list/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1178. Number of Valid Words for Each Puzzle</title>
		<link>https://zxi.mytechroad.com/blog/hashtable/leetcode-1178-number-of-valid-words-for-each-puzzle/</link>
					<comments>https://zxi.mytechroad.com/blog/hashtable/leetcode-1178-number-of-valid-words-for-each-puzzle/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Mon, 02 Sep 2019 01:28:10 +0000</pubDate>
				<category><![CDATA[Hashtable]]></category>
		<category><![CDATA[compression]]></category>
		<category><![CDATA[frequency]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[hashtable]]></category>
		<category><![CDATA[string]]></category>
		<category><![CDATA[subset]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=5521</guid>

					<description><![CDATA[With respect to a given&#160;puzzle&#160;string, a&#160;word&#160;is&#160;valid&#160;if both the following conditions are satisfied: word&#160;contains the first letter of&#160;puzzle. For each letter in&#160;word, that letter is in&#160;puzzle.For&#8230;]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="花花酱 LeetCode 1178. Number of Valid Words for Each Puzzle - 刷题找工作 EP267" width="500" height="375" src="https://www.youtube.com/embed/qOrmhPX-gAU?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>

With respect to a given&nbsp;<code>puzzle</code>&nbsp;string, a&nbsp;<code>word</code>&nbsp;is&nbsp;<em>valid</em>&nbsp;if both the following conditions are satisfied:</p>



<ul class="wp-block-list"><li><code>word</code>&nbsp;contains the first letter of&nbsp;<code>puzzle</code>.</li><li>For each letter in&nbsp;<code>word</code>, that letter is in&nbsp;<code>puzzle</code>.<br>For example, if the puzzle is &#8220;abcdefg&#8221;, then valid words are &#8220;faced&#8221;, &#8220;cabbage&#8221;, and &#8220;baggage&#8221;; while invalid words are &#8220;beefed&#8221; (doesn&#8217;t include &#8220;a&#8221;) and &#8220;based&#8221; (includes &#8220;s&#8221; which isn&#8217;t in the puzzle).</li></ul>



<p>Return an array&nbsp;<code>answer</code>, where&nbsp;<code>answer[i]</code>&nbsp;is the number of words in the given word list&nbsp;<code>words</code>&nbsp;that are valid with respect to the puzzle&nbsp;<code>puzzles[i]</code>.</p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> 
words = ["aaaa","asas","able","ability","actt","actor","access"], 
puzzles = ["aboveyz","abrodyz","abslute","absoryz","actresz","gaswxyz"]
<strong>Output:</strong> [1,1,3,2,4,0]
<strong>Explanation:</strong>
1 valid word&nbsp;for "aboveyz" : "aaaa" 
1 valid word&nbsp;for "abrodyz" : "aaaa"
3 valid words for "abslute" : "aaaa", "asas", "able"
2 valid words for&nbsp;"absoryz" : "aaaa", "asas"
4 valid words for&nbsp;"actresz" : "aaaa", "asas", "actt", "access"
There're&nbsp;no valid words for&nbsp;"gaswxyz" cause none of the words in the list contains letter 'g'.
</pre>



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



<ul class="wp-block-list"><li><code>1 &lt;= words.length &lt;= 10^5</code></li><li><code>4 &lt;= words[i].length &lt;= 50</code></li><li><code>1 &lt;= puzzles.length &lt;= 10^4</code></li><li><code>puzzles[i].length == 7</code></li><li><code>words[i][j]</code>,&nbsp;<code>puzzles[i][j]</code>&nbsp;are English lowercase letters.</li><li>Each&nbsp;<code>puzzles[i]&nbsp;</code>doesn&#8217;t contain repeated characters.</li></ul>



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



<p>Preprocessing: <br>Compress each word to a bit map, and compute the frequency of each bit map.<br>Since there are at most |words| bitmaps while its value ranging from 0 to 2^26, thus it&#8217;s better to use a hashtable instead of an array.</p>



<p>Query:<br>Use the same way to compress a puzzle into a bit map.<br>Try all subsets (at most 128) of the puzzle (the bit of the first character is be must), and check how many words match each subset.</p>



<p>words = [&#8220;aaaa&#8221;,&#8221;asas&#8221;,&#8221;able&#8221;,&#8221;ability&#8221;,&#8221;actt&#8221;,&#8221;actor&#8221;,&#8221;access&#8221;], <br>puzzle = &#8220;abslute&#8221;<br>bitmap(&#8220;aaaa&#8221;)  = {0}<br>bitmap(&#8220;asas&#8221;) = {0, 18}<br>bitmap(&#8220;able&#8221;) = {0,1,4,11}<br>bitmap(&#8220;actt&#8221;) = {0, 2, 19}<br>bitmap(&#8220;actor&#8221;) = {0, 2, 14, 17, 19}<br>bitmap(&#8220;access&#8221;) = {0, 2, 4, 18}<br><br>bitmap(&#8220;abslute&#8221;) = {0, 1, 4, 11, 18, 19, 20}<br></p>



<p>Time complexity: O(sum(len(w_i)) + |puzzles|)<br>Space complexity: O(|words|)</p>



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

<pre class="urvanov-syntax-highlighter-plain-tag">// Author: Huahua, 136 ms, 29.7 MB
class Solution {
public:
  vector&lt;int&gt; findNumOfValidWords(vector&lt;string&gt;&amp; words, vector&lt;string&gt;&amp; puzzles) {
    vector&lt;int&gt; ans;    
    unordered_map&lt;int, int&gt; freq;
    for (const string&amp; word : words) {
      int mask = 0;
      for (char c : word)
        mask |= 1 &lt;&lt; (c - 'a');
      ++freq[mask];
    }    
    for (const string&amp; p : puzzles) {
      int mask = 0;      
      for (char c : p)
        mask |= 1 &lt;&lt; (c - 'a');
      int first = p[0] - 'a';
      int curr = mask;
      int total = 0;
      while (curr) {
        if ((curr &gt;&gt; first) &amp; 1) {
          auto it = freq.find(curr);
          if (it != freq.end()) total += it-&gt;second;
        }
        curr = (curr - 1) &amp; mask;
      }
      ans.push_back(total);
    }
    return ans;
  }
};</pre>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/hashtable/leetcode-1178-number-of-valid-words-for-each-puzzle/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
