<?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>trie Archives - Huahua&#039;s Tech Road</title>
	<atom:link href="https://zxi.mytechroad.com/blog/tag/trie/feed/" rel="self" type="application/rss+xml" />
	<link>https://zxi.mytechroad.com/blog/tag/trie/</link>
	<description></description>
	<lastBuildDate>Mon, 28 Dec 2020 08:12:11 +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>trie Archives - Huahua&#039;s Tech Road</title>
	<link>https://zxi.mytechroad.com/blog/tag/trie/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>花花酱 LeetCode 1707. Maximum XOR With an Element From Array</title>
		<link>https://zxi.mytechroad.com/blog/trie/leetcode-1707-maximum-xor-with-an-element-from-array/</link>
					<comments>https://zxi.mytechroad.com/blog/trie/leetcode-1707-maximum-xor-with-an-element-from-array/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 27 Dec 2020 21:54:20 +0000</pubDate>
				<category><![CDATA[Trie]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[query]]></category>
		<category><![CDATA[sorting]]></category>
		<category><![CDATA[trie]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=7871</guid>

					<description><![CDATA[<p>You are given an array&#160;nums&#160;consisting of non-negative integers. You are also given a&#160;queries&#160;array, where&#160;queries[i] = [xi, mi]. The answer to the&#160;ith&#160;query is the maximum bitwise&#160;XOR&#160;value&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/trie/leetcode-1707-maximum-xor-with-an-element-from-array/">花花酱 LeetCode 1707. Maximum XOR With an Element From Array</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 1707. Maximum XOR With an Element From Array - 刷题找工作 EP377" width="500" height="281" src="https://www.youtube.com/embed/k0e9tM7gU3E?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<p>You are given an array&nbsp;<code>nums</code>&nbsp;consisting of non-negative integers. You are also given a&nbsp;<code>queries</code>&nbsp;array, where&nbsp;<code>queries[i] = [x<sub>i</sub>, m<sub>i</sub>]</code>.</p>



<p>The answer to the&nbsp;<code>i<sup>th</sup></code>&nbsp;query is the maximum bitwise&nbsp;<code>XOR</code>&nbsp;value of&nbsp;<code>x<sub>i</sub></code>&nbsp;and any element of&nbsp;<code>nums</code>&nbsp;that does not exceed&nbsp;<code>m<sub>i</sub></code>. In other words, the answer is&nbsp;<code>max(nums[j] XOR x<sub>i</sub>)</code>&nbsp;for all&nbsp;<code>j</code>&nbsp;such that&nbsp;<code>nums[j] &lt;= m<sub>i</sub></code>. If all elements in&nbsp;<code>nums</code>&nbsp;are larger than&nbsp;<code>m<sub>i</sub></code>, then the answer is&nbsp;<code>-1</code>.</p>



<p>Return&nbsp;<em>an integer array&nbsp;</em><code>answer</code><em>&nbsp;where&nbsp;</em><code>answer.length == queries.length</code><em>&nbsp;and&nbsp;</em><code>answer[i]</code><em>&nbsp;is the answer to the&nbsp;</em><code>i<sup>th</sup></code><em>&nbsp;query.</em></p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [0,1,2,3,4], queries = [[3,1],[1,3],[5,6]]
<strong>Output:</strong> [3,3,7]
<strong>Explanation:</strong>
1) 0 and 1 are the only two integers not greater than 1. 0 XOR 3 = 3 and 1 XOR 3 = 2. The larger of the two is 3.
2) 1 XOR 2 = 3.
3) 5 XOR 2 = 7.
</pre>



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



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



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



<ul><li><code>1 &lt;= nums.length, queries.length &lt;= 10<sup>5</sup></code></li><li><code>queries[i].length == 2</code></li><li><code>0 &lt;= nums[j], x<sub>i</sub>, m<sub>i</sub>&nbsp;&lt;= 10<sup>9</sup></code></li></ul>



<h2><strong>Solution: Trie on the fly</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/1707-ep377-1.png" alt="" class="wp-image-7874" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/12/1707-ep377-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/12/1707-ep377-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/12/1707-ep377-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/1707-ep377-2.png" alt="" class="wp-image-7875" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/12/1707-ep377-2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/12/1707-ep377-2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/12/1707-ep377-2-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/1707-ep377-3.png" alt="" class="wp-image-7876" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/12/1707-ep377-3.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/12/1707-ep377-3-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/12/1707-ep377-3-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></figure>



<p>Similar idea to <a href="https://zxi.mytechroad.com/blog/trie/leetcode-421-maximum-xor-of-two-numbers-in-an-array/">https://zxi.mytechroad.com/blog/trie/leetcode-421-maximum-xor-of-two-numbers-in-an-array/</a></p>



<p>We can build the trie on the fly by sorting nums in ascending order and queries by its limit, insert nums into the trie up the limit.</p>



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



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

<pre class="crayon-plain-tag">// Author: Huahua
class Trie {
public:
  Trie(): children{nullptr, nullptr} {}  
  Trie* children[2];
};
class Solution {
public:
  vector&lt;int&gt; maximizeXor(vector&lt;int&gt;&amp; nums, vector&lt;vector&lt;int&gt;&gt;&amp; queries) {
    const int n = nums.size();
    sort(begin(nums), end(nums));    
    
    const int Q = queries.size();
    for (int i = 0; i &lt; Q; ++i)
      queries[i].push_back(i);
    sort(begin(queries), end(queries), [](const auto&amp; q1, const auto&amp; q2) {
      return q1[1] &lt; q2[1];
    });
    
    Trie root;    
    auto insert = [&amp;](int num) {
      Trie* node = &amp;root; 
      for (int i = 31; i &gt;= 0; --i) {
        int bit = (num &gt;&gt; i) &amp; 1;
        if (!node-&gt;children[bit])
          node-&gt;children[bit] = new Trie();
        node = node-&gt;children[bit];
      }
    };
        
    auto query = [&amp;](int num) {
      Trie* node = &amp;root;
      int sum = 0;
      for (int i = 31; i &gt;= 0; --i) {
        if (!node) return -1;
        int bit = (num &gt;&gt; i) &amp; 1;
        if (node-&gt;children[1 - bit]) {
          sum |= (1 &lt;&lt; i);
          node = node-&gt;children[1 - bit];
        } else {
          node = node-&gt;children[bit];
        }
      }
      return sum;
    };
    
    vector&lt;int&gt; ans(Q);
    int i = 0;
    for (const auto&amp; q : queries) {
      while (i &lt; n &amp;&amp; nums[i] &lt;= q[1]) insert(nums[i++]);
      ans[q[2]] = query(q[0]);
    }  
    return ans;
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/trie/leetcode-1707-maximum-xor-with-an-element-from-array/">花花酱 LeetCode 1707. Maximum XOR With an Element From Array</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/trie/leetcode-1707-maximum-xor-with-an-element-from-array/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 421. Maximum XOR of Two Numbers in an Array</title>
		<link>https://zxi.mytechroad.com/blog/trie/leetcode-421-maximum-xor-of-two-numbers-in-an-array/</link>
					<comments>https://zxi.mytechroad.com/blog/trie/leetcode-421-maximum-xor-of-two-numbers-in-an-array/#comments</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 27 Dec 2020 21:31:59 +0000</pubDate>
				<category><![CDATA[Trie]]></category>
		<category><![CDATA[bit]]></category>
		<category><![CDATA[trie]]></category>
		<category><![CDATA[xor]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=7868</guid>

					<description><![CDATA[<p>Given an integer array&#160;nums, return&#160;the maximum result of&#160;nums[i] XOR nums[j], where&#160;0 ≤ i ≤ j &#60; n. Follow up:&#160;Could you do this in&#160;O(n)&#160;runtime? Example 1:&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/trie/leetcode-421-maximum-xor-of-two-numbers-in-an-array/">花花酱 LeetCode 421. Maximum XOR of Two Numbers in an Array</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 an integer array&nbsp;<code>nums</code>, return&nbsp;<em>the maximum result of&nbsp;<code>nums[i] XOR nums[j]</code></em>, where&nbsp;<code>0 ≤ i ≤ j &lt; n</code>.</p>



<p><strong>Follow up:</strong>&nbsp;Could you do this in&nbsp;<code>O(n)</code>&nbsp;runtime?</p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [3,10,5,25,2,8]
<strong>Output:</strong> 28
<strong>Explanation:</strong> The maximum result is 5 XOR 25 = 28.</pre>



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



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



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [2,4]
<strong>Output:</strong> 6
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [8,10,2]
<strong>Output:</strong> 10
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [14,70,53,83,49,91,36,80,92,51,66,70]
<strong>Output:</strong> 127
</pre>



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



<ul><li><code>1 &lt;= nums.length &lt;= 2 * 10<sup>4</sup></code></li><li><code>0 &lt;= nums[i] &lt;= 2<sup>31</sup>&nbsp;- 1</code></li></ul>



<h2><strong>Solution: Trie</strong></h2>



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



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

<pre class="crayon-plain-tag">// Author: Huahua
class Trie {
public:
  Trie(): children(2) {}  
  vector&lt;unique_ptr&lt;Trie&gt;&gt; children;
};
class Solution {
public:
  int findMaximumXOR(vector&lt;int&gt;&amp; nums) {
    Trie root;
    
    // Insert a number into the trie.
    auto insert = [&amp;](Trie* node, int num) {
      for (int i = 31; i &gt;= 0; --i) {
        int bit = (num &gt;&gt; i) &amp; 1;
        if (!node-&gt;children[bit])
          node-&gt;children[bit] = std::make_unique&lt;Trie&gt;();
        node = node-&gt;children[bit].get();
      }
    };
  
    // Find max xor sum of num and another element in the array.
    auto query = [&amp;](Trie* node, int num) {
      int sum = 0;
      for (int i = 31; i &gt;= 0; --i) {
        int bit = (num &gt;&gt; i) &amp; 1;
        if (node-&gt;children[1 - bit]) {
          sum += (1 &lt;&lt; i);
          node = node-&gt;children[1 - bit].get();
        } else {
          node = node-&gt;children[bit].get();
        }
      }
      return sum;
    };
    
    // Insert all numbers.
    for (int x : nums) 
      insert(&amp;root, x);
    
    int ans = 0;
    // For each number find the maximum xor sum.
    for (int x : nums) 
      ans = max(ans, query(&amp;root, x));
    return ans;
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/trie/leetcode-421-maximum-xor-of-two-numbers-in-an-array/">花花酱 LeetCode 421. Maximum XOR of Two Numbers in an Array</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/trie/leetcode-421-maximum-xor-of-two-numbers-in-an-array/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1268. Search Suggestions System</title>
		<link>https://zxi.mytechroad.com/blog/algorithms/binary-search/leetcode-1268-search-suggestions-system/</link>
					<comments>https://zxi.mytechroad.com/blog/algorithms/binary-search/leetcode-1268-search-suggestions-system/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 24 Nov 2019 08:06:55 +0000</pubDate>
				<category><![CDATA[Binary Search]]></category>
		<category><![CDATA[binary search]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[prefix]]></category>
		<category><![CDATA[sorting]]></category>
		<category><![CDATA[trie]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=5841</guid>

					<description><![CDATA[<p>Given an array of strings&#160;products&#160;and a string&#160;searchWord. We want to design a system that suggests at most three product names from&#160;products&#160;after each character of&#160;searchWord&#160;is typed.&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/algorithms/binary-search/leetcode-1268-search-suggestions-system/">花花酱 LeetCode 1268. Search Suggestions System</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="花花酱 LeetCode 1268. Search Suggestions System - 刷题找工作 EP268" width="500" height="375" src="https://www.youtube.com/embed/hi8xga8nWm4?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<p>Given an array of strings&nbsp;<code>products</code>&nbsp;and a string&nbsp;<code>searchWord</code>. We want to design a system that suggests at most three product names from&nbsp;<code>products</code>&nbsp;after each character of&nbsp;<code>searchWord</code>&nbsp;is typed. Suggested products should have common prefix with the searchWord. If there are&nbsp;more than three products with a common prefix&nbsp;return the three lexicographically minimums products.</p>



<p>Return&nbsp;<em>list of lists</em>&nbsp;of the suggested&nbsp;<code>products</code>&nbsp;after each character of&nbsp;<code>searchWord</code>&nbsp;is typed.&nbsp;</p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> products = ["mobile","mouse","moneypot","monitor","mousepad"], searchWord = "mouse"
<strong>Output:</strong> [
["mobile","moneypot","monitor"],
["mobile","moneypot","monitor"],
["mouse","mousepad"],
["mouse","mousepad"],
["mouse","mousepad"]
]
<strong>Explanation:</strong> products sorted lexicographically = ["mobile","moneypot","monitor","mouse","mousepad"]
After typing m and mo all products match and we show user ["mobile","moneypot","monitor"]
After typing mou, mous and mouse the system suggests ["mouse","mousepad"]
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> products = ["havana"], searchWord = "havana"
<strong>Output:</strong> [["havana"],["havana"],["havana"],["havana"],["havana"],["havana"]]
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> products = ["bags","baggage","banner","box","cloths"], searchWord = "bags"
<strong>Output:</strong> [["baggage","bags","banner"],["baggage","bags","banner"],["baggage","bags"],["bags"]]
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> products = ["havana"], searchWord = "tatiana"
<strong>Output:</strong> [[],[],[],[],[],[],[]]
</pre>



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



<ul><li><code>1 &lt;= products.length &lt;= 1000</code></li><li><code>1 &lt;= Σ products[i].length &lt;= 2 * 10^4</code></li><li>All characters of&nbsp;<code>products[i]</code>&nbsp;are lower-case English letters.</li><li><code>1 &lt;= searchWord.length &lt;= 1000</code></li><li>All characters of&nbsp;<code>searchWord</code>&nbsp;are lower-case English letters.</li></ul>



<h2><strong>Solution 1: Binary Search</strong></h2>



<p>Sort the input array and do two binary searches.<br>One for prefix of the search word as lower bound, another for prefix + &#8216;~&#8217; as upper bound.<br>&#8216;~&#8217; &gt; &#8216;z&#8217;</p>



<p>Time complexity: O(nlogn + l * logn)<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, 36ms, 35MB
class Solution {
public:
  vector&lt;vector&lt;string&gt;&gt; suggestedProducts(vector&lt;string&gt;&amp; products, string searchWord) {
    vector&lt;vector&lt;string&gt;&gt; ans;
    std::sort(begin(products), end(products));
    string key;
    for (char c : searchWord) {
      key += c;      
      auto l = lower_bound(begin(products), end(products), key);
      auto r = upper_bound(begin(products), end(products), key += '~');
      if (l == r) break; // early return
      key.pop_back();
      ans.emplace_back(l, min(l + 3, r));
    }
    while (ans.size() != searchWord.length()) ans.push_back({});
    return ans;
  }
};</pre>
</div></div>



<h2><strong>Solution 2: Trie</strong></h2>



<p>Initialization: Sum(len(products[i]))<br>Query: O(len(searchWord))</p>



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

<pre class="crayon-plain-tag">// Author: Huahua, 148 ms, 98.8 MB
struct Trie {
  Trie(): nodes(26) {}
  ~Trie() { 
    for (auto* node : nodes)
      delete node;
  }
  vector&lt;Trie*&gt; nodes;
  vector&lt;const string*&gt; words;  
  
  static void addWord(Trie* root, const string&amp; word) {    
    for (char c : word) {      
      if (root-&gt;nodes[c - 'a'] == nullptr) root-&gt;nodes[c - 'a'] = new Trie();
      root = root-&gt;nodes[c - 'a'];
      if (root-&gt;words.size() &lt; 3)
        root-&gt;words.push_back(&amp;word);
    }
  }
  
  static vector&lt;vector&lt;string&gt;&gt; getWords(Trie* root, const string&amp; prefix) {
    vector&lt;vector&lt;string&gt;&gt; ans(prefix.size());
    for (int i = 0; i &lt; prefix.size(); ++i) {
      char c = prefix[i];
      root = root-&gt;nodes[c - 'a'];
      if (root == nullptr) break;
      for (auto* word : root-&gt;words)
        ans[i].push_back(*word);
    }
    return ans;
  }
};

class Solution {
public:
  vector&lt;vector&lt;string&gt;&gt; suggestedProducts(vector&lt;string&gt;&amp; products, string searchWord) {
    std::sort(begin(products), end(products));
    Trie root;
    for (const auto&amp; product : products)
      Trie::addWord(&amp;root, product);
    return Trie::getWords(&amp;root, searchWord);
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/algorithms/binary-search/leetcode-1268-search-suggestions-system/">花花酱 LeetCode 1268. Search Suggestions System</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/algorithms/binary-search/leetcode-1268-search-suggestions-system/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 212. Word Search II</title>
		<link>https://zxi.mytechroad.com/blog/searching/leetcode-212-word-search-ii/</link>
					<comments>https://zxi.mytechroad.com/blog/searching/leetcode-212-word-search-ii/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Tue, 20 Aug 2019 22:28:28 +0000</pubDate>
				<category><![CDATA[Search]]></category>
		<category><![CDATA[DFS]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[search]]></category>
		<category><![CDATA[trie]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=5464</guid>

					<description><![CDATA[<p>Given a 2D board and a list of words from the dictionary, find all words in the board. Each word must be constructed from letters&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/searching/leetcode-212-word-search-ii/">花花酱 LeetCode 212. Word Search 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[
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe width="500" height="375" src="https://www.youtube.com/embed/aEEJ3xHIF5o?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<p>Given a 2D board and a list of words from the dictionary, find all words in the board.</p>



<p>Each word must be constructed from letters of sequentially adjacent cell, where &#8220;adjacent&#8221; cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once in a word.</p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> 
<strong>board </strong>= [
  ['o','a','a','n'],
  ['e','t','a','e'],
  ['i','h','k','r'],
  ['i','f','l','v']
]
<strong>words</strong> = <code>["oath","pea","eat","rain"]</code>

<strong>Output:&nbsp;</strong><code>["eat","oath"]</code>
</pre>



<p><strong>Note:</strong></p>



<ol><li>All inputs are consist of lowercase letters&nbsp;<code>a-z</code>.</li><li>The values of&nbsp;<code>words</code>&nbsp;are distinct.</li></ol>



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



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



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

<pre class="crayon-plain-tag">// Author: Huahua, 708 ms, 15.3 MB
class Solution {
public:
  vector&lt;string&gt; findWords(vector&lt;vector&lt;char&gt;&gt;&amp; board, vector&lt;string&gt;&amp; words) {
    unordered_set&lt;string&gt; unique_words(words.begin(), words.end());
    vector&lt;string&gt; ans;
    for (const string&amp; word : unique_words)
      if (exist(board, word))
        ans.push_back(word);
    return ans;
  }
private:
  int w;
  int h;
  bool exist(vector&lt;vector&lt;char&gt;&gt; &amp;board, string word) {
    if (board.size() == 0) return false;
    h = board.size();
    w = board[0].size();
    for (int i = 0 ; i &lt; w; i++)
      for (int j = 0 ; j &lt; h; j++)
        if (search(board, word, 0, i, j)) return true;
    return false;
  }
    
  bool search(vector&lt;vector&lt;char&gt;&gt; &amp;board, 
           const string&amp; word, int d, int x, int y) {
    if (x &lt; 0 || x == w || y &lt; 0 || y == h || word[d] != board[y][x]) 
      return false;

    // Found the last char of the word
    if (d == word.length() - 1)
      return true;

    char cur = board[y][x];
    board[y][x] = '#'; 
    bool found = search(board, word, d + 1, x + 1, y)
              || search(board, word, d + 1, x - 1, y)
              || search(board, word, d + 1, x, y + 1)
              || search(board, word, d + 1, x, y - 1);
    board[y][x] = cur;
    return found;
  }
};</pre>
</div></div>



<h2><strong>Solution 2: Trie</strong></h2>



<p>Store all the words into a trie, search the board using DFS, paths must be in the trie otherwise there is no need to explore.</p>



<p>Time complexity: O(sum(l) + 4^max(l))<br>space complexity: O(sum(l) + l)</p>



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

<pre class="crayon-plain-tag">// Author: Huahua, 64 ms, 35.6 MB
class TrieNode {
public:
  vector&lt;TrieNode*&gt; nodes;  
  const string* word;
  TrieNode(): nodes(26), word(nullptr) {}
  ~TrieNode() {
    for (auto node : nodes) delete node;
  }  
};
class Solution {
public:
  vector&lt;string&gt; findWords(vector&lt;vector&lt;char&gt;&gt;&amp; board, vector&lt;string&gt;&amp; words) {
    TrieNode root;
    
    // Add all the words into Trie.
    for (const string&amp; word : words) {
      TrieNode* cur = &amp;root;
      for (char c : word) {
        auto&amp; next = cur-&gt;nodes[c - 'a'];
        if (!next) next = new TrieNode();
        cur = next;
      }
      cur-&gt;word = &amp;word;
    }
    
    const int n = board.size();
    const int m = board[0].size();    
    vector&lt;string&gt; ans;
    
    function&lt;void(int, int, TrieNode*)&gt; walk = [&amp;](int x, int y, TrieNode* node) {      
      if (x &lt; 0 || x == m || y &lt; 0 || y == n || board[y][x] == '#')
        return;      
      
      const char cur = board[y][x];
      TrieNode* next_node = node-&gt;nodes[cur - 'a'];
      
      // Pruning, only expend paths that are in the trie.
      if (!next_node) return;
      
      if (next_node-&gt;word) {
        ans.push_back(*next_node-&gt;word);
        next_node-&gt;word = nullptr;
      }

      board[y][x] = '#';
      walk(x + 1, y, next_node);
      walk(x - 1, y, next_node);
      walk(x, y + 1, next_node);
      walk(x, y - 1, next_node);
      board[y][x] = cur;
    };
    
    // Try all possible pathes.
    for (int i = 0 ; i &lt; n; i++)
      for (int j = 0 ; j &lt; m; j++)
        walk(j, i, &amp;root);        
        
    return ans;
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/searching/leetcode-212-word-search-ii/">花花酱 LeetCode 212. Word Search 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/searching/leetcode-212-word-search-ii/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode Weekly Contest 133</title>
		<link>https://zxi.mytechroad.com/blog/leetcode/leetcode-weekly-contest-133/</link>
					<comments>https://zxi.mytechroad.com/blog/leetcode/leetcode-weekly-contest-133/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 21 Apr 2019 04:39:26 +0000</pubDate>
				<category><![CDATA[Leetcode]]></category>
		<category><![CDATA[contest]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[trie]]></category>
		<category><![CDATA[weekly]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=5092</guid>

					<description><![CDATA[<p>LeetCode 1029 Two City Scheduling Solution1: DP dp[i][j] := min cost to put j people into city A for the first i peopledp[0][0] = 0dp[i][0]&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/leetcode/leetcode-weekly-contest-133/">花花酱 LeetCode Weekly Contest 133</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe width="500" height="375" src="https://www.youtube.com/embed/3A98vh5zsqw?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



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



<h2><strong>LeetCode 1029  Two City Scheduling</strong></h2>



<p>Solution1: DP</p>



<p>dp[i][j] := min cost to put j people into city A for the first i people<br>dp[0][0] = 0<br>dp[i][0] = dp[i -1][0] + cost_b<br>dp[i][j] = min(dp[i &#8211; 1][j] + cost_b, dp[i &#8211; 1][j &#8211; 1] + cost_a)<br>ans := dp[n][n/2]</p>



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



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

<pre class="crayon-plain-tag">// Author: Huahua, running time: 8 ms
class Solution {
public:
  int twoCitySchedCost(vector&lt;vector&lt;int&gt;&gt;&amp; costs) {
    int n = costs.size();
    vector&lt;vector&lt;int&gt;&gt; dp(n + 1, vector&lt;int&gt;(n + 1, INT_MAX / 2));
    dp[0][0] = 0;
    for (int i = 1; i &lt;= n; ++i) {      
      dp[i][0] = dp[i - 1][0] + costs[i - 1][1];
      for (int j = 1; j &lt;= i; ++j)
        dp[i][j] = min(dp[i - 1][j - 1] + costs[i - 1][0], 
                       dp[i - 1][j] + costs[i - 1][1]);
    }
    return dp[n][n / 2];
  }
};</pre>
</div></div>



<p>Solution 2: Greedy</p>



<p>Sort by cost_a &#8211; cost_b</p>



<p>Choose the first n/2 people for A, rest for B</p>



<p>Time complexity: O(nlogn)<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, running time: 8 ms
class Solution {
public:
  int twoCitySchedCost(vector&lt;vector&lt;int&gt;&gt;&amp; costs) {
    int n = costs.size();
    sort(begin(costs), end(costs), [](const auto&amp; c1, const auto&amp; c2){
      return c1[0] - c1[1] &lt; c2[0] - c2[1];
    });
    int ans = 0;
    for (int i = 0; i &lt; n; ++i)
      ans += i &lt; n/2 ? costs[i][0] : costs[i][1];    
    return ans;
  }
};</pre>
</div></div>



<h2><strong> 1030.&nbsp;Matrix Cells in Distance Order</strong></h2>



<p>Solution: Sorting</p>



<p>Time complexity: O(RC*log(RC))<br>Space complexity: O(RC)</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;vector&lt;int&gt;&gt; allCellsDistOrder(int R, int C, int r0, int c0) {
    vector&lt;vector&lt;int&gt;&gt; ans;
    for (int i = 0; i &lt; R; ++i)
      for (int j = 0; j &lt; C; ++j)
        ans.push_back({i, j});
    std::sort(begin(ans), end(ans), [r0, c0](const vector&lt;int&gt;&amp; a, const vector&lt;int&gt;&amp; b){
      return (abs(a[0] - r0) + abs(a[1] - c0)) &lt; (abs(b[0] - r0) + abs(b[1] - c0));
    });
    return ans;
  }
};</pre>
</div></div>



<h2><strong>1031. Maximum Sum of Two Non-Overlapping Subarrays</strong></h2>



<p>Solution: Prefix sum</p>



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



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

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  int maxSumTwoNoOverlap(vector&lt;int&gt;&amp; A, int L, int M) {
    const int n = A.size();
    vector&lt;int&gt; s(n + 1, 0);
    for (int i = 0; i &lt; n; ++i)
      s[i + 1] = s[i] + A[i];
    int ans = 0;
    for (int i = 0; i &lt;= n - L; ++i) {
      int ls = s[i + L] - s[i];
      int ms = max(maxSum(s, 0, i - M - 1, M), 
                   maxSum(s, i + L, n - M, M));
      ans = max(ans, ls + ms);      
    }
    return ans;
  }
private:
  int maxSum(const vector&lt;int&gt;&amp; s, int start, int end, int l) {
    int ans = INT_MIN;    
    for (int i = start; i &lt;= end; ++i)
      ans = max(ans, s[i + l] - s[i]);
    return ans;
  }
};</pre>
</div></div>



<h2><strong> 1032. Stream of Characters</strong></h2>



<p>Solution: Trie</p>



<p>Time complexity: <br></p>



<ul><li>build O(sum(len(w))</li><li>query O(max(len(w)) </li></ul>



<p>Space complexity: O(sum(len(w))</p>



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

<pre class="crayon-plain-tag">// Author: Huahua, 320 ms, 95 MB
class TrieNode {
public:        
  ~TrieNode() {
    for (auto node : next_)
      delete node;
  }

  void reverse_build(const string&amp; s, int i) {
    if (i == -1) {
      is_word_ = true;
      return;
    }
    const int idx = s[i] - 'a';
    if (!next_[idx]) next_[idx] = new TrieNode();
    next_[idx]-&gt;reverse_build(s, i - 1);
  }
  
  bool reverse_search(const string&amp; s, int i) {
    if (i == -1 || is_word_) return is_word_;
    const int idx = s[i] - 'a';
    if (!next_[idx]) return false;
    return next_[idx]-&gt;reverse_search(s, i - 1);
  }

private:
  bool is_word_ = false;
  TrieNode* next_[26] = {0};
};

class StreamChecker {
public:
  StreamChecker(vector&lt;string&gt;&amp; words) {
    root_ = std::make_unique&lt;TrieNode&gt;();
    for (const string&amp; w : words)
      root_-&gt;reverse_build(w, w.length() - 1);
  }

  bool query(char letter) {
    s_ += letter;
    return root_-&gt;reverse_search(s_, s_.length() - 1);    
  }
  
private:
  string s_;
  unique_ptr&lt;TrieNode&gt; root_;
};</pre>

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

<pre class="crayon-plain-tag">// Author: Huahua, running time: 133 ms
class StreamChecker {
  class TrieNode {
    public TrieNode() {
      isWord = false;
      next = new TrieNode[26];
    }
    public boolean isWord;
    public TrieNode next[];    
  }
  
  private TrieNode root;
  private StringBuilder sb;

  public StreamChecker(String[] words) {
    root = new TrieNode();
    sb = new StringBuilder();
    for (String word : words) {
      TrieNode node = root;
      char[] w = word.toCharArray();
      for (int i = w.length - 1; i &gt;= 0; --i) {        
        int idx = w[i] - 'a';
        if (node.next[idx] == null) node.next[idx] = new TrieNode();
        node = node.next[idx];
      }
      node.isWord = true;
    }
  }

  public boolean query(char letter) {
    sb.append(letter);
    TrieNode node = root;
    for (int i = sb.length() - 1; i &gt;= 0; --i) {      
      int idx = sb.charAt(i) - 'a';
      if (node.next[idx] == null) return false;
      if (node.next[idx].isWord) return true;
      node = node.next[idx];
    }
    return false;
  }  
}</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/leetcode/leetcode-weekly-contest-133/">花花酱 LeetCode Weekly Contest 133</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/leetcode/leetcode-weekly-contest-133/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 648. Replace Words</title>
		<link>https://zxi.mytechroad.com/blog/string/leetcode-648-replace-words/</link>
					<comments>https://zxi.mytechroad.com/blog/string/leetcode-648-replace-words/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Fri, 09 Nov 2018 04:42:30 +0000</pubDate>
				<category><![CDATA[Hashtable]]></category>
		<category><![CDATA[String]]></category>
		<category><![CDATA[hashtable]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[prefix]]></category>
		<category><![CDATA[replace]]></category>
		<category><![CDATA[string]]></category>
		<category><![CDATA[trie]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=4267</guid>

					<description><![CDATA[<p>Problem https://leetcode.com/problems/replace-words/description/ In English, we have a concept called root, which can be followed by some other words to form another longer word &#8211; let&#8217;s call&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/string/leetcode-648-replace-words/">花花酱 LeetCode 648. Replace Words</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1><strong>Problem</strong></h1>
<p><a href="https://leetcode.com/problems/replace-words/description/">https://leetcode.com/problems/replace-words/description/</a></p>
<p>In English, we have a concept called <code>root</code>, which can be followed by some other words to form another longer word &#8211; let&#8217;s call this word <code>successor</code>. For example, the root <code>an</code>, followed by <code>other</code>, which can form another word <code>another</code>.</p>
<p>Now, given a dictionary consisting of many roots and a sentence. You need to replace all the <code>successor</code> in the sentence with the <code>root</code> forming it. If a <code>successor</code> has many <code>roots</code> can form it, replace it with the root with the shortest length.</p>
<p>You need to output the sentence after the replacement.</p>
<p><b>Example 1:</b></p>
<pre class="crayon:false"><b>Input:</b> dict = ["cat", "bat", "rat"]
sentence = "the cattle was rattled by the battery"
<b>Output:</b> "the cat was rat by the bat"
</pre>
<p><b>Note:</b></p>
<ol>
<li>The input will only have lower-case letters.</li>
<li>1 &lt;= dict words number &lt;= 1000</li>
<li>1 &lt;= sentence words number &lt;= 1000</li>
<li>1 &lt;= root length &lt;= 100</li>
<li>1 &lt;= sentence words length &lt;= 1000</li>
</ol>
<h1><strong>Solution 1: HashTable</strong></h1>
<p>Time complexity: O(sum(w^2))</p>
<p>Space complexity: O(sum(l))</p><pre class="crayon-plain-tag">// Author: Huahua, Running time: 84 ms
class Solution {
public:
  string replaceWords(vector&lt;string&gt;&amp; dict, string sentence) {
    unordered_set&lt;string&gt; d(begin(dict), end(dict));
    sentence.push_back(' ');
    string output;
    string word;
    bool found = false;
    for (char c : sentence) {
      if (c == ' ') {
        if (!output.empty()) output += ' ';
        output += word;
        word = "";
        found = false;
        continue;
      }
      if (found) continue;
      word += c;
      if (d.count(word)) {
        found = true;
      }
    }
    return output;
  }
};</pre><p></p>
<h2><strong>Solution2: Trie</strong></h2>
<p>Time complexity: O(sum(l) + n)</p>
<p>Space complexity: O(sum(l) * 26)</p><pre class="crayon-plain-tag">// Author: Huahua, running time: 48 ms
class TrieNode {
public:
  TrieNode(): children(26), is_word(false) {}
  ~TrieNode() {
    for (int i = 0; i &lt; 26; ++i)
      if (children[i]) {
        delete children[i];
        children[i] = nullptr;
      }
  }
  vector&lt;TrieNode*&gt; children;
  bool is_word;
};
class Solution {
public:
  string replaceWords(vector&lt;string&gt;&amp; dict, string sentence) {    
    TrieNode root;
    for (const string&amp; word : dict) {
      TrieNode* cur = &amp;root;
      for (char c : word) {        
        if (!cur-&gt;children[c - 'a']) cur-&gt;children[c - 'a'] = new TrieNode();
        cur = cur-&gt;children[c - 'a'];
      }
      cur-&gt;is_word = true;
    }
    
    string ans;
    stringstream ss(sentence);
    string word;
    while (ss &gt;&gt; word) {      
      TrieNode* cur = &amp;root;
      bool found = false;
      int len = 0;
      for (char c : word) {        
        cur = cur-&gt;children[c - 'a'];        
        if (!cur) break;
        ++len;
        if (cur-&gt;is_word) {
          found = true;
          break;
        }
      }      
      if (!ans.empty()) ans += ' ';      
      ans += found ? word.substr(0, len) : word;
    }
    return ans;
  }
};</pre><p>&nbsp;</p>
<p>&nbsp;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/string/leetcode-648-replace-words/">花花酱 LeetCode 648. Replace Words</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/string/leetcode-648-replace-words/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 745. Prefix and Suffix Search</title>
		<link>https://zxi.mytechroad.com/blog/tree/leetcode-745-prefix-and-suffix-search/</link>
					<comments>https://zxi.mytechroad.com/blog/tree/leetcode-745-prefix-and-suffix-search/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Mon, 11 Dec 2017 23:33:34 +0000</pubDate>
				<category><![CDATA[Hashtable]]></category>
		<category><![CDATA[String]]></category>
		<category><![CDATA[Tree]]></category>
		<category><![CDATA[prefix]]></category>
		<category><![CDATA[suffix]]></category>
		<category><![CDATA[trie]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=1184</guid>

					<description><![CDATA[<p>Link: https://leetcode.com/problems/prefix-and-suffix-search/description/ Problem: Given many words, words[i] has weight i. Design a class WordFilter that supports one function, WordFilter.f(String prefix, String suffix). It will return the word with given prefix and suffix with maximum weight. If no&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/tree/leetcode-745-prefix-and-suffix-search/">花花酱 LeetCode 745. Prefix and Suffix Search</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>Link: <a href="https://leetcode.com/problems/prefix-and-suffix-search/description/">https://leetcode.com/problems/prefix-and-suffix-search/description/</a></p>
<p><iframe width="500" height="375" src="https://www.youtube.com/embed/a-4WbFqalIA?feature=oembed" frameborder="0" gesture="media" allow="encrypted-media" allowfullscreen></iframe></p>
<p><strong>Problem:</strong></p>
<p>Given many <code>words</code>, <code>words[i]</code> has weight <code>i</code>.</p>
<p>Design a class <code>WordFilter</code> that supports one function, <code>WordFilter.f(String prefix, String suffix)</code>. It will return the word with given <code>prefix</code> and <code>suffix</code> with maximum weight. If no word exists, return -1.</p>
<p><b>Examples:</b></p><pre class="crayon-plain-tag">Input:
WordFilter([&quot;apple&quot;])
WordFilter.f(&quot;a&quot;, &quot;e&quot;) // returns 0
WordFilter.f(&quot;b&quot;, &quot;&quot;) // returns -1</pre><p><b>Note:</b></p>
<ol>
<li><code>words</code> has length in range <code>[1, 15000]</code>.</li>
<li>For each test case, up to <code>words.length</code> queries <code>WordFilter.f</code> may be made.</li>
<li><code>words[i]</code> has length in range <code>[1, 10]</code>.</li>
<li><code>prefix, suffix</code> have lengths in range <code>[0, 10]</code>.</li>
<li><code>words[i]</code> and <code>prefix, suffix</code> queries consist of lowercase letters only.</li>
</ol>
<p><strong>Idea:</strong></p>
<p>Construct all possible filters</p>
<p>&nbsp;</p>
<p><strong>Solution1:</strong></p>
<p>C++</p>
<p>Time complexity: O(NL^3 + QL)  where N is the number of words, L is the max length of the word, Q is the number of queries.</p>
<p>Space complexity: O(NL^3)</p><pre class="crayon-plain-tag">// Author: Huahua
// Runtime: 482 ms
class WordFilter {
public:
    WordFilter(const vector&lt;string&gt;&amp; words) {
        int index = 0;
        for (const string&amp; word : words) {
            int n = word.length();
            string prefix;
            for (int i = 0; i &lt;= n; ++i) {
                if (i &gt; 0) prefix += word[i - 1];
                string suffix;
                for (int j = n; j &gt;= 0; --j) {                    
                    if (j != n) suffix = word[j] + suffix;
                    const string key = prefix + "_" + suffix;
                    filters_[key] = index;                    
                }                
            }
            ++index;
        }
    }
    
    int f(string prefix, string suffix) {
        const string key = prefix + "_" + suffix;
        auto it = filters_.find(key);
        if (it != filters_.end()) return it-&gt;second;
        return -1;
    }
private:
    unordered_map&lt;string, int&gt; filters_;
};</pre><p>Version #2</p><pre class="crayon-plain-tag">// Author: Huahua
// Runtime: 499 ms
class WordFilter {
public:
    WordFilter(const vector&lt;string&gt;&amp; words) {
        int index = 0;
        for (const string&amp; word : words) {
            int n = word.length();
            vector&lt;string&gt; prefixes(n + 1, "");
            vector&lt;string&gt; suffixes(n + 1, "");
            for (int i = 0; i &lt; n; ++i) {
                prefixes[i + 1] = prefixes[i] + word[i];
                suffixes[i + 1] = word[n - i - 1] + suffixes[i];
            }
            
            for (const string&amp; prefix : prefixes)          
                for (const string&amp; suffix : suffixes)                              
                    filters_[prefix + "_" + suffix] = index;            
            ++index;
        }        
    }
    
    int f(string prefix, string suffix) {
        const string key = prefix + "_" + suffix;
        auto it = filters_.find(key);
        if (it != filters_.end()) return it-&gt;second;
        return -1;
    }
private:
    unordered_map&lt;string, int&gt; filters_;
};</pre><p><strong>Solution 2</strong>:</p>
<p>C++ / Trie</p>
<p>Time complexity: O(NL^2 + QL)  where N is the number of words, L is the max length of the word, Q is the number of queries.</p>
<p>Space complexity: O(NL^2)</p><pre class="crayon-plain-tag">// Author: Huahua
// Runtime: 572 ms
class Trie {
public:
    /** Initialize your data structure here. */
    Trie(): root_(new TrieNode()) {}
    
    /** Inserts a word into the trie. */
    void insert(const string&amp; word, int index) {
        TrieNode* p = root_.get();
        for (const char c : word) {            
            if (!p-&gt;children[c - 'a'])
                p-&gt;children[c - 'a'] = new TrieNode();
            p = p-&gt;children[c - 'a'];
            // Update index
            p-&gt;index = index;
        }
        p-&gt;is_word = true;
    }
    
    
    /** Returns the index of word that has the prefix. */
    int startsWith(const string&amp; prefix) const {
        auto node = find(prefix);
        if (!node) return -1;
        return node-&gt;index;
    }
private:
    struct TrieNode {
        TrieNode():index(-1), is_word(false), children(27, nullptr){}
        
        ~TrieNode() {
            for (TrieNode* child : children)
                if (child) delete child;
        }
        
        int index;
        int is_word;
        vector&lt;TrieNode*&gt; children;
    };
    
    const TrieNode* find(const string&amp; prefix) const {
        const TrieNode* p = root_.get();
        for (const char c : prefix) {
            p = p-&gt;children[c - 'a'];
            if (p == nullptr) break;
        }
        return p;
    }
    
    std::unique_ptr&lt;TrieNode&gt; root_;
};

class WordFilter {
public:
    WordFilter(vector&lt;string&gt; words) {        
        for (int i = 0; i &lt; words.size(); ++i) {
            const string&amp; w = words[i];            
            string key = "{" + w;
            trie_.insert(key, i);            
            for (int j = 0; j &lt; w.size(); ++j) {
                key = w[w.size() - j - 1] + key;                
                trie_.insert(key, i);
            }
        }
    }
    
    int f(string prefix, string suffix) {        
        return trie_.startsWith(suffix + "{" + prefix);
    }
private:
    Trie trie_;
};</pre><p><strong>Related Problems:</strong></p>
<ul>
<li><a href="http://zxi.mytechroad.com/blog/hashtable/leetcode-676-implement-magic-dictionary/">[解题报告] LeetCode 676. Implement Magic Dictionary</a></li>
<li><a href="http://zxi.mytechroad.com/blog/data-structure/leetcode-208-implement-trie-prefix-tree/">[解题报告] LeetCode 208. Implement Trie (Prefix Tree)</a></li>
</ul>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/tree/leetcode-745-prefix-and-suffix-search/">花花酱 LeetCode 745. Prefix and Suffix Search</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/tree/leetcode-745-prefix-and-suffix-search/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 720. Longest Word in Dictionary</title>
		<link>https://zxi.mytechroad.com/blog/string/leetcode-720-longest-word-in-dictionary/</link>
					<comments>https://zxi.mytechroad.com/blog/string/leetcode-720-longest-word-in-dictionary/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Fri, 17 Nov 2017 04:41:55 +0000</pubDate>
				<category><![CDATA[Easy]]></category>
		<category><![CDATA[String]]></category>
		<category><![CDATA[prefix]]></category>
		<category><![CDATA[trie]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=819</guid>

					<description><![CDATA[<p>Given a list of strings words representing an English Dictionary, find the longest word in words that can be built one character at a time by other words in words.&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/string/leetcode-720-longest-word-in-dictionary/">花花酱 LeetCode 720. Longest Word in Dictionary</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/TqrZg4wYP1U?feature=oembed" frameborder="0" gesture="media" allow="encrypted-media" allowfullscreen></iframe></p>
<p>Given a list of strings <code>words</code> representing an English Dictionary, find the longest word in <code>words</code> that can be built one character at a time by other words in <code>words</code>. If there is more than one possible answer, return the longest word with the smallest lexicographical order.</p>
<p>If there is no answer, return the empty string.</p>
<p><b>Example 1:</b></p><pre class="crayon-plain-tag">Input: 
words = [&quot;w&quot;,&quot;wo&quot;,&quot;wor&quot;,&quot;worl&quot;, &quot;world&quot;]
Output: &quot;world&quot;
Explanation: 
The word &quot;world&quot; can be built one character at a time by &quot;w&quot;, &quot;wo&quot;, &quot;wor&quot;, and &quot;worl&quot;.</pre><p><b>Example 2:</b></p><pre class="crayon-plain-tag">Input: 
words = [&quot;a&quot;, &quot;banana&quot;, &quot;app&quot;, &quot;appl&quot;, &quot;ap&quot;, &quot;apply&quot;, &quot;apple&quot;]
Output: &quot;apple&quot;
Explanation: 
Both &quot;apply&quot; and &quot;apple&quot; can be built from other words in the dictionary. 
However, &quot;apple&quot; is lexicographically smaller than &quot;apply&quot;.</pre><p><b>Note:</b></p>
<p>&nbsp;</p>
<ul>
<li>All the strings in the input will only contain lowercase letters.</li>
<li>The length of <code>words</code> will be in the range <code>[1, 1000]</code>.</li>
<li>The length of <code>words[i]</code> will be in the range <code>[1, 30]</code>.</li>
</ul>
<p><strong>Idea:</strong></p>
<p>Brute force</p>
<p>Trie</p>
<p><a href="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/11/720-ep109.png"><img class="alignnone size-full wp-image-828" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/11/720-ep109.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2017/11/720-ep109.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/11/720-ep109-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/11/720-ep109-768x432.png 768w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/11/720-ep109-624x351.png 624w" sizes="(max-width: 960px) 100vw, 960px" /></a></p>
<p><a href="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/11/720-ep109-1.png"><img class="alignnone size-full wp-image-827" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/11/720-ep109-1.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2017/11/720-ep109-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/11/720-ep109-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/11/720-ep109-1-768x432.png 768w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/11/720-ep109-1-624x351.png 624w" sizes="(max-width: 960px) 100vw, 960px" /></a></p>
<p><strong>Solution:</strong></p>
<p>C++</p><pre class="crayon-plain-tag">// Author: Huahua
// Runtime: 39 ms (better than 97.85%)
class Solution {
public:
    string longestWord(vector&lt;string&gt;&amp; words) {
        string best;        
        unordered_set&lt;string&gt; dict(words.begin(), words.end());
        
        for (const string&amp; word : words) {
            if (word.length() &lt; best.length() 
             || (word.length() == best.length() &amp;&amp; word &gt; best)) 
                continue;
            string prefix;
            bool valid = true;
            for (int i = 0; i &lt; word.length() - 1 &amp;&amp; valid; ++i) {
                prefix += word[i];
                if (!dict.count(prefix)) valid = false;
            }
            if (valid) best = word;
        }
        
        return best;
    }
};</pre><p>&nbsp;</p><pre class="crayon-plain-tag">// Author: Huahua
// Runtime: 46 ms
class Solution {
public:
    string longestWord(vector&lt;string&gt;&amp; words) {
        // Sort by length DESC, if there is a tie, sort by lexcial order.
        std::sort(words.begin(), words.end(), 
                  [](const string&amp; w1, const string&amp; w2){
                    if (w1.length() != w2.length()) 
                        return w1.length() &gt; w2.length();
                    return w1 &lt; w2;
                  });
        
        unordered_set&lt;string&gt; dict(words.begin(), words.end());
        
        for (const string&amp; word : words) {
            string prefix;
            bool valid = true;
            for (int i = 0; i &lt; word.length() - 1 &amp;&amp; valid; ++i) {
                prefix += word[i];
                if (!dict.count(prefix)) valid = false;
            }
            if (valid) return word;
        }
        
        return "";
    }
};</pre><p>&nbsp;</p>
<p>Trie + Sorting</p><pre class="crayon-plain-tag">// Author: Huahua
// Runtime: 49 ms
class Trie {
public:
    Trie(): root_(new TrieNode()) {}
    
    void insert(const string&amp; word) {
        TrieNode* p = root_.get();
        for (const char c : word) {
            if (!p-&gt;children[c - 'a'])
                p-&gt;children[c - 'a'] = new TrieNode();
            p = p-&gt;children[c - 'a'];
        }
        p-&gt;is_word = true;
    }
    
    bool hasAllPrefixes(const string&amp; word) {
        const TrieNode* p = root_.get();
        for (const char c : word) {
            if (!p-&gt;children[c - 'a']) return false;
            p = p-&gt;children[c - 'a'];
            if (!p-&gt;is_word) return false;
        }
        return true;
    }    
private:
    struct TrieNode {
        TrieNode():is_word(false), children(26, nullptr){}
        
        ~TrieNode() {
            for (auto node : children)
                delete node;
        }
        
        bool is_word;
        vector&lt;TrieNode*&gt; children;
    };
    
    std::unique_ptr&lt;TrieNode&gt; root_;
};

class Solution {
public:
    string longestWord(vector&lt;string&gt;&amp; words) {
        std::sort(words.begin(), words.end(), 
          [](const string&amp; w1, const string&amp; w2){
            if (w1.length() != w2.length()) 
                return w1.length() &gt; w2.length();
            return w1 &lt; w2;
          });
            
        Trie trie;
        for (const string&amp; word : words)
            trie.insert(word);
                
        for (const string&amp; word : words)
            if (trie.hasAllPrefixes(word)) return word;  
        
        return "";
    }
};</pre><p>&nbsp;</p>
<p>Trie + No sorting</p><pre class="crayon-plain-tag">// Author: Huahua
// Runtime: 56 ms
class Trie {
public:
    Trie(): root_(new TrieNode()) {}
    
    void insert(const string&amp; word) {
        TrieNode* p = root_.get();
        for (const char c : word) {
            if (!p-&gt;children[c - 'a'])
                p-&gt;children[c - 'a'] = new TrieNode();
            p = p-&gt;children[c - 'a'];
        }
        p-&gt;is_word = true;
    }
    
    bool hasAllPrefixes(const string&amp; word) {
        const TrieNode* p = root_.get();
        for (const char c : word) {
            if (!p-&gt;children[c - 'a']) return false;
            p = p-&gt;children[c - 'a'];
            if (!p-&gt;is_word) return false;
        }
        return true;
    }    
private:
    struct TrieNode {
        TrieNode():is_word(false), children(26, nullptr){}
        
        ~TrieNode() {
            for (auto node : children)
                delete node;
        }
        
        bool is_word;
        vector&lt;TrieNode*&gt; children;
    };
    
    std::unique_ptr&lt;TrieNode&gt; root_;
};

class Solution {
public:
    string longestWord(vector&lt;string&gt;&amp; words) {
        Trie trie;
        for (const string&amp; word : words)
            trie.insert(word);
        
        string best;
        for (const string&amp; word : words) {
            if (word.length() &lt; best.length() 
            || (word.length() == best.length() &amp;&amp; word &gt; best))
                continue;
            if (trie.hasAllPrefixes(word))
                best = word;
        }
        
        return best;
    }
};</pre><p>&nbsp;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/string/leetcode-720-longest-word-in-dictionary/">花花酱 LeetCode 720. Longest Word in Dictionary</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/string/leetcode-720-longest-word-in-dictionary/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 208. Implement Trie (Prefix Tree)</title>
		<link>https://zxi.mytechroad.com/blog/data-structure/leetcode-208-implement-trie-prefix-tree/</link>
					<comments>https://zxi.mytechroad.com/blog/data-structure/leetcode-208-implement-trie-prefix-tree/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Thu, 28 Sep 2017 05:23:38 +0000</pubDate>
				<category><![CDATA[Data Structure]]></category>
		<category><![CDATA[children]]></category>
		<category><![CDATA[hashtable]]></category>
		<category><![CDATA[prefix]]></category>
		<category><![CDATA[prefix tree]]></category>
		<category><![CDATA[trie]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=440</guid>

					<description><![CDATA[<p>Problem: Implement a trie with insert, search, and startsWith methods. Note: You may assume that all inputs are consist of lowercase letters a-z. Idea: Tree/children array &#160; &#160; Solution: C++&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/data-structure/leetcode-208-implement-trie-prefix-tree/">花花酱 LeetCode 208. Implement Trie (Prefix Tree)</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/f48wGD-MuQw?feature=oembed" frameborder="0" gesture="media" allowfullscreen></iframe></p>
<p><strong>Problem:</strong></p>
<p>Implement a trie with <code>insert</code>, <code>search</code>, and <code>startsWith</code> methods.</p>
<p><b>Note:</b><br />
You may assume that all inputs are consist of lowercase letters <code>a-z</code>.</p>
<p><strong>Idea:</strong></p>
<p><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script><br />
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-2404451723245401"
     data-ad-slot="7983117522"></ins><br />
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script><br />
Tree/children array</p>
<p><a href="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/208-ep74-1.png"><img class="alignnone size-full wp-image-445" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/208-ep74-1.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/208-ep74-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/208-ep74-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/208-ep74-1-768x432.png 768w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/208-ep74-1-624x351.png 624w" sizes="(max-width: 960px) 100vw, 960px" /></a></p>
<p>&nbsp;</p>
<p><a href="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/208-ep74-2.png"><img class="alignnone size-full wp-image-444" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/208-ep74-2.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/208-ep74-2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/208-ep74-2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/208-ep74-2-768x432.png 768w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/208-ep74-2-624x351.png 624w" sizes="(max-width: 960px) 100vw, 960px" /></a></p>
<p>&nbsp;</p>
<p><strong>Solution:</strong></p>
<p>C++ / Array</p><pre class="crayon-plain-tag">// Author: Huahua 
// Running time: 99 ms
class Trie {
public:
    /** Initialize your data structure here. */
    Trie(): root_(new TrieNode()) {}
    
    /** Inserts a word into the trie. */
    void insert(const string&amp; word) {
        TrieNode* p = root_.get();
        for (const char c : word) {
            if (!p-&gt;children[c - 'a'])
                p-&gt;children[c - 'a'] = new TrieNode();
            p = p-&gt;children[c - 'a'];
        }
        p-&gt;is_word = true;
    }
    
    /** Returns if the word is in the trie. */
    bool search(const string&amp; word) const {
        const TrieNode* p = find(word);
        return p &amp;&amp; p-&gt;is_word;
    }
    
    /** Returns if there is any word in the trie that starts with the given prefix. */
    bool startsWith(const string&amp; prefix) const {
        return find(prefix) != nullptr;
    }
private:
    struct TrieNode {
        TrieNode():is_word(false), children(26, nullptr){}
        
        ~TrieNode() {
            for (TrieNode* child : children)
                if (child) delete child;
        }
               
        bool is_word;
        vector&lt;TrieNode*&gt; children;
    };
    
    const TrieNode* find(const string&amp; prefix) const {
        const TrieNode* p = root_.get();
        for (const char c : prefix) {
            p = p-&gt;children[c - 'a'];
            if (p == nullptr) break;
        }
        return p;
    }
    
    std::unique_ptr&lt;TrieNode&gt; root_;
};</pre><p>&nbsp;</p>
<p>C++ / hashmap</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 98 ms
class Trie {
public:
    /** Initialize your data structure here. */
    Trie(): root_(new TrieNode()) {}
    
    /** Inserts a word into the trie. */
    void insert(const string&amp; word) {
        TrieNode* p = root_.get();
        for (const char c : word) {
            if (!p-&gt;children.count(c))
                p-&gt;children[c] = new TrieNode();
            p = p-&gt;children[c];
        }
        p-&gt;is_word = true;
    }
    
    /** Returns if the word is in the trie. */
    bool search(const string&amp; word) const {
        const TrieNode* p = find(word);
        return p &amp;&amp; p-&gt;is_word;
    }
    
    /** Returns if there is any word in the trie that starts with the given prefix. */
    bool startsWith(const string&amp; prefix) const {
        return find(prefix) != nullptr;
    }
private:
    struct TrieNode {
        TrieNode():is_word(false){}
        
        ~TrieNode() {
            for (auto&amp; kv : children)
                if (kv.second) delete kv.second;
        }
        
        bool is_word;
        unordered_map&lt;char, TrieNode*&gt; children;
    };
    
    const TrieNode* find(const string&amp; prefix) const {
        const TrieNode* p = root_.get();
        for (const char c : prefix) {
            if (!p-&gt;children.count(c)) return nullptr;
            p = p-&gt;children.at(c);
        }
        return p;
    }
    
    std::unique_ptr&lt;TrieNode&gt; root_;
};</pre><p>&nbsp;</p>
<p>Java</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 184 ms
class Trie {
    class TrieNode {
        public TrieNode() {
            children = new TrieNode[26];
            is_word = false;
        }
        public boolean is_word;
        public TrieNode[] children;
    }
    
    private TrieNode root;
    
    /** Initialize your data structure here. */
    public Trie() {
        root = new TrieNode();
    }
    
    /** Inserts a word into the trie. */
    public void insert(String word) {
        TrieNode p = root;
        for (int i = 0; i &lt; word.length(); i++) {
            int index = (int)(word.charAt(i) - 'a');
            if (p.children[index] == null)
                p.children[index] = new TrieNode();
            p = p.children[index];
        }
        p.is_word = true;
    }
    
    /** Returns if the word is in the trie. */
    public boolean search(String word) {
        TrieNode node = find(word);
        return node != null &amp;&amp; node.is_word;
    }
    
    /** Returns if there is any word in the trie that starts with the given prefix. */
    public boolean startsWith(String prefix) {
        TrieNode node = find(prefix);
        return node != null;
    }
    
    private TrieNode find(String prefix) {
        TrieNode p = root;
        for(int i = 0; i &lt; prefix.length(); i++) {
            int index = (int)(prefix.charAt(i) - 'a');
            if (p.children[index] == null) return null;
            p = p.children[index];
        }
        return p;
    }
}</pre><p>&nbsp;</p>
<p>Python 1:</p><pre class="crayon-plain-tag">"""
Author: Huahua
Running time: 469 ms
"""
class Trie(object):
    class TrieNode(object):
        def __init__(self):
            self.is_word = False
            self.children = [None] * 26
        
    def __init__(self):
        self.root = Trie.TrieNode()
        

    def insert(self, word):
        p = self.root
        for c in word:
            index = ord(c) - ord('a')
            if not p.children[index]: 
                p.children[index] = Trie.TrieNode()
            p = p.children[index]
        p.is_word = True

    def search(self, word):
        node = self.find(word)
        return node is not None and node.is_word
        

    def startsWith(self, prefix):
        return self.find(prefix) is not None
    
    def find(self, prefix):
        p = self.root
        for c in prefix:
            index = ord(c) - ord('a')
            if not p.children[index]: return None
            p = p.children[index]
        return p</pre><p>&nbsp;</p>
<p>Python 2:</p><pre class="crayon-plain-tag">"""
Author: Huahua
Running time: 212 ms
"""
class Trie(object):            
    def __init__(self):
        self.root = {}
        

    def insert(self, word):
        p = self.root
        for c in word:            
            if c not in p: 
                p[c] = {}
            p = p[c]
        p['#'] = True

    def search(self, word):
        node = self.find(word)
        return node is not None and '#' in node
        

    def startsWith(self, prefix):
        return self.find(prefix) is not None
    
    def find(self, prefix):
        p = self.root
        for c in prefix:            
            if c not in p: return None
            p = p[c]
        return p</pre><p>&nbsp;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/data-structure/leetcode-208-implement-trie-prefix-tree/">花花酱 LeetCode 208. Implement Trie (Prefix Tree)</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/data-structure/leetcode-208-implement-trie-prefix-tree/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 677. Map Sum Pairs</title>
		<link>https://zxi.mytechroad.com/blog/tree/leetcode-677-map-sum-pairs/</link>
					<comments>https://zxi.mytechroad.com/blog/tree/leetcode-677-map-sum-pairs/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Mon, 18 Sep 2017 07:23:25 +0000</pubDate>
				<category><![CDATA[Data Structure]]></category>
		<category><![CDATA[Tree]]></category>
		<category><![CDATA[hashtable]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[prefix]]></category>
		<category><![CDATA[sum]]></category>
		<category><![CDATA[trie]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=331</guid>

					<description><![CDATA[<p>https://leetcode.com/problems/map-sum-pairs/description/ Problem: Implement a MapSum class with insert, and sum methods. For the method insert, you&#8217;ll be given a pair of (string, integer). The string represents the key and&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/tree/leetcode-677-map-sum-pairs/">花花酱 LeetCode 677. Map Sum Pairs</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/FYluJaicnlY?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<p><a href="https://leetcode.com/problems/map-sum-pairs/description/">https://leetcode.com/problems/map-sum-pairs/description/</a></p>
<p><strong>Problem:</strong></p>
<p>Implement a MapSum class with <code>insert</code>, and <code>sum</code> methods.</p>
<p>For the method <code>insert</code>, you&#8217;ll be given a pair of (string, integer). The string represents the key and the integer represents the value. If the key already existed, then the original key-value pair will be overridden to the new one.</p>
<p>For the method <code>sum</code>, you&#8217;ll be given a string representing the prefix, and you need to return the sum of all the pairs&#8217; value whose key starts with the prefix.</p>
<p><b>Example 1:</b></p><pre class="crayon-plain-tag">Input: insert(&quot;apple&quot;, 3), Output: Null
Input: sum(&quot;ap&quot;), Output: 3
Input: insert(&quot;app&quot;, 2), Output: Null
Input: sum(&quot;ap&quot;), Output: 5</pre><p><strong>Idea:</strong></p>
<p>Prefix tree</p>
<p><a href="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/677-ep61-1.png"><img class="alignnone size-full wp-image-336" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/677-ep61-1.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/677-ep61-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/677-ep61-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/677-ep61-1-768x432.png 768w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/677-ep61-1-624x351.png 624w" sizes="(max-width: 960px) 100vw, 960px" /></a><a href="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/677-ep61-2.png"><img class="alignnone size-full wp-image-335" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/677-ep61-2.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/677-ep61-2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/677-ep61-2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/677-ep61-2-768x432.png 768w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/677-ep61-2-624x351.png 624w" sizes="(max-width: 960px) 100vw, 960px" /></a><a href="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/677-ep61-3.png"><img class="alignnone size-full wp-image-334" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/677-ep61-3.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/677-ep61-3.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/677-ep61-3-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/677-ep61-3-768x432.png 768w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/677-ep61-3-624x351.png 624w" sizes="(max-width: 960px) 100vw, 960px" /></a></p>
<p><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script><br />
<ins class="adsbygoogle" style="display: block; text-align: center;" data-ad-layout="in-article" data-ad-format="fluid" data-ad-client="ca-pub-2404451723245401" data-ad-slot="7983117522"></ins><br />
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></p>
<p><strong>Solution 1</strong></p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 3 ms
class MapSum {
public:
    /** Initialize your data structure here. */
    MapSum() {}
    
    void insert(const string&amp; key, int val) {
        int inc = val;
        if (vals_.count(key)) {
            inc -= vals_[key];
        }
        vals_[key] = val;
        for (int i = 1; i &lt;= key.length(); ++i)
            sums_[key.substr(0,i)] += inc;
    }
    
    int sum(const string&amp; prefix) {
        return sums_[prefix];
    }
private:
    unordered_map&lt;string, int&gt; vals_;
    unordered_map&lt;string, int&gt; sums_;    
};</pre><p><strong>Solution 2:</strong></p><pre class="crayon-plain-tag">class MapSum {
public:
    /** Initialize your data structure here. */
    MapSum() {}
    
    void insert(string key, int val) {
        int inc = val - vals_[key];
        Trie* p = &amp;root;
        for (const char c : key) {
            if (!p-&gt;children[c])
                p-&gt;children[c] = new Trie();
            p-&gt;children[c]-&gt;sum += inc;
            p = p-&gt;children[c];
        }
        vals_[key] = val;
    }
    
    int sum(string prefix) {
        Trie* p = &amp;root;
        for (const char c : prefix) {
            if (!p-&gt;children[c]) return 0;
            p = p-&gt;children[c];
        }        
        return p-&gt;sum;
    }
private:
    struct Trie {
        Trie():children(128, nullptr), sum(0){}
        ~Trie() {
            for (auto child : children)
                if (child) delete child;
            children.clear();
        }
        vector&lt;Trie*&gt; children;
        int sum;        
    };
    
    Trie root; // dummy root
    unordered_map&lt;string, int&gt; vals_; // key -&gt; val
};</pre><p>with std::unique_ptr</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 5 ms
class MapSum {
public:
    /** Initialize your data structure here. */
    MapSum(): root_(new Trie()) {}
  
    void insert(string key, int val) {      
      int inc = val - vals_[key];
      Trie* p = root_.get();
      for (const char c : key) {
        if (!p-&gt;children[c])
          p-&gt;children[c] = new Trie();
        p-&gt;children[c]-&gt;sum += inc;
        p = p-&gt;children[c];
      }
      vals_[key] = val;
    }
    
    int sum(string prefix) {
      Trie* p = root_.get();
      for (const char c : prefix) {
        if (!p-&gt;children[c]) return 0;
        p = p-&gt;children[c];
      }

      return p-&gt;sum;        
    }
private:
    struct Trie {
        Trie():children(128, nullptr), sum(0){}
        ~Trie() {
          for (auto child : children)
            if (child) {
              delete child;
              child = nullptr;
            }
          children.clear();
        }
        vector&lt;Trie*&gt; children;
        int sum;        
    };
    
    std::unique_ptr&lt;Trie&gt; root_;
    unordered_map&lt;string, int&gt; vals_; // key -&gt; val
};</pre><p>&nbsp;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/tree/leetcode-677-map-sum-pairs/">花花酱 LeetCode 677. Map Sum Pairs</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/tree/leetcode-677-map-sum-pairs/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 676. Implement Magic Dictionary</title>
		<link>https://zxi.mytechroad.com/blog/hashtable/leetcode-676-implement-magic-dictionary/</link>
					<comments>https://zxi.mytechroad.com/blog/hashtable/leetcode-676-implement-magic-dictionary/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 10 Sep 2017 21:00:40 +0000</pubDate>
				<category><![CDATA[Hashtable]]></category>
		<category><![CDATA[contains]]></category>
		<category><![CDATA[dict]]></category>
		<category><![CDATA[transform]]></category>
		<category><![CDATA[trie]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=227</guid>

					<description><![CDATA[<p>Problem: Implement a magic directory with buildDict, and search methods. For the method buildDict, you&#8217;ll be given a list of non-repetitive words to build a dictionary. For the method search,&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/hashtable/leetcode-676-implement-magic-dictionary/">花花酱 LeetCode 676. Implement Magic Dictionary</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/wq9XjoKMxek?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<p><strong>Problem:</strong></p>
<div class="question-description">
<p>Implement a magic directory with <code>buildDict</code>, and <code>search</code> methods.</p>
<p>For the method <code>buildDict</code>, you&#8217;ll be given a list of non-repetitive words to build a dictionary.</p>
<p>For the method <code>search</code>, you&#8217;ll be given a word, and judge whether if you modify <b>exactly</b> one character into <b>another</b> character in this word, the modified word is in the dictionary you just built.</p>
<p><b>Example 1:</b></p><pre class="crayon-plain-tag">Input: buildDict([&quot;hello&quot;, &quot;leetcode&quot;]), Output: Null
Input: search(&quot;hello&quot;), Output: False
Input: search(&quot;hhllo&quot;), Output: True
Input: search(&quot;hell&quot;), Output: False
Input: search(&quot;leetcoded&quot;), Output: False</pre><p><b>Note:</b></p>
<ol>
<li>You may assume that all the inputs are consist of lowercase letters <code>a-z</code>.</li>
<li>For contest purpose, the test data is rather small by now. You could think about highly efficient algorithm after the contest.</li>
<li>Please remember to <b>RESET</b> your class variables declared in class MagicDictionary, as static/class variables are <b>persisted across multiple test cases</b>. Please see <a href="https://leetcode.com/faq/#different-output">here</a> for more details.</li>
</ol>
</div>
<div id="interviewed-div"><strong>Idea:</strong></div>
<div></div>
<div>Fuzzy match</div>
<div></div>
<div><a href="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/676-ep49-1.png"><img class="alignnone size-full wp-image-231" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/676-ep49-1.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/676-ep49-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/676-ep49-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/676-ep49-1-768x432.png 768w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/676-ep49-1-624x351.png 624w" sizes="(max-width: 960px) 100vw, 960px" /></a></div>
<div></div>
<div><strong>Time Complexity:</strong></div>
<div>buildDict: O(n*m)</div>
<div>n: numbers of words</div>
<div>m: length of word</div>
<div></div>
<div>search: O(m)</div>
<div>m: length of word</div>
<div></div>
<div><strong>Space Complexity:</strong></div>
<div>O(n*m)</div>
<div></div>
<div><strong>Solution:</strong></div>
<div>
<pre class="crayon-plain-tag">// Author: Huahua
class MagicDictionary {
public:
    /** Initialize your data structure here. */
    MagicDictionary() {
        dict_.clear();
    }
    
    /** Build a dictionary through a list of words */
    void buildDict(vector&lt;string&gt; dict) {
        for(string&amp; word: dict) {
            for(int i = 0; i &lt; word.length(); ++i) {
                char c = word[i];
                word[i] = '*';
                dict_[word].insert(c);
                word[i] = c;
            }
        }
    }
    
    /** Returns if there is any word in the trie that equals to the given word after modifying exactly one character */
    bool search(string word) {
        for(int i = 0; i &lt; word.length(); ++i) {
            char c = word[i];
            word[i] = '*';
            if (dict_.count(word)) {
                const auto&amp; char_set = dict_[word];
                if (!char_set.count(c) || char_set.size() &gt; 1)
                    return true;
            }
            word[i] = c;
        }
        return false;
    }
private:
    unordered_map&lt;string, unordered_set&lt;char&gt;&gt; dict_;
};

/**
 * Your MagicDictionary object will be instantiated and called as such:
 * MagicDictionary obj = new MagicDictionary();
 * obj.buildDict(dict);
 * bool param_2 = obj.search(word);
 */</pre>
</div>
<p>Java / Trie</p><pre class="crayon-plain-tag">class MagicDictionary {
    private Trie root;    
    
    public MagicDictionary() {
        root = new Trie();
    } 
    
    public void buildDict(String[] dict) {
        for (String word : dict) {
            Trie curr = root;
            for (char c : word.toCharArray()) {                
                int index = c - 'a';
                if (curr.children[index] == null)
                    curr.children[index] = new Trie();
                curr = curr.children[index];
            }
            curr.ends = true;
        }
    }  
    
    public boolean search(String word) {
        char[] s = word.toCharArray();
        for(int i = 0; i &lt; s.length; i++) {
            for (char c = 'a'; c &lt;= 'z'; ++c) {
                if (s[i] == c) continue;
                char tmp = s[i];
                s[i] = c;
                if (contains(s)) return true;
                s[i] = tmp;
            }
        }
        return false;
    }
    
    private boolean contains(char[] word) {        
        Trie curr = root;
        for (int i = 0; i &lt; word.length; ++i) {
            curr = curr.children[word[i] - 'a'];
            if (curr == null) return false;            
        }
        return curr.ends;
    }
    
    class Trie {
        private boolean ends;
        private Trie[] children;
        public Trie() {
            children = new Trie[26];
            ends = false;
        }
    }
}</pre><p>Java / Trie v2</p><pre class="crayon-plain-tag">class MagicDictionary {
    private Trie root;    
    
    public MagicDictionary() {
        root = new Trie();
    } 
    
    public void buildDict(String[] dict) {
        for (String word : dict) {
            Trie curr = root;
            for (char c : word.toCharArray()) {                
                int index = c - 'a';
                if (curr.children[index] == null)
                    curr.children[index] = new Trie();
                curr = curr.children[index];
            }
            curr.ends = true;
        }
    }  
    
    public boolean search(String word) {
        char[] s = word.toCharArray();
        Trie prefix = root;
        for(int i = 0; i &lt; s.length; i++) {
            for (char c = 'a'; c &lt;= 'z'; ++c) {
                if (s[i] == c) continue;
                char tmp = s[i];
                s[i] = c;
                if (contains(s, prefix, i)) return true;
                s[i] = tmp;                
            }
            prefix = prefix.children[s[i] - 'a'];
            if (prefix == null) return false;
        }
        return false;
    }
    
    private boolean contains(char[] word, Trie prefix, int s) {        
        Trie curr = prefix;
        for (int i = s; i &lt; word.length; ++i) {
            curr = curr.children[word[i] - 'a'];
            if (curr == null) return false;
        }
        return curr.ends;
    }
    
    class Trie {
        private boolean ends;
        private Trie[] children;
        public Trie() {
            children = new Trie[26];
            ends = false;
        }
    }
}</pre><p>&nbsp;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/hashtable/leetcode-676-implement-magic-dictionary/">花花酱 LeetCode 676. Implement Magic Dictionary</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-676-implement-magic-dictionary/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
