<?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>design Archives - Huahua&#039;s Tech Road</title>
	<atom:link href="https://zxi.mytechroad.com/blog/tag/design/feed/" rel="self" type="application/rss+xml" />
	<link>https://zxi.mytechroad.com/blog/tag/design/</link>
	<description></description>
	<lastBuildDate>Sun, 17 Apr 2022 05:47:26 +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>design Archives - Huahua&#039;s Tech Road</title>
	<link>https://zxi.mytechroad.com/blog/tag/design/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>花花酱 LeetCode 2241. Design an ATM Machine</title>
		<link>https://zxi.mytechroad.com/blog/desgin/leetcode-2241-design-an-atm-machine/</link>
					<comments>https://zxi.mytechroad.com/blog/desgin/leetcode-2241-design-an-atm-machine/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 17 Apr 2022 05:46:46 +0000</pubDate>
				<category><![CDATA[Desgin]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[medium]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=9659</guid>

					<description><![CDATA[<p>There is an ATM machine that stores banknotes of&#160;5&#160;denominations:&#160;20,&#160;50,&#160;100,&#160;200, and&#160;500&#160;dollars. Initially the ATM is empty. The user can use the machine to deposit or withdraw&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/desgin/leetcode-2241-design-an-atm-machine/">花花酱 LeetCode 2241. Design an ATM Machine</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>There is an ATM machine that stores banknotes of&nbsp;<code>5</code>&nbsp;denominations:&nbsp;<code>20</code>,&nbsp;<code>50</code>,&nbsp;<code>100</code>,&nbsp;<code>200</code>, and&nbsp;<code>500</code>&nbsp;dollars. Initially the ATM is empty. The user can use the machine to deposit or withdraw any amount of money.</p>



<p>When withdrawing, the machine prioritizes using banknotes of&nbsp;<strong>larger</strong>&nbsp;values.</p>



<ul><li>For example, if you want to withdraw&nbsp;<code>$300</code>&nbsp;and there are&nbsp;<code>2</code>&nbsp;<code>$50</code>&nbsp;banknotes,&nbsp;<code>1</code>&nbsp;<code>$100</code>&nbsp;banknote, and&nbsp;<code>1</code>&nbsp;<code>$200</code>&nbsp;banknote, then the machine will use the&nbsp;<code>$100</code>&nbsp;and&nbsp;<code>$200</code>&nbsp;banknotes.</li><li>However, if you try to withdraw&nbsp;<code>$600</code>&nbsp;and there are&nbsp;<code>3</code>&nbsp;<code>$200</code>&nbsp;banknotes and&nbsp;<code>1</code>&nbsp;<code>$500</code>&nbsp;banknote, then the withdraw request will be rejected because the machine will first try to use the&nbsp;<code>$500</code>&nbsp;banknote and then be unable to use banknotes to complete the remaining&nbsp;<code>$100</code>. Note that the machine is&nbsp;<strong>not</strong>&nbsp;allowed to use the&nbsp;<code>$200</code>&nbsp;banknotes instead of the&nbsp;<code>$500</code>&nbsp;banknote.</li></ul>



<p>Implement the ATM class:</p>



<ul><li><code>ATM()</code>&nbsp;Initializes the ATM object.</li><li><code>void deposit(int[] banknotesCount)</code>&nbsp;Deposits new banknotes in the order&nbsp;<code>$20</code>,&nbsp;<code>$50</code>,&nbsp;<code>$100</code>,&nbsp;<code>$200</code>, and&nbsp;<code>$500</code>.</li><li><code>int[] withdraw(int amount)</code>&nbsp;Returns an array of length&nbsp;<code>5</code>&nbsp;of the number of banknotes that will be handed to the user in the order&nbsp;<code>$20</code>,&nbsp;<code>$50</code>,&nbsp;<code>$100</code>,&nbsp;<code>$200</code>, and&nbsp;<code>$500</code>, and update the number of banknotes in the ATM after withdrawing. Returns&nbsp;<code>[-1]</code>&nbsp;if it is not possible (do&nbsp;<strong>not</strong>&nbsp;withdraw any banknotes in this case).</li></ul>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input</strong>
["ATM", "deposit", "withdraw", "deposit", "withdraw", "withdraw"]
[[], [[0,0,1,2,1]], [600], [[0,1,0,1,1]], [600], [550]]
<strong>Output</strong>
[null, null, [0,0,1,0,1], null, [-1], [0,1,0,0,1]]

<strong>Explanation</strong>
ATM atm = new ATM();
atm.deposit([0,0,1,2,1]); // Deposits 1 $100 banknote, 2 $200 banknotes,
                          // and 1 $500 banknote.
atm.withdraw(600);        // Returns [0,0,1,0,1]. The machine uses 1 $100 banknote
                          // and 1 $500 banknote. The banknotes left over in the
                          // machine are [0,0,0,2,0].
atm.deposit([0,1,0,1,1]); // Deposits 1 $50, $200, and $500 banknote.
                          // The banknotes in the machine are now [0,1,0,3,1].
atm.withdraw(600);        // Returns [-1]. The machine will try to use a $500 banknote
                          // and then be unable to complete the remaining $100,
                          // so the withdraw request will be rejected.
                          // Since the request is rejected, the number of banknotes
                          // in the machine is not modified.
atm.withdraw(550);        // Returns [0,1,0,0,1]. The machine uses 1 $50 banknote
                          // and 1 $500 banknote.</pre>



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



<ul><li><code>banknotesCount.length == 5</code></li><li><code>0 &lt;= banknotesCount[i] &lt;= 10<sup>9</sup></code></li><li><code>1 &lt;= amount &lt;= 10<sup>9</sup></code></li><li>At most&nbsp;<code>5000</code>&nbsp;calls&nbsp;<strong>in total</strong>&nbsp;will be made to&nbsp;<code>withdraw</code>&nbsp;and&nbsp;<code>deposit</code>.</li><li>At least&nbsp;<strong>one</strong>&nbsp;call will be made to each function&nbsp;<code>withdraw</code>&nbsp;and&nbsp;<code>deposit</code>.</li></ul>



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



<p>Follow the rules. Note: total count can be very large, use long instead.</p>



<p>Time complexity: O(1)<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
constexpr int kNotes = 5;
constexpr long notes[kNotes] = {20, 50, 100, 200, 500};

class ATM {
public:
  ATM(): counts(kNotes) {}

  void deposit(vector&lt;int&gt; banknotesCount) {
    for (int i = 0; i &lt; kNotes; ++i)
      counts[i] += banknotesCount[i];
  }

  vector&lt;int&gt; withdraw(int amount) {
    vector&lt;int&gt; ans(kNotes);
    vector&lt;long&gt; tmp(counts);
    for (int i = kNotes - 1; i &gt;= 0; --i)
      if (amount &gt;= notes[i]) {
        int c = min(counts[i], amount / notes[i]);
        ans[i] = c;
        amount -= c * notes[i];
        tmp[i] -= c;
      }
    if (amount != 0) return {-1};
    counts.swap(tmp);
    return ans;
  }
private:
  vector&lt;long&gt; counts;  
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/desgin/leetcode-2241-design-an-atm-machine/">花花酱 LeetCode 2241. Design an ATM Machine</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/desgin/leetcode-2241-design-an-atm-machine/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1912. Design Movie Rental System</title>
		<link>https://zxi.mytechroad.com/blog/data-structure/leetcode-1912-design-movie-rental-system/</link>
					<comments>https://zxi.mytechroad.com/blog/data-structure/leetcode-1912-design-movie-rental-system/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sat, 01 Jan 2022 23:40:32 +0000</pubDate>
				<category><![CDATA[Data Structure]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[hashtable]]></category>
		<category><![CDATA[treeset]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=9387</guid>

					<description><![CDATA[<p>You have a movie renting company consisting of&#160;n&#160;shops. You want to implement a renting system that supports searching for, booking, and returning movies. The system&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/data-structure/leetcode-1912-design-movie-rental-system/">花花酱 LeetCode 1912. Design Movie Rental 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[
<p>You have a movie renting company consisting of&nbsp;<code>n</code>&nbsp;shops. You want to implement a renting system that supports searching for, booking, and returning movies. The system should also support generating a report of the currently rented movies.</p>



<p>Each movie is given as a 2D integer array&nbsp;<code>entries</code>&nbsp;where&nbsp;<code>entries[i] = [shop<sub>i</sub>, movie<sub>i</sub>, price<sub>i</sub>]</code>&nbsp;indicates that there is a copy of movie&nbsp;<code>movie<sub>i</sub></code>&nbsp;at shop&nbsp;<code>shop<sub>i</sub></code>&nbsp;with a rental price of&nbsp;<code>price<sub>i</sub></code>. Each shop carries&nbsp;<strong>at most one</strong>&nbsp;copy of a movie&nbsp;<code>movie<sub>i</sub></code>.</p>



<p>The system should support the following functions:</p>



<ul><li><strong>Search</strong>: Finds the&nbsp;<strong>cheapest 5 shops</strong>&nbsp;that have an&nbsp;<strong>unrented copy</strong>&nbsp;of a given movie. The shops should be sorted by&nbsp;<strong>price</strong>&nbsp;in ascending order, and in case of a tie, the one with the&nbsp;<strong>smaller&nbsp;</strong><code>shop<sub>i</sub></code>&nbsp;should appear first. If there are less than 5 matching shops, then all of them should be returned. If no shop has an unrented copy, then an empty list should be returned.</li><li><strong>Rent</strong>: Rents an&nbsp;<strong>unrented copy</strong>&nbsp;of a given movie from a given shop.</li><li><strong>Drop</strong>: Drops off a&nbsp;<strong>previously rented copy</strong>&nbsp;of a given movie at a given shop.</li><li><strong>Report</strong>: Returns the&nbsp;<strong>cheapest 5 rented movies</strong>&nbsp;(possibly of the same movie ID) as a 2D list&nbsp;<code>res</code>&nbsp;where&nbsp;<code>res[j] = [shop<sub>j</sub>, movie<sub>j</sub>]</code>&nbsp;describes that the&nbsp;<code>j<sup>th</sup></code>&nbsp;cheapest rented movie&nbsp;<code>movie<sub>j</sub></code>&nbsp;was rented from the shop&nbsp;<code>shop<sub>j</sub></code>. The movies in&nbsp;<code>res</code>&nbsp;should be sorted by&nbsp;<strong>price&nbsp;</strong>in ascending order, and in case of a tie, the one with the&nbsp;<strong>smaller&nbsp;</strong><code>shop<sub>j</sub></code>&nbsp;should appear first, and if there is still tie, the one with the&nbsp;<strong>smaller&nbsp;</strong><code>movie<sub>j</sub></code>&nbsp;should appear first. If there are fewer than 5 rented movies, then all of them should be returned. If no movies are currently being rented, then an empty list should be returned.</li></ul>



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



<ul><li><code>MovieRentingSystem(int n, int[][] entries)</code>&nbsp;Initializes the&nbsp;<code>MovieRentingSystem</code>&nbsp;object with&nbsp;<code>n</code>&nbsp;shops and the movies in&nbsp;<code>entries</code>.</li><li><code>List&lt;Integer&gt; search(int movie)</code>&nbsp;Returns a list of shops that have an&nbsp;<strong>unrented copy</strong>&nbsp;of the given&nbsp;<code>movie</code>&nbsp;as described above.</li><li><code>void rent(int shop, int movie)</code>&nbsp;Rents the given&nbsp;<code>movie</code>&nbsp;from the given&nbsp;<code>shop</code>.</li><li><code>void drop(int shop, int movie)</code>&nbsp;Drops off a previously rented&nbsp;<code>movie</code>&nbsp;at the given&nbsp;<code>shop</code>.</li><li><code>List&lt;List&lt;Integer&gt;&gt; report()</code>&nbsp;Returns a list of cheapest&nbsp;<strong>rented</strong>&nbsp;movies as described above.</li></ul>



<p><strong>Note:</strong>&nbsp;The test cases will be generated such that&nbsp;<code>rent</code>&nbsp;will only be called if the shop has an&nbsp;<strong>unrented</strong>&nbsp;copy of the movie, and&nbsp;<code>drop</code>&nbsp;will only be called if the shop had&nbsp;<strong>previously rented</strong>&nbsp;out the movie.</p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input</strong>
["MovieRentingSystem", "search", "rent", "rent", "report", "drop", "search"]
[[3, [[0, 1, 5], [0, 2, 6], [0, 3, 7], [1, 1, 4], [1, 2, 7], [2, 1, 5]]], [1], [0, 1], [1, 2], [], [1, 2], [2]]
<strong>Output</strong>
[null, [1, 0, 2], null, null, [[0, 1], [1, 2]], null, [0, 1]]

<strong>Explanation</strong>
MovieRentingSystem movieRentingSystem = new MovieRentingSystem(3, [[0, 1, 5], [0, 2, 6], [0, 3, 7], [1, 1, 4], [1, 2, 7], [2, 1, 5]]);
movieRentingSystem.search(1);  // return [1, 0, 2], Movies of ID 1 are unrented at shops 1, 0, and 2. Shop 1 is cheapest; shop 0 and 2 are the same price, so order by shop number.
movieRentingSystem.rent(0, 1); // Rent movie 1 from shop 0. Unrented movies at shop 0 are now [2,3].
movieRentingSystem.rent(1, 2); // Rent movie 2 from shop 1. Unrented movies at shop 1 are now [1].
movieRentingSystem.report();   // return [[0, 1], [1, 2]]. Movie 1 from shop 0 is cheapest, followed by movie 2 from shop 1.
movieRentingSystem.drop(1, 2); // Drop off movie 2 at shop 1. Unrented movies at shop 1 are now [1,2].
movieRentingSystem.search(2);  // return [0, 1]. Movies of ID 2 are unrented at shops 0 and 1. Shop 0 is cheapest, followed by shop 1.
</pre>



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



<ul><li><code>1 &lt;= n &lt;= 3 * 10<sup>5</sup></code></li><li><code>1 &lt;= entries.length &lt;= 10<sup>5</sup></code></li><li><code>0 &lt;= shop<sub>i</sub>&nbsp;&lt; n</code></li><li><code>1 &lt;= movie<sub>i</sub>, price<sub>i</sub>&nbsp;&lt;= 10<sup>4</sup></code></li><li>Each shop carries&nbsp;<strong>at most one</strong>&nbsp;copy of a movie&nbsp;<code>movie<sub>i</sub></code>.</li><li>At most&nbsp;<code>10<sup>5</sup></code>&nbsp;calls&nbsp;<strong>in total</strong>&nbsp;will be made to&nbsp;<code>search</code>,&nbsp;<code>rent</code>,&nbsp;<code>drop</code>&nbsp;and&nbsp;<code>report</code>.</li></ul>



<h2><strong>Solution: Hashtable + TreeSet</strong></h2>



<p>We need three containers:<br>1. <strong><em>movies</em></strong> tracks the {movie -&gt; price} of each shop. This is readonly to get the price of a movie for generating keys for treesets.<br>2. <strong><em>unrented</em></strong> tracks unrented movies keyed by movie id,  value is a treeset ordered by {price, shop}.<br>3. <strong><em>rented</em></strong> tracks rented movies, a treeset <meta charset="utf-8">ordered by {price, shop, movie}</p>



<p>Note: By using array&lt;int, 3&gt; we can unpack values like below:<br>array&lt;int, 3&gt; entries; // {price, shop, movie}<br>for (const auto [price, shop, moive] : entries)<br>  &#8230;</p>



<p>Time complexity: <br>Init: O(nlogn)<br>rent / drop: O(logn)<br>search / report: O(1)</p>



<p>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 MovieRentingSystem {
public:
  MovieRentingSystem(int n, vector&lt;vector&lt;int&gt;&gt;&amp; entries): movies(n) {
    for (const auto&amp; e : entries) {
      const int shop = e[0];
      const int movie = e[1];
      const int price = e[2];
      movies[shop].emplace(movie, price);
      unrented[movie].emplace(price, shop);
    }
  }

  vector&lt;int&gt; search(int movie) {
    vector&lt;int&gt; shops;
    for (const auto [price, shop] : unrented[movie]) {
      shops.push_back(shop);
      if (shops.size() == 5) break;
    }
    return shops;
  }

  void rent(int shop, int movie) {
    const int price = movies[shop][movie];
    unrented[movie].erase({price, shop});
    rented.insert({price, shop, movie});
  }

  void drop(int shop, int movie) {
    const int price = movies[shop][movie];
    rented.erase({price, shop, movie});
    unrented[movie].emplace(price, shop);
  }

  vector&lt;vector&lt;int&gt;&gt; report() {
    vector&lt;vector&lt;int&gt;&gt; ans;
    for (const auto&amp; [price, shop, movie] : rented) {
      ans.push_back({shop, movie});
      if (ans.size() == 5) break;
    }
    return ans;
  }
private:
  vector&lt;unordered_map&lt;int, int&gt;&gt; movies; // shop -&gt; {movie -&gt; price}
  unordered_map&lt;int, set&lt;pair&lt;int, int&gt;&gt;&gt; unrented; // movie -&gt; {price, shop}
  set&lt;array&lt;int, 3&gt;&gt; rented; // {price, shop, movie}
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/data-structure/leetcode-1912-design-movie-rental-system/">花花酱 LeetCode 1912. Design Movie Rental 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/data-structure/leetcode-1912-design-movie-rental-system/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1865. Finding Pairs With a Certain Sum</title>
		<link>https://zxi.mytechroad.com/blog/hashtable/leetcode-1865-finding-pairs-with-a-certain-sum/</link>
					<comments>https://zxi.mytechroad.com/blog/hashtable/leetcode-1865-finding-pairs-with-a-certain-sum/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Thu, 05 Aug 2021 05:48:38 +0000</pubDate>
				<category><![CDATA[Hashtable]]></category>
		<category><![CDATA[array]]></category>
		<category><![CDATA[data structure]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[hashtable]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=8471</guid>

					<description><![CDATA[<p>You are given two integer arrays&#160;nums1&#160;and&#160;nums2. You are tasked to implement a data structure that supports queries of two types: Add&#160;a positive integer to an&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/hashtable/leetcode-1865-finding-pairs-with-a-certain-sum/">花花酱 LeetCode 1865. Finding Pairs With a Certain Sum</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>You are given two integer arrays&nbsp;<code>nums1</code>&nbsp;and&nbsp;<code>nums2</code>. You are tasked to implement a data structure that supports queries of two types:</p>



<ol><li><strong>Add</strong>&nbsp;a positive integer to an element of a given index in the array&nbsp;<code>nums2</code>.</li><li><strong>Count</strong>&nbsp;the number of pairs&nbsp;<code>(i, j)</code>&nbsp;such that&nbsp;<code>nums1[i] + nums2[j]</code>&nbsp;equals a given value (<code>0 &lt;= i &lt; nums1.length</code>&nbsp;and&nbsp;<code>0 &lt;= j &lt; nums2.length</code>).</li></ol>



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



<ul><li><code>FindSumPairs(int[] nums1, int[] nums2)</code>&nbsp;Initializes the&nbsp;<code>FindSumPairs</code>&nbsp;object with two integer arrays&nbsp;<code>nums1</code>&nbsp;and&nbsp;<code>nums2</code>.</li><li><code>void add(int index, int val)</code>&nbsp;Adds&nbsp;<code>val</code>&nbsp;to&nbsp;<code>nums2[index]</code>, i.e., apply&nbsp;<code>nums2[index] += val</code>.</li><li><code>int count(int tot)</code>&nbsp;Returns the number of pairs&nbsp;<code>(i, j)</code>&nbsp;such that&nbsp;<code>nums1[i] + nums2[j] == tot</code>.</li></ul>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input</strong>
["FindSumPairs", "count", "add", "count", "count", "add", "add", "count"]
[[[1, 1, 2, 2, 2, 3], [1, 4, 5, 2, 5, 4]], [7], [3, 2], [8], [4], [0, 1], [1, 1], [7]]
<strong>Output</strong>
[null, 8, null, 2, 1, null, null, 11]
<strong>Explanation</strong>
FindSumPairs findSumPairs = new FindSumPairs([1, 1, 2, 2, 2, 3], [1, 4, 5, 2, 5, 4]);
findSumPairs.count(7); // return 8; pairs (2,2), (3,2), (4,2), (2,4), (3,4), (4,4) make 2 + 5 and pairs (5,1), (5,5) make 3 + 4
findSumPairs.add(3, 2); // now nums2 = [1,4,5,<strong>4</strong>,5,4] 
findSumPairs.count(8); // return 2; pairs (5,2), (5,4) make 3 + 5 
findSumPairs.count(4); // return 1; pair (5,0) makes 3 + 1 
findSumPairs.add(0, 1); // now nums2 = [<strong>2</strong>,4,5,4,5,4] 
findSumPairs.add(1, 1); // now nums2 = [2,<strong>5</strong>,5,4,5,4] 
findSumPairs.count(7); // return 11; pairs (2,1), (2,2), (2,4), (3,1), (3,2), (3,4), (4,1), (4,2), (4,4) make 2 + 5 and pairs (5,3), (5,5) make 3 + 4
</pre>



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



<ul><li><code>1 &lt;= nums1.length &lt;= 1000</code></li><li><code>1 &lt;= nums2.length &lt;= 10<sup>5</sup></code></li><li><code>1 &lt;= nums1[i] &lt;= 10<sup>9</sup></code></li><li><code>1 &lt;= nums2[i] &lt;= 10<sup>5</sup></code></li><li><code>0 &lt;= index &lt; nums2.length</code></li><li><code>1 &lt;= val &lt;= 10<sup>5</sup></code></li><li><code>1 &lt;= tot &lt;= 10<sup>9</sup></code></li><li>At most&nbsp;<code>1000</code>&nbsp;calls are made to&nbsp;<code>add</code>&nbsp;and&nbsp;<code>count</code>&nbsp;<strong>each</strong>.</li></ul>



<h2><strong>Solution: HashTable</strong></h2>



<p>Note nums1 and nums2 are unbalanced. Brute force method will take O(m*n) = O(10<sup>3</sup>*10<sup>5</sup>) = O(10<sup>8</sup>) for each count call which will TLE. We could use a hashtable to store the counts of elements from nums2, and only iterate over nums1 to reduce the time complexity.</p>



<p>Time complexity:</p>



<p>init: O(m) + O(n)<br>add: O(1)<br>count: O(m)</p>



<p>Total time is less than O(10<sup>6</sup>)</p>



<p>Space complexity: O(m + n)</p>



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

<pre class="crayon-plain-tag">// Author: Huahua
class FindSumPairs {
public:
  FindSumPairs(vector&lt;int&gt;&amp; nums1, 
               vector&lt;int&gt;&amp; nums2): nums1_(nums1), nums2_(nums2) {
    for (int x : nums2_) ++freq_[x];
  }

  void add(int index, int val) {
    if (--freq_[nums2_[index]] == 0)
      freq_.erase(nums2_[index]);
    ++freq_[nums2_[index] += val];
  }

  int count(int tot) {
    int ans = 0;
    for (int a : nums1_) {
      auto it = freq_.find(tot - a);
      if (it != freq_.end()) ans += it-&gt;second;
    }
    return ans;
  }
private:  
  vector&lt;int&gt; nums1_;
  vector&lt;int&gt; nums2_;
  unordered_map&lt;int, int&gt; freq_;
};</pre>

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

<pre class="crayon-plain-tag"># Author: Huahua
class FindSumPairs:
  def __init__(self, nums1: List[int], nums2: List[int]):
    self.nums1 = nums1
    self.nums2 = nums2
    self.freq = Counter(nums2)


  def add(self, index: int, val: int) -&gt; None:
    self.freq.subtract((self.nums2[index],))
    self.nums2[index] += val
    self.freq.update((self.nums2[index],))


  def count(self, tot: int) -&gt; int:
    return sum(self.freq[tot - a] for a in self.nums1)</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/hashtable/leetcode-1865-finding-pairs-with-a-certain-sum/">花花酱 LeetCode 1865. Finding Pairs With a Certain Sum</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-1865-finding-pairs-with-a-certain-sum/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1797. Design Authentication Manager</title>
		<link>https://zxi.mytechroad.com/blog/hashtable/leetcode-1797-design-authentication-manager/</link>
					<comments>https://zxi.mytechroad.com/blog/hashtable/leetcode-1797-design-authentication-manager/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sat, 20 Mar 2021 16:28:53 +0000</pubDate>
				<category><![CDATA[Hashtable]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[hashtable]]></category>
		<category><![CDATA[medium]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=8252</guid>

					<description><![CDATA[<p>There is an authentication system that works with authentication tokens. For each session, the user will receive a new authentication token that will expire&#160;timeToLive&#160;seconds after&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/hashtable/leetcode-1797-design-authentication-manager/">花花酱 LeetCode 1797. Design Authentication Manager</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>There is an authentication system that works with authentication tokens. For each session, the user will receive a new authentication token that will expire&nbsp;<code>timeToLive</code>&nbsp;seconds after the&nbsp;<code>currentTime</code>. If the token is renewed, the expiry time will be&nbsp;<strong>extended</strong>&nbsp;to expire&nbsp;<code>timeToLive</code>&nbsp;seconds after the (potentially different)&nbsp;<code>currentTime</code>.</p>



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



<ul><li><code>AuthenticationManager(int timeToLive)</code>&nbsp;constructs the&nbsp;<code>AuthenticationManager</code>&nbsp;and sets the&nbsp;<code>timeToLive</code>.</li><li><code>generate(string tokenId, int currentTime)</code>&nbsp;generates a new token with the given&nbsp;<code>tokenId</code>&nbsp;at the given&nbsp;<code>currentTime</code>&nbsp;in seconds.</li><li><code>renew(string tokenId, int currentTime)</code>&nbsp;renews the&nbsp;<strong>unexpired</strong>&nbsp;token with the given&nbsp;<code>tokenId</code>&nbsp;at the given&nbsp;<code>currentTime</code>&nbsp;in seconds. If there are no unexpired tokens with the given&nbsp;<code>tokenId</code>, the request is ignored, and nothing happens.</li><li><code>countUnexpiredTokens(int currentTime)</code>&nbsp;returns the number of&nbsp;<strong>unexpired</strong>&nbsp;tokens at the given currentTime.</li></ul>



<p>Note that if a token expires at time&nbsp;<code>t</code>, and another action happens on time&nbsp;<code>t</code>&nbsp;(<code>renew</code>&nbsp;or&nbsp;<code>countUnexpiredTokens</code>), the expiration takes place&nbsp;<strong>before</strong>&nbsp;the other actions.</p>



<p><strong>Example 1:</strong><img alt="" src="https://assets.leetcode.com/uploads/2021/02/25/copy-of-pc68_q2.png"></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input</strong>
["AuthenticationManager", "<code>renew</code>", "generate", "<code>countUnexpiredTokens</code>", "generate", "<code>renew</code>", "<code>renew</code>", "<code>countUnexpiredTokens</code>"]
[[5], ["aaa", 1], ["aaa", 2], [6], ["bbb", 7], ["aaa", 8], ["bbb", 10], [15]]
<strong>Output</strong>
[null, null, null, 1, null, null, null, 0]
</pre>



<p><strong>Explanation</strong> AuthenticationManager authenticationManager = new AuthenticationManager(5); // Constructs the AuthenticationManager with <code>timeToLive</code> = 5 seconds. authenticationManager.<code>renew</code>(&#8220;aaa&#8221;, 1); // No token exists with tokenId &#8220;aaa&#8221; at time 1, so nothing happens. authenticationManager.generate(&#8220;aaa&#8221;, 2); // Generates a new token with tokenId &#8220;aaa&#8221; at time 2. authenticationManager.<code>countUnexpiredTokens</code>(6); // The token with tokenId &#8220;aaa&#8221; is the only unexpired one at time 6, so return 1. authenticationManager.generate(&#8220;bbb&#8221;, 7); // Generates a new token with tokenId &#8220;bbb&#8221; at time 7. authenticationManager.<code>renew</code>(&#8220;aaa&#8221;, 8); // The token with tokenId &#8220;aaa&#8221; expired at time 7, and 8 &gt;= 7, so at time 8 the <code>renew</code> request is ignored, and nothing happens. authenticationManager.<code>renew</code>(&#8220;bbb&#8221;, 10); // The token with tokenId &#8220;bbb&#8221; is unexpired at time 10, so the <code>renew</code> request is fulfilled and now the token will expire at time 15. authenticationManager.<code>countUnexpiredTokens</code>(15); // The token with tokenId &#8220;bbb&#8221; expires at time 15, and the token with tokenId &#8220;aaa&#8221; expired at time 7, so currently no token is unexpired, so return 0.</p>



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



<ul><li><code>1 &lt;= timeToLive &lt;= 10<sup>8</sup></code></li><li><code>1 &lt;= currentTime &lt;= 10<sup>8</sup></code></li><li><code>1 &lt;= tokenId.length &lt;= 5</code></li><li><code>tokenId</code>&nbsp;consists only of lowercase letters.</li><li>All calls to&nbsp;<code>generate</code>&nbsp;will contain unique values of&nbsp;<code>tokenId</code>.</li><li>The values of&nbsp;<code>currentTime</code>&nbsp;across all the function calls will be&nbsp;<strong>strictly increasing</strong>.</li><li>At most&nbsp;<code>2000</code>&nbsp;calls will be made to all functions combined.</li></ul>



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



<p>Use a hashtable to store the token and its expiration time.</p>



<p>Time complexity: at most O(n) per operation<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, 160 ms, 30.1 MB
class AuthenticationManager {
public:
  AuthenticationManager(int timeToLive) : ttl_(timeToLive) {}

  void generate(string tokenId, int currentTime) {
    clear(currentTime);
    tokens_[tokenId] = currentTime + ttl_;
  }

  void renew(string tokenId, int currentTime) {
    clear(currentTime);
    if (!tokens_.count(tokenId)) return;    
    tokens_[tokenId] = currentTime + ttl_;
  }

  int countUnexpiredTokens(int currentTime) {
    clear(currentTime);
    return tokens_.size();
  }
private:
  void clear(int currentTime) {
    vector&lt;string&gt; ids;
    for (const auto&amp; [id, t] : tokens_)
      if (t &lt;= currentTime) ids.push_back(id);
    for (const string&amp; id : ids)
      tokens_.erase(id);
  }
  
  unordered_map&lt;string, int&gt; tokens_;
  int ttl_;
};

/**
 * Your AuthenticationManager object will be instantiated and called as such:
 * AuthenticationManager* obj = new AuthenticationManager(timeToLive);
 * obj-&gt;generate(tokenId,currentTime);
 * obj-&gt;renew(tokenId,currentTime);
 * int param_3 = obj-&gt;countUnexpiredTokens(currentTime);
 */</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/hashtable/leetcode-1797-design-authentication-manager/">花花酱 LeetCode 1797. Design Authentication Manager</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-1797-design-authentication-manager/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1670. Design Front Middle Back Queue</title>
		<link>https://zxi.mytechroad.com/blog/list/leetcode-1670-design-front-middle-back-queue/</link>
					<comments>https://zxi.mytechroad.com/blog/list/leetcode-1670-design-front-middle-back-queue/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sat, 28 Nov 2020 20:00:04 +0000</pubDate>
				<category><![CDATA[List]]></category>
		<category><![CDATA[data structure]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[iterator]]></category>
		<category><![CDATA[list]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=7725</guid>

					<description><![CDATA[<p>Design a queue that supports&#160;push&#160;and&#160;pop&#160;operations in the front, middle, and back. Implement the&#160;FrontMiddleBack&#160;class: FrontMiddleBack()&#160;Initializes the queue. void pushFront(int val)&#160;Adds&#160;val&#160;to the&#160;front&#160;of the queue. void pushMiddle(int val)&#160;Adds&#160;val&#160;to&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/list/leetcode-1670-design-front-middle-back-queue/">花花酱 LeetCode 1670. Design Front Middle Back Queue</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>Design a queue that supports&nbsp;<code>push</code>&nbsp;and&nbsp;<code>pop</code>&nbsp;operations in the front, middle, and back.</p>



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



<ul><li><code>FrontMiddleBack()</code>&nbsp;Initializes the queue.</li><li><code>void pushFront(int val)</code>&nbsp;Adds&nbsp;<code>val</code>&nbsp;to the&nbsp;<strong>front</strong>&nbsp;of the queue.</li><li><code>void pushMiddle(int val)</code>&nbsp;Adds&nbsp;<code>val</code>&nbsp;to the&nbsp;<strong>middle</strong>&nbsp;of the queue.</li><li><code>void pushBack(int val)</code>&nbsp;Adds&nbsp;<code>val</code>&nbsp;to the&nbsp;<strong>back</strong>&nbsp;of the queue.</li><li><code>int popFront()</code>&nbsp;Removes the&nbsp;<strong>front</strong>&nbsp;element of the queue and returns it. If the queue is empty, return&nbsp;<code>-1</code>.</li><li><code>int popMiddle()</code>&nbsp;Removes the&nbsp;<strong>middle</strong>&nbsp;element of the queue and returns it. If the queue is empty, return&nbsp;<code>-1</code>.</li><li><code>int popBack()</code>&nbsp;Removes the&nbsp;<strong>back</strong>&nbsp;element of the queue and returns it. If the queue is empty, return&nbsp;<code>-1</code>.</li></ul>



<p><strong>Notice</strong>&nbsp;that when there are&nbsp;<strong>two</strong>&nbsp;middle position choices, the operation is performed on the&nbsp;<strong>frontmost</strong>&nbsp;middle position choice. For example:</p>



<ul><li>Pushing&nbsp;<code>6</code>&nbsp;into the middle of&nbsp;<code>[1, 2, 3, 4, 5]</code>&nbsp;results in&nbsp;<code>[1, 2,&nbsp;6, 3, 4, 5]</code>.</li><li>Popping the middle from&nbsp;<code>[1, 2,&nbsp;3, 4, 5, 6]</code>&nbsp;returns&nbsp;<code>3</code>&nbsp;and results in&nbsp;<code>[1, 2, 4, 5, 6]</code>.</li></ul>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong>
["FrontMiddleBackQueue", "pushFront", "pushBack", "pushMiddle", "pushMiddle", "popFront", "popMiddle", "popMiddle", "popBack", "popFront"]
[[], [1], [2], [3], [4], [], [], [], [], []]
<strong>Output:</strong>
[null, null, null, null, null, 1, 3, 4, 2, -1]
<strong>Explanation:</strong>
FrontMiddleBackQueue q = new FrontMiddleBackQueue();
q.pushFront(1);   // [1]
q.pushBack(2);    // [1, 2]
q.pushMiddle(3);  // [1, 3, 2]
q.pushMiddle(4);  // [1, 4, 3, 2]
q.popFront();     // return 1 -&gt; [4, 3, 2]
q.popMiddle();    // return 3 -&gt; [4, 2]
q.popMiddle();    // return 4 -&gt; [2]
q.popBack();      // return 2 -&gt; []
q.popFront();     // return -1 -&gt; [] (The queue is empty)
</pre>



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



<ul><li><code>1 &lt;= val &lt;= 10<sup>9</sup></code></li><li>At most&nbsp;<code>1000</code>&nbsp;calls will be made to&nbsp;<code>pushFront</code>,&nbsp;<code>pushMiddle</code>,&nbsp;<code>pushBack</code>,&nbsp;<code>popFront</code>,&nbsp;<code>popMiddle</code>, and&nbsp;<code>popBack</code>.</li></ul>



<h2><strong>Solution: List + Middle Iterator</strong></h2>



<p>Time complexity: O(1) per op<br>Space complexity: O(n) in total</p>



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

<pre class="crayon-plain-tag">// Author: Huahua
class FrontMiddleBackQueue {
public:
  FrontMiddleBackQueue() {}

  void pushFront(int val) {
    q_.push_front(val); 
    updateMit(even() ? -1 : 0);
  }

  void pushMiddle(int val) {    
    if (q_.empty())
      q_.push_back(val);
    else
      q_.insert(even() ? next(mit_) : mit_, val);
    updateMit(even() ? -1 : 1);
  }

  void pushBack(int val) {    
    q_.push_back(val); 
    updateMit(even() ? 0 : 1);
  }

  int popFront() {     
    if (q_.empty()) return -1;
    int val = q_.front();
    q_.pop_front();
    updateMit(even() ? 0 : 1);
    return val;
  }

  int popMiddle() {    
    if (q_.empty()) return -1;
    int val = *mit_;
    mit_ = q_.erase(mit_);
    updateMit(even() ? -1 : 0);
    return val;
  }

  int popBack() {    
    if (q_.empty()) return -1;
    int val = q_.back();
    q_.pop_back();
    updateMit(even() ? -1 : 0);
    return val;
  }
private:  
  void updateMit(int delta) {
    if (q_.size() &lt;= 1) {      
      mit_ = begin(q_);
    } else {
      if (delta &gt; 0) ++mit_;
      if (delta &lt; 0) --mit_;
    }    
  }
  
  bool even() const { return q_.size() % 2 == 0; }
  
  list&lt;int&gt; q_;
  list&lt;int&gt;::iterator mit_;
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/list/leetcode-1670-design-front-middle-back-queue/">花花酱 LeetCode 1670. Design Front Middle Back Queue</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/list/leetcode-1670-design-front-middle-back-queue/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1656. Design an Ordered Stream</title>
		<link>https://zxi.mytechroad.com/blog/data-structure/leetcode-1656-design-an-ordered-stream/</link>
					<comments>https://zxi.mytechroad.com/blog/data-structure/leetcode-1656-design-an-ordered-stream/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 15 Nov 2020 04:16:02 +0000</pubDate>
				<category><![CDATA[Data Structure]]></category>
		<category><![CDATA[array]]></category>
		<category><![CDATA[data structure]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[easy]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=7666</guid>

					<description><![CDATA[<p>There are&#160;n&#160;(id, value)&#160;pairs, where&#160;id&#160;is an integer between&#160;1&#160;and&#160;n&#160;and&#160;value&#160;is a string. No two pairs have the same&#160;id. Design a stream that takes the&#160;n&#160;pairs in an&#160;arbitrary&#160;order, and returns&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/data-structure/leetcode-1656-design-an-ordered-stream/">花花酱 LeetCode 1656. Design an Ordered Stream</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>There are&nbsp;<code>n</code>&nbsp;<code>(id, value)</code>&nbsp;pairs, where&nbsp;<code>id</code>&nbsp;is an integer between&nbsp;<code>1</code>&nbsp;and&nbsp;<code>n</code>&nbsp;and&nbsp;<code>value</code>&nbsp;is a string. No two pairs have the same&nbsp;<code>id</code>.</p>



<p>Design a stream that takes the&nbsp;<code>n</code>&nbsp;pairs in an&nbsp;<strong>arbitrary</strong>&nbsp;order, and returns the values over several calls in&nbsp;<strong>increasing order of their ids</strong>.</p>



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



<ul><li><code>OrderedStream(int n)</code>&nbsp;Constructs the stream to take&nbsp;<code>n</code>&nbsp;values and sets a current&nbsp;<code>ptr</code>&nbsp;to&nbsp;<code>1</code>.</li><li><code>String[] insert(int id, String value)</code>&nbsp;Stores the new&nbsp;<code>(id, value)</code>&nbsp;pair in the stream. After storing the pair:<ul><li>If the stream has stored a pair with&nbsp;<code>id = ptr</code>, then find the&nbsp;<strong>longest contiguous incrementing sequence</strong>&nbsp;of ids starting with&nbsp;<code>id = ptr</code>&nbsp;and return a list of the values associated with those ids&nbsp;<strong>in order</strong>. Then, update&nbsp;<code>ptr</code>&nbsp;to the last&nbsp;<code>id + 1</code>.</li><li>Otherwise, return an empty list.</li></ul></li></ul>



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



<figure class="wp-block-image"><img src="https://assets.leetcode.com/uploads/2020/11/10/q1.gif" alt=""/></figure>



<pre class="wp-block-preformatted wp-block-preformatted;crayon:false"><strong>Input</strong>
["OrderedStream", "insert", "insert", "insert", "insert", "insert"]
[[5], [3, "ccccc"], [1, "aaaaa"], [2, "bbbbb"], [5, "eeeee"], [4, "ddddd"]]
<strong>Output</strong>
[null, [], ["aaaaa"], ["bbbbb", "ccccc"], [], ["ddddd", "eeeee"]]
<strong>Explanation</strong>
OrderedStream os= new OrderedStream(5);
os.insert(3, "ccccc"); // Inserts (3, "ccccc"), returns [].
os.insert(1, "aaaaa"); // Inserts (1, "aaaaa"), returns ["aaaaa"].
os.insert(2, "bbbbb"); // Inserts (2, "bbbbb"), returns ["bbbbb", "ccccc"].
os.insert(5, "eeeee"); // Inserts (5, "eeeee"), returns [].
os.insert(4, "ddddd"); // Inserts (4, "ddddd"), returns ["ddddd", "eeeee"].
</pre>



<h2><strong>Solution: Straight Forward</strong></h2>



<p>Time complexity: O(n) in total<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 OrderedStream {
public:
  OrderedStream(int n): data_(n + 1) {}

  vector&lt;string&gt; insert(int id, string value) {
    data_[id] = value;
    vector&lt;string&gt; ans;
    if (ptr_ == id)
      while (ptr_ &lt; data_.size() &amp;&amp; !data_[ptr_].empty())
        ans.push_back(data_[ptr_++]);
    return ans;
  }
private:
  int ptr_ = 1;
  vector&lt;string&gt; data_;
};</pre>

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

<pre class="crayon-plain-tag"># Author: Huahua
class OrderedStream:
  def __init__(self, n: int):
    self.data = [None] * (n + 1)
    self.ptr = 1

  def insert(self, id: int, value: str) -&gt; List[str]:
    self.data[id] = value
    if id == self.ptr:
      while self.ptr &lt; len(self.data) and self.data[self.ptr]:
        self.ptr += 1
      return self.data[id:self.ptr]
    return []</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/data-structure/leetcode-1656-design-an-ordered-stream/">花花酱 LeetCode 1656. Design an Ordered Stream</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-1656-design-an-ordered-stream/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1206. Design Skiplist</title>
		<link>https://zxi.mytechroad.com/blog/desgin/leetcode-1206-design-skiplist/</link>
					<comments>https://zxi.mytechroad.com/blog/desgin/leetcode-1206-design-skiplist/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Fri, 06 Nov 2020 21:19:24 +0000</pubDate>
				<category><![CDATA[Desgin]]></category>
		<category><![CDATA[data structure]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[skiplist]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=7606</guid>

					<description><![CDATA[<p>Design a Skiplist without using any built-in libraries. A Skiplist is a data structure that takes&#160;O(log(n)) time&#160;to&#160;add,&#160;erase&#160;and&#160;search. Comparing with treap and red-black tree which has&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/desgin/leetcode-1206-design-skiplist/">花花酱 LeetCode 1206. Design Skiplist</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 1206. Design Skiplist - 刷题找工作 EP367" width="500" height="281" src="https://www.youtube.com/embed/783qX31AN08?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<p>Design a Skiplist without using any built-in libraries.</p>



<p><em>A Skiplist is a data structure that takes&nbsp;O(log(n)) time&nbsp;to&nbsp;<code>add</code>,&nbsp;<code>erase</code>&nbsp;and&nbsp;<code>search</code>. Comparing with treap and red-black tree which has the same function and performance, the code length of Skiplist can be&nbsp;comparatively short and the idea behind Skiplists are just simple linked lists.</em></p>



<p><em>For example:&nbsp;we have a Skiplist containing&nbsp;<code>[30,40,50,60,70,90]</code>&nbsp;and we want to add&nbsp;<code>80</code>&nbsp;and&nbsp;<code>45</code>&nbsp;into it. The&nbsp;Skiplist works this way:</em></p>



<figure class="wp-block-image"><img src="https://assets.leetcode.com/uploads/2019/09/27/1506_skiplist.gif" alt=""/></figure>



<p><br>Artyom Kalinin [CC BY-SA 3.0], via&nbsp;<a href="https://commons.wikimedia.org/wiki/File:Skip_list_add_element-en.gif" target="_blank" rel="noreferrer noopener">Wikimedia Commons</a></p>



<p><em>You can see there are many layers in the Skiplist. Each layer is a sorted linked list. With the help of the top layers,&nbsp;<code>add</code>&nbsp;,&nbsp;<code>erase</code>&nbsp;and&nbsp;<code>search&nbsp;</code>can be faster than O(n).&nbsp;It can be proven&nbsp;that the average time complexity for each operation is O(log(n)) and space complexity is O(n).</em></p>



<p>To be specific, your design should include these functions:</p>



<ul><li><code>bool search(int target)</code>&nbsp;: Return whether&nbsp;the&nbsp;<code>target</code>&nbsp;exists in the Skiplist&nbsp;or not.</li><li><code>void add(int num)</code>:&nbsp;Insert a value into the SkipList.&nbsp;</li><li><code>bool erase(int num)</code>: Remove a value in&nbsp;the Skiplist.&nbsp;If&nbsp;<code>num</code>&nbsp;does not exist in the Skiplist, do nothing and return false. If there exists multiple&nbsp;<code>num</code>&nbsp;values, removing&nbsp;any one of them is fine.</li></ul>



<p>See more about Skiplist :&nbsp;<a href="https://en.wikipedia.org/wiki/Skip_list" target="_blank" rel="noreferrer noopener">https://en.wikipedia.org/wiki/Skip_list</a></p>



<p>Note that duplicates may exist in the Skiplist, your code needs to handle this situation.</p>



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



<pre class="crayon-plain-tag">Skiplist skiplist = new Skiplist();

skiplist.add(1);
skiplist.add(2);
skiplist.add(3);
skiplist.search(0);   // return false.
skiplist.add(4);
skiplist.search(1);   // return true.
skiplist.erase(0);    // return false, 0 is not in skiplist.
skiplist.erase(1);    // return true.
skiplist.search(1);   // return false, 1 has already been erased.</pre>



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



<ul><li><code>0 &lt;= num, target&nbsp;&lt;= 20000</code></li><li>At most&nbsp;<code>50000</code>&nbsp;calls will be made to&nbsp;<code>search</code>,&nbsp;<code>add</code>, and&nbsp;<code>erase</code>.</li></ul>



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



<figure class="wp-block-image size-large"><img width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/1206-ep367-1.png" alt="" class="wp-image-7610" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/1206-ep367-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/1206-ep367-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/1206-ep367-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/11/1206-ep367-2.png" alt="" class="wp-image-7611" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/1206-ep367-2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/1206-ep367-2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/1206-ep367-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/11/1206-ep367-3.png" alt="" class="wp-image-7612" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/1206-ep367-3.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/1206-ep367-3-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/1206-ep367-3-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/11/1206-ep367-4.png" alt="" class="wp-image-7613" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/1206-ep367-4.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/1206-ep367-4-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/1206-ep367-4-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/11/1206-ep367-5.png" alt="" class="wp-image-7614" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/1206-ep367-5.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/1206-ep367-5-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/1206-ep367-5-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></figure>



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

<pre class="crayon-plain-tag">// Author: Huahua
class Skiplist {
public:
  Skiplist() { head_ = make_shared&lt;Node&gt;(); }

  bool search(int target) {
    for (auto node = head_; node; node = node-&gt;down) {
      while (node-&gt;next &amp;&amp; node-&gt;next-&gt;val &lt; target)
        node = node-&gt;next;
      if (node-&gt;next &amp;&amp; node-&gt;next-&gt;val == target)
        return true;
    }
    return false;
  }

  void add(int num) {
    stack&lt;shared_ptr&lt;Node&gt;&gt; s;
    shared_ptr&lt;Node&gt; down;
    bool insert = true;
    
    for (auto node = head_; node; node = node-&gt;down) {
      while (node-&gt;next &amp;&amp; node-&gt;next-&gt;val &lt; num)
        node = node-&gt;next;
      s.push(node);
    }
    
    while (!s.empty() &amp;&amp; insert) {
      auto cur = s.top(); s.pop();
      cur-&gt;next = make_shared&lt;Node&gt;(num, cur-&gt;next, down);
      down = cur-&gt;next;
      insert = rand() &amp; 1; // 50% chance
    }
    
    if (insert) // create a new layer.
      head_ = make_shared&lt;Node&gt;(-1, nullptr, head_);
  }

  bool erase(int num) {
    bool found = false;
    for (auto node = head_; node; node = node-&gt;down) {
      while (node-&gt;next &amp;&amp; node-&gt;next-&gt;val &lt; num)
        node = node-&gt;next;
      if (node-&gt;next &amp;&amp; node-&gt;next-&gt;val == num) {
        found = true;
        node-&gt;next = node-&gt;next-&gt;next;
      }
    }
    return found;
  }
private:
  struct Node {
    Node(int val = -1, 
         shared_ptr&lt;Node&gt; next = nullptr, 
         shared_ptr&lt;Node&gt; down = nullptr): 
          val(val), next(next), down(down) {}
    int val;
    shared_ptr&lt;Node&gt; next;
    shared_ptr&lt;Node&gt; down;
  };
  
  shared_ptr&lt;Node&gt; head_;
};

/**
 * Your Skiplist object will be instantiated and called as such:
 * Skiplist* obj = new Skiplist();
 * bool param_1 = obj-&gt;search(target);
 * obj-&gt;add(num);
 * bool param_3 = obj-&gt;erase(num);
 */</pre>

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

<pre class="crayon-plain-tag">import random

class Node:
  def __init__(self, val=-1, right=None, down=None):
    self.val = val
    self.right = right
    self.down = down
    
class Skiplist:
  def __init__(self):
    self.head = Node() # Dummy head

  def search(self, target: int) -&gt; bool:
    node = self.head
    while node:
      # Move to the right in the current level
      while node.right and node.right.val &lt; target:
        node = node.right
      if node.right and node.right.val == target:
        return True
      # Move to the the next level
      node = node.down
    return False

  def add(self, num: int) -&gt; None:
    nodes = []
    node = self.head
    while node:
      # Move to the right in the current level
      while node.right and node.right.val &lt; num:
        node = node.right
      nodes.append(node)
      # Move to the next level
      node = node.down
    
    insert = True
    down = None
    while insert and nodes:
      node = nodes.pop()
      node.right = Node(num, node.right, down)
      down = node.right
      insert = (random.getrandbits(1) == 0)      
    
    # Create a new level with a dummy head.
    # right = None
    # down = current head
    if insert:
      self.head = Node(-1, None, self.head)

  def erase(self, num: int) -&gt; bool:
    node = self.head
    found = False
    while node:
      # Move to the right in the current level
      while node.right and node.right.val &lt; num:
        node = node.right
      # Find the target node
      if node.right and node.right.val == num:
        # Delete by skipping
        node.right = node.right.right
        found = True
      # Move to the next level
      node = node.down      
    return found
        
# Your Skiplist object will be instantiated and called as such:
# obj = Skiplist()
# param_1 = obj.search(target)
# obj.add(num)
# param_3 = obj.erase(num)</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/desgin/leetcode-1206-design-skiplist/">花花酱 LeetCode 1206. Design Skiplist</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/desgin/leetcode-1206-design-skiplist/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1603. Design Parking System</title>
		<link>https://zxi.mytechroad.com/blog/simulation/leetcode-1603-design-parking-system/</link>
					<comments>https://zxi.mytechroad.com/blog/simulation/leetcode-1603-design-parking-system/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sat, 03 Oct 2020 22:34:47 +0000</pubDate>
				<category><![CDATA[Simulation]]></category>
		<category><![CDATA[class]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[easy]]></category>
		<category><![CDATA[hashtable]]></category>
		<category><![CDATA[simulation]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=7439</guid>

					<description><![CDATA[<p>Design a parking system for a parking lot. The parking lot has three kinds of parking spaces: big, medium, and small, with a fixed number&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/simulation/leetcode-1603-design-parking-system/">花花酱 LeetCode 1603. Design Parking 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[
<p>Design a parking system for a parking lot. The parking lot has three kinds of parking spaces: big, medium, and small, with a fixed number of slots for each size.</p>



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



<ul><li><code>ParkingSystem(int big, int medium, int small)</code>&nbsp;Initializes object of the&nbsp;<code>ParkingSystem</code>&nbsp;class. The number of slots for each parking space are given as part of the constructor.</li><li><code>bool addCar(int carType)</code>&nbsp;Checks whether there is a parking space of&nbsp;<code>carType</code>&nbsp;for the car that wants to get into the parking lot.&nbsp;<code>carType</code>&nbsp;can be of three kinds: big, medium, or small, which are represented by&nbsp;<code>1</code>,&nbsp;<code>2</code>, and&nbsp;<code>3</code>&nbsp;respectively.&nbsp;<strong>A car can only park in a parking space of its&nbsp;</strong><code>carType</code>. If there is no space available, return&nbsp;<code>false</code>, else park the car in that size space and return&nbsp;<code>true</code>.</li></ul>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input</strong>
["ParkingSystem", "addCar", "addCar", "addCar", "addCar"]
[[1, 1, 0], [1], [2], [3], [1]]
<strong>Output</strong>
[null, true, true, false, false]
</pre>



<p><strong>Explanation</strong>
ParkingSystem parkingSystem = new ParkingSystem(1, 1, 0);
parkingSystem.addCar(1); // return true because there is 1 available slot for a big car
parkingSystem.addCar(2); // return true because there is 1 available slot for a medium car
parkingSystem.addCar(3); // return false because there is no available slot for a small car
parkingSystem.addCar(1); // return false because there is no available slot for a big car. It is already occupied.
</p>



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



<ul><li><code>0 &lt;= big, medium, small &lt;= 1000</code></li><li><code>carType</code>&nbsp;is&nbsp;<code>1</code>,&nbsp;<code>2</code>, or&nbsp;<code>3</code></li><li>At most&nbsp;<code>1000</code>&nbsp;calls will be made to&nbsp;<code>addCar</code></li></ul>



<h2><strong>Solution: Simulation</strong></h2>



<p>Time complexity: O(1) per addCar call<br>Space complexity: O(1)</p>



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

<pre class="crayon-plain-tag">// Author: Huahua
class ParkingSystem {
public:
  ParkingSystem(int big, int medium, int small): 
    slots_{{big, medium, small}} {}

  bool addCar(int carType) {
    return slots_[carType - 1]-- &gt; 0;
  }
private:
  vector&lt;int&gt; slots_;
};</pre>

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

<pre class="crayon-plain-tag"># Author: Huahua
class ParkingSystem:
  def __init__(self, big: int, medium: int, small: int):
    self.slots = {1: big, 2: medium, 3: small}

  def addCar(self, carType: int) -&gt; bool:
    if self.slots[carType] == 0: return False
    self.slots[carType] -= 1
    return True</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/simulation/leetcode-1603-design-parking-system/">花花酱 LeetCode 1603. Design Parking 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/simulation/leetcode-1603-design-parking-system/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1472. Design Browser History</title>
		<link>https://zxi.mytechroad.com/blog/desgin/leetcode-1472-design-browser-history/</link>
					<comments>https://zxi.mytechroad.com/blog/desgin/leetcode-1472-design-browser-history/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 07 Jun 2020 05:51:23 +0000</pubDate>
				<category><![CDATA[Desgin]]></category>
		<category><![CDATA[array]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[simulation]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=6886</guid>

					<description><![CDATA[<p>You have a&#160;browser&#160;of one tab where you start on the&#160;homepage&#160;and you can visit another&#160;url, get back in the history number of&#160;steps&#160;or move forward in the&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/desgin/leetcode-1472-design-browser-history/">花花酱 LeetCode 1472. Design Browser History</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>You have a&nbsp;<strong>browser</strong>&nbsp;of one tab where you start on the&nbsp;<code>homepage</code>&nbsp;and you can visit another&nbsp;<code>url</code>, get back in the history number of&nbsp;<code>steps</code>&nbsp;or move forward in the history number of&nbsp;<code>steps</code>.</p>



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



<ul><li><code>BrowserHistory(string homepage)</code>&nbsp;Initializes the object with the&nbsp;<code>homepage</code>&nbsp;of the browser.</li><li><code>void visit(string url)</code>&nbsp;visits&nbsp;<code>url</code>&nbsp;from the current page. It clears up all the forward history.</li><li><code>string back(int steps)</code>&nbsp;Move&nbsp;<code>steps</code>&nbsp;back in history. If you can only return&nbsp;<code>x</code>&nbsp;steps in the history and&nbsp;<code>steps &gt; x</code>, you will&nbsp;return only&nbsp;<code>x</code>&nbsp;steps. Return the current&nbsp;<code>url</code>&nbsp;after moving back in history&nbsp;<strong>at most</strong>&nbsp;<code>steps</code>.</li><li><code>string forward(int steps)</code>&nbsp;Move&nbsp;<code>steps</code>&nbsp;forward in history. If you can only forward&nbsp;<code>x</code>&nbsp;steps in the history and&nbsp;<code>steps &gt; x</code>, you will&nbsp;forward only&nbsp;<code>x</code>&nbsp;steps. Return the current&nbsp;<code>url</code>&nbsp;after forwarding in history&nbsp;<strong>at most</strong>&nbsp;<code>steps</code>.</li></ul>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong>
["BrowserHistory","visit","visit","visit","back","back","forward","visit","forward","back","back"]
[["leetcode.com"],["google.com"],["facebook.com"],["youtube.com"],[1],[1],[1],["linkedin.com"],[2],[2],[7]]
<strong>Output:</strong>
[null,null,null,null,"facebook.com","google.com","facebook.com",null,"linkedin.com","google.com","leetcode.com"]
<p><strong>Explanation:</strong>
BrowserHistory browserHistory = new BrowserHistory("leetcode.com");
browserHistory.visit("google.com");       // You are in "leetcode.com". Visit "google.com"
browserHistory.visit("facebook.com");     // You are in "google.com". Visit "facebook.com"
browserHistory.visit("youtube.com");      // You are in "facebook.com". Visit "youtube.com"
browserHistory.back(1);                   // You are in "youtube.com", move back to "facebook.com" return "facebook.com"
browserHistory.back(1);                   // You are in "facebook.com", move back to "google.com" return "google.com"
browserHistory.forward(1);                // You are in "google.com", move forward to "facebook.com" return "facebook.com"
browserHistory.visit("linkedin.com");     // You are in "facebook.com". Visit "linkedin.com"
browserHistory.forward(2);                // You are in "linkedin.com", you cannot move forward any steps.
browserHistory.back(2);                   // You are in "linkedin.com", move back two steps to "facebook.com" then to "google.com". return "google.com"
browserHistory.back(7);                   // You are in "google.com", you can move back only one step to "leetcode.com". return "leetcode.com"
</pre>



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



<ul><li><code>1 &lt;= homepage.length &lt;= 20</code></li><li><code>1 &lt;= url.length &lt;= 20</code></li><li><code>1 &lt;= steps &lt;= 100</code></li><li><code>homepage</code>&nbsp;and&nbsp;<code>url</code>&nbsp;consist of&nbsp; &#8216;.&#8217; or lower case English letters.</li><li>At most&nbsp;<code>5000</code>&nbsp;calls will be made to&nbsp;<code>visit</code>,&nbsp;<code>back</code>, and&nbsp;<code>forward</code>.</li></ul>



<h2><strong>Solution: Vector</strong></h2>



<p>Time complexity: <br>visit: Amortized O(1)<br>back: O(1)<br>forward: O(1)</p>



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

<pre class="crayon-plain-tag">// Author: Huahua
class BrowserHistory {
public:
  BrowserHistory(string homepage) : 
    index_(0) {
    urls_.push_back(std::move(homepage));    
  }

  void visit(string url) {
    while (urls_.size() &gt; index_ + 1)
      urls_.pop_back();
    ++index_;
    urls_.push_back(std::move(url));
  }

  string back(int steps) {    
    index_ = max(index_ - steps, 0);
    return urls_[index_];
  }

  string forward(int steps) {
    index_ = min(index_ + steps, static_cast&lt;int&gt;(urls_.size()) - 1);  
    return urls_[index_];
  }
private:
  int index_;
  vector&lt;string&gt; urls_;
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/desgin/leetcode-1472-design-browser-history/">花花酱 LeetCode 1472. Design Browser History</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/desgin/leetcode-1472-design-browser-history/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1396. Design Underground System</title>
		<link>https://zxi.mytechroad.com/blog/hashtable/leetcode-1396-design-underground-system/</link>
					<comments>https://zxi.mytechroad.com/blog/hashtable/leetcode-1396-design-underground-system/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 29 Mar 2020 04:35:17 +0000</pubDate>
				<category><![CDATA[Hashtable]]></category>
		<category><![CDATA[class]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[hashtable]]></category>
		<category><![CDATA[medium]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=6543</guid>

					<description><![CDATA[<p>Implement the class&#160;UndergroundSystem&#160;that supports three methods: 1.&#160;checkIn(int id, string stationName, int t) A customer with id card equal to&#160;id, gets in the station&#160;stationName&#160;at time&#160;t. A&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/hashtable/leetcode-1396-design-underground-system/">花花酱 LeetCode 1396. Design Underground 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[
<p>Implement the class&nbsp;<code>UndergroundSystem</code>&nbsp;that supports three methods:</p>



<p>1.<code>&nbsp;checkIn(int id, string stationName, int t)</code></p>



<ul><li>A customer with id card equal to&nbsp;<code>id</code>, gets in the station&nbsp;<code>stationName</code>&nbsp;at time&nbsp;<code>t</code>.</li><li>A customer&nbsp;can only be checked into one place at a time.</li></ul>



<p>2.<code>&nbsp;checkOut(int id, string stationName, int t)</code></p>



<ul><li>A customer with id card equal to&nbsp;<code>id</code>, gets out from the station&nbsp;<code>stationName</code>&nbsp;at time&nbsp;<code>t</code>.</li></ul>



<p>3.&nbsp;<code>getAverageTime(string startStation, string endStation)</code>&nbsp;</p>



<ul><li>Returns the average time to travel between the&nbsp;<code>startStation</code>&nbsp;and the&nbsp;<code>endStation</code>.</li><li>The average time is computed from all the previous traveling from&nbsp;<code>startStation</code>&nbsp;to&nbsp;<code>endStation</code>&nbsp;that happened&nbsp;<strong>directly</strong>.</li><li>Call to&nbsp;<code>getAverageTime</code>&nbsp;is always valid.</li></ul>



<p>You can assume all calls to&nbsp;<code>checkIn</code>&nbsp;and&nbsp;<code>checkOut</code>&nbsp;methods are consistent. That is, if a customer gets in at time&nbsp;<strong>t<sub>1</sub></strong>&nbsp;at some station, then it gets out at time&nbsp;<strong>t<sub>2</sub></strong>&nbsp;with&nbsp;<strong>t<sub>2</sub>&nbsp;&gt; t<sub>1</sub></strong>.&nbsp;All events happen in chronological order.</p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input</strong>
["UndergroundSystem","checkIn","checkIn","checkIn","checkOut","checkOut","checkOut","getAverageTime","getAverageTime","checkIn","getAverageTime","checkOut","getAverageTime"]
[[],[45,"Leyton",3],[32,"Paradise",8],[27,"Leyton",10],[45,"Waterloo",15],[27,"Waterloo",20],[32,"Cambridge",22],["Paradise","Cambridge"],["Leyton","Waterloo"],[10,"Leyton",24],["Leyton","Waterloo"],[10,"Waterloo",38],["Leyton","Waterloo"]]

<strong>Output</strong>
[null,null,null,null,null,null,null,14.0,11.0,null,11.0,null,12.0]

<strong>Explanation</strong>
UndergroundSystem undergroundSystem = new UndergroundSystem();
undergroundSystem.checkIn(45, "Leyton", 3);
undergroundSystem.checkIn(32, "Paradise", 8);
undergroundSystem.checkIn(27, "Leyton", 10);
undergroundSystem.checkOut(45, "Waterloo", 15);
undergroundSystem.checkOut(27, "Waterloo", 20);
undergroundSystem.checkOut(32, "Cambridge", 22);
undergroundSystem.getAverageTime("Paradise", "Cambridge");       // return 14.0. There was only one travel from "Paradise" (at time 8) to "Cambridge" (at time 22)
undergroundSystem.getAverageTime("Leyton", "Waterloo");          // return 11.0. There were two travels from "Leyton" to "Waterloo", a customer with id=45 from time=3 to time=15 and a customer with id=27 from time=10 to time=20. So the average time is ( (15-3) + (20-10) ) / 2 = 11.0
undergroundSystem.checkIn(10, "Leyton", 24);
undergroundSystem.getAverageTime("Leyton", "Waterloo");          // return 11.0
undergroundSystem.checkOut(10, "Waterloo", 38);
undergroundSystem.getAverageTime("Leyton", "Waterloo");          // return 12.0</p>
</pre>



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



<ul><li>There will be at most&nbsp;<code>20000</code>&nbsp;operations.</li><li><code>1 &lt;= id, t &lt;= 10^6</code></li><li>All strings consist of uppercase, lowercase English letters and digits.</li><li><code>1 &lt;=&nbsp;stationName.length &lt;= 10</code></li><li>Answers within&nbsp;<code>10^-5</code>&nbsp;of the actual value will be accepted as correct.</li></ul>



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



<p>For each user, store the checkin station and time.<br>For each trip (startStation + &#8220;_&#8221; + endStation), store the total time and counts.</p>



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



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

<pre class="crayon-plain-tag">// Author: Huahua
class UndergroundSystem {
public:
  UndergroundSystem() {}

  void checkIn(int id, string stationName, int t) {
    m_[id] = {stationName, t};
  }

  void checkOut(int id, string stationName, int t) {
    const auto&amp; [s0, t0] = m_[id];
    string key = s0 + &quot;_&quot; + stationName;
    times_[key].first += (t - t0);
    ++times_[key].second;
  }

  double getAverageTime(string startStation, string endStation) {
    const auto&amp; [sum, count] = times_[startStation + &quot;_&quot; + endStation];
    return static_cast&lt;double&gt;(sum) / count;
  }
private:
  unordered_map&lt;int, pair&lt;string, int&gt;&gt; m_; // id -&gt; {station, t}
  unordered_map&lt;string, pair&lt;int, int&gt;&gt; times_; // trip -&gt; {sum, count}
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/hashtable/leetcode-1396-design-underground-system/">花花酱 LeetCode 1396. Design Underground 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/hashtable/leetcode-1396-design-underground-system/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 355. Design Twitter</title>
		<link>https://zxi.mytechroad.com/blog/hashtable/leetcode-355-design-twitter/</link>
					<comments>https://zxi.mytechroad.com/blog/hashtable/leetcode-355-design-twitter/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Tue, 10 Mar 2020 08:01:02 +0000</pubDate>
				<category><![CDATA[Hashtable]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[hashtable]]></category>
		<category><![CDATA[medium]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=6454</guid>

					<description><![CDATA[<p>Design a simplified version of Twitter where users can post tweets, follow/unfollow another user and is able to see the 10 most recent tweets in&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/hashtable/leetcode-355-design-twitter/">花花酱 LeetCode 355. Design Twitter</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>Design a simplified version of Twitter where users can post tweets, follow/unfollow another user and is able to see the 10 most recent tweets in the user&#8217;s news feed. Your design should support the following methods:</p>



<ol><li><strong>postTweet(userId, tweetId)</strong>: Compose a new tweet.</li><li><strong>getNewsFeed(userId)</strong>: Retrieve the 10 most recent tweet ids in the user&#8217;s news feed. Each item in the news feed must be posted by users who the user followed or by the user herself. Tweets must be ordered from most recent to least recent.</li><li><strong>follow(followerId, followeeId)</strong>: Follower follows a followee.</li><li><strong>unfollow(followerId, followeeId)</strong>: Follower unfollows a followee.</li></ol>



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



<pre class="wp-block-preformatted;crayon:false">Twitter twitter = new Twitter();

// User 1 posts a new tweet (id = 5).
twitter.postTweet(1, 5);

// User 1's news feed should return a list with 1 tweet id -&gt; [5].
twitter.getNewsFeed(1);

// User 1 follows user 2.
twitter.follow(1, 2);

// User 2 posts a new tweet (id = 6).
twitter.postTweet(2, 6);

// User 1's news feed should return a list with 2 tweet ids -&gt; [6, 5].
// Tweet id 6 should precede tweet id 5 because it is posted after tweet id 5.
twitter.getNewsFeed(1);

// User 1 unfollows user 2.
twitter.unfollow(1, 2);

// User 1's news feed should return a list with 1 tweet id -&gt; [5],
// since user 1 is no longer following user 2.
twitter.getNewsFeed(1);</pre>



<h2><strong>Solution: hashtables</strong></h2>



<p>Time complexity:<br>postTweet O(1)<br>follow O(1)<br>unfollow O(1)<br>getNewsFeed O(nlogn)</p>



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



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

<pre class="crayon-plain-tag">// Author: Huahua
constexpr size_t kMaxTweets = 10;
class Twitter {
public:
  /** Initialize your data structure here. */
  Twitter() {}

  /** Compose a new tweet. */
  void postTweet(int userId, int tweetId) {
    auto&amp; tweets = user_tweets_[userId];
    if (tweets.size() == kMaxTweets)
      tweets.pop_front();
    tweets.emplace_back(++time_, tweetId);
  }

  /** Retrieve the 10 most recent tweet ids in the user's news feed. Each item in the news feed must be posted by users who the user followed or by the user herself. Tweets must be ordered from most recent to least recent. */
  vector&lt;int&gt; getNewsFeed(int userId) {
    vector&lt;pair&lt;int, int&gt;&gt; feed(begin(user_tweets_[userId]), 
                                end(user_tweets_[userId]));
    for (int uid : user_followers_[userId])
      feed.insert(end(feed), 
                  begin(user_tweets_[uid]), 
                  end(user_tweets_[uid]));
    sort(rbegin(feed), rend(feed));
    vector&lt;int&gt; ans;
    for (int i = 0; i &lt; min(kMaxTweets, feed.size()); ++i)
      ans.push_back(feed[i].second);
    return ans;
  }

  /** Follower follows a followee. If the operation is invalid, it should be a no-op. */
  void follow(int followerId, int followeeId) {
    if (followerId == followeeId) return;
    user_followers_[followerId].insert(followeeId);
  }

  /** Follower unfollows a followee. If the operation is invalid, it should be a no-op. */
  void unfollow(int followerId, int followeeId) {
    if (followerId == followeeId) return;
    user_followers_[followerId].erase(followeeId);
  }
private:
  int time_;
  unordered_map&lt;int, deque&lt;pair&lt;int, int&gt;&gt;&gt; user_tweets_;
  unordered_map&lt;int, set&lt;int&gt;&gt; user_followers_;
};

/**
 * Your Twitter object will be instantiated and called as such:
 * Twitter* obj = new Twitter();
 * obj-&gt;postTweet(userId,tweetId);
 * vector&lt;int&gt; param_2 = obj-&gt;getNewsFeed(userId);
 * obj-&gt;follow(followerId,followeeId);
 * obj-&gt;unfollow(followerId,followeeId);
 */</pre>
</div></div>



<p></p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/hashtable/leetcode-355-design-twitter/">花花酱 LeetCode 355. Design Twitter</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-355-design-twitter/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1146. Snapshot Array</title>
		<link>https://zxi.mytechroad.com/blog/data-structure/leetcode-1146-snapshot-array/</link>
					<comments>https://zxi.mytechroad.com/blog/data-structure/leetcode-1146-snapshot-array/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 04 Aug 2019 17:52:50 +0000</pubDate>
				<category><![CDATA[Data Structure]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[map]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=5388</guid>

					<description><![CDATA[<p>Implement a SnapshotArray that supports the following interface: SnapshotArray(int length)&#160;initializes an array-like data structure with the given length.&#160;&#160;Initially, each element equals 0. void set(index, val)&#160;sets&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/data-structure/leetcode-1146-snapshot-array/">花花酱 LeetCode 1146. Snapshot 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>Implement a SnapshotArray that supports the following interface:</p>



<ul><li><code>SnapshotArray(int length)</code>&nbsp;initializes an array-like data structure with the given length.&nbsp;&nbsp;<strong>Initially, each element equals 0</strong>.</li><li><code>void set(index, val)</code>&nbsp;sets the element at the given&nbsp;<code>index</code>&nbsp;to be equal to&nbsp;<code>val</code>.</li><li><code>int snap()</code>&nbsp;takes a snapshot of the array and returns the&nbsp;<code>snap_id</code>: the total number of times we called&nbsp;<code>snap()</code>&nbsp;minus&nbsp;<code>1</code>.</li><li><code>int get(index, snap_id)</code>&nbsp;returns the value at the given&nbsp;<code>index</code>, at the time we took the snapshot with the given&nbsp;<code>snap_id</code></li></ul>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> ["SnapshotArray","set","snap","set","get"]
[[3],[0,5],[],[0,6],[0,0]]
<strong>Output:</strong> [null,null,0,null,5]
<strong>Explanation: </strong>
SnapshotArray snapshotArr = new SnapshotArray(3); // set the length to be 3
snapshotArr.set(0,5);  // Set array[0] = 5
snapshotArr.snap();  // Take a snapshot, return snap_id = 0
snapshotArr.set(0,6);
snapshotArr.get(0,0);  // Get the value of array[0] with snap_id = 0, return 5</pre>



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



<ul><li><code>1 &lt;= length&nbsp;&lt;= 50000</code></li><li>At most&nbsp;<code>50000</code>&nbsp;calls will be made to&nbsp;<code>set</code>,&nbsp;<code>snap</code>, and&nbsp;<code>get</code>.</li><li><code>0 &lt;= index&nbsp;&lt;&nbsp;length</code></li><li><code>0 &lt;=&nbsp;snap_id &lt;&nbsp;</code>(the total number of times we call&nbsp;<code>snap()</code>)</li><li><code>0 &lt;=&nbsp;val &lt;= 10^9</code></li></ul>



<h2><strong>Solution: map + upper_bound</strong></h2>



<p>Use a vector to store maps, one map per element.<br>The map stores {snap_id -> val}, use upper_bound to find the first version > snap_id and use previous version&#8217;s value.</p>



<p>Time complexity: <br>Set: O(log|snap_id|)<br>Get: O(log|snap_id|)  <br>Snap: O(1)<br>Space complexity: O(length + set_calls)</p>



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

<pre class="crayon-plain-tag">// Author: Huahua
class SnapshotArray {
public:
  SnapshotArray(int length): id_(0), vals_(length) {}

  void set(int index, int val) {
    vals_[index][id_] = val;
  }

  int snap() { return id_++; }

  int get(int index, int snap_id) const {
    auto it = vals_[index].upper_bound(snap_id);
    if (it == begin(vals_[index])) return 0;
    return prev(it)-&gt;second;
  }
private:
  int id_;
  vector&lt;map&lt;int, int&gt;&gt; vals_;
};</pre>
</div></div>



<p><br></p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/data-structure/leetcode-1146-snapshot-array/">花花酱 LeetCode 1146. Snapshot 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/data-structure/leetcode-1146-snapshot-array/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 622. Design Circular Queue</title>
		<link>https://zxi.mytechroad.com/blog/desgin/leetcode-622-design-circular-queue/</link>
					<comments>https://zxi.mytechroad.com/blog/desgin/leetcode-622-design-circular-queue/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Fri, 13 Jul 2018 05:37:46 +0000</pubDate>
				<category><![CDATA[Desgin]]></category>
		<category><![CDATA[data structure]]></category>
		<category><![CDATA[deque]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[queue]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=3104</guid>

					<description><![CDATA[<p>Design your implementation of the circular queue. The circular queue is a linear data structure in which the operations are performed based on FIFO (First&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/desgin/leetcode-622-design-circular-queue/">花花酱 LeetCode 622. Design Circular Queue</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>Design your implementation of the circular queue. The circular queue is a linear data structure in which the operations are performed based on FIFO (First In First Out) principle and the last position is connected back to the first position to make a circle. It is also called &#8220;Ring Buffer&#8221;.</p>



<p>One of the benefits of the circular queue is that we can make use of the spaces in front of the queue. In a normal queue, once the queue becomes full, we cannot insert the next element even if there is a space in front of the queue. But using the circular queue, we can use the space to store new values.</p>



<p>Your implementation should support following operations:</p>



<ul><li><code>MyCircularQueue(k)</code>: Constructor, set the size of the queue to be k.</li><li><code>Front</code>: Get the front item from the queue. If the queue is empty, return -1.</li><li><code>Rear</code>: Get the last item from the queue. If the queue is empty, return -1.</li><li><code>enQueue(value)</code>: Insert an element into the circular queue. Return true if the operation is successful.</li><li><code>deQueue()</code>: Delete an element from the circular queue. Return true if the operation is successful.</li><li><code>isEmpty()</code>: Checks whether the circular queue is empty or not.</li><li><code>isFull()</code>: Checks whether the circular queue is full or not.</li></ul>



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



<pre class="wp-block-preformatted;crayon:false">MyCircularQueue circularQueue = new MyCircularQueue(3); // set the size to be 3
circularQueue.enQueue(1); &nbsp;// return true
circularQueue.enQueue(2); &nbsp;// return true
circularQueue.enQueue(3); &nbsp;// return true
circularQueue.enQueue(4); &nbsp;// return false, the queue is full
circularQueue.Rear(); &nbsp;// return 3
circularQueue.isFull(); &nbsp;// return true
circularQueue.deQueue(); &nbsp;// return true
circularQueue.enQueue(4); &nbsp;// return true
circularQueue.Rear(); &nbsp;// return 4
</pre>



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



<ul><li>All values will be in the range of [0, 1000].</li><li>The number of operations will be in the range of&nbsp;[1, 1000].</li><li>Please do not use the built-in Queue library.</li></ul>



<h2><strong>Solution: Simulate with an array</strong></h2>



<p>We need a fixed length array, and the head location as well as the size of the current queue.</p>



<p>We can use q[head] to access the front, and q[(head + size &#8211; 1) % k] to access the rear.</p>



<p>Time complexity: O(1) for all the operations.<br>Space complexity: O(k)</p>



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

<pre class="crayon-plain-tag">// Author: Huahua
class MyCircularQueue {
public:
  MyCircularQueue(int k): q_(k) {}
  
  bool enQueue(int value) {
    if (isFull()) return false;
    q_[(head_ + size_) % q_.size()] = value;    
    ++size_;
    return true;
  }
  
  bool deQueue() {
    if (isEmpty()) return false;
    head_ = (head_ + 1) % q_.size();
    --size_;
    return true;
  }

  int Front() { return isEmpty() ? -1 : q_[head_]; }

  int Rear() { return isEmpty() ? -1 : q_[(head_ + size_ - 1) % q_.size()]; }

  bool isEmpty() { return size_ == 0; }

  bool isFull() { return size_ == q_.size(); }
private:
  vector&lt;int&gt; q_;
  int head_ = 0;
  int size_ = 0;
};</pre>

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

<pre class="crayon-plain-tag">class MyCircularQueue {
  private int[] q;
  private int head;
  private int size;
  
  public MyCircularQueue(int k) {
    this.q = new int[k];
    this.head = 0;
    this.size = 0;
  }
  
  public boolean enQueue(int value) {
    if (this.isFull()) return false;    
    this.q[(this.head + this.size) % this.q.length] = value;
    ++this.size;
    return true;
  }

  public boolean deQueue() {
    if (this.isEmpty()) return false;
    this.head = (this.head + 1) % this.q.length;
    --this.size;
    return true;
  }

  public int Front() {
    return this.isEmpty() ? -1 : this.q[this.head];
  }

  public int Rear() {
    return this.isEmpty() ? -1 : this.q[(this.head + this.size - 1) % this.q.length];
  }

  public boolean isEmpty() { return this.size == 0; }  

  public boolean isFull() { return this.size == this.q.length; }
}</pre>

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

<pre class="crayon-plain-tag">class MyCircularQueue:
  def __init__(self, k: int):
    self.q = [0] * k
    self.k = k
    self.head = self.size = 0


  def enQueue(self, value: int) -&gt; bool:
    if self.isFull(): return False
    self.q[(self.head + self.size) % self.k] = value
    self.size += 1
    return True


  def deQueue(self) -&gt; bool:
    if self.isEmpty(): return False
    self.head = (self.head + 1) % self.k
    self.size -= 1
    return True


  def Front(self) -&gt; int:
    return -1 if self.isEmpty() else self.q[self.head]


  def Rear(self) -&gt; int:
    return -1 if self.isEmpty() else self.q[(self.head + self.size - 1) % self.k]


  def isEmpty(self) -&gt; bool:
    return self.size == 0


  def isFull(self) -&gt; bool:
    return self.size == self.k</pre>
</div></div>



<p></p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/desgin/leetcode-622-design-circular-queue/">花花酱 LeetCode 622. Design Circular Queue</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/desgin/leetcode-622-design-circular-queue/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 432. All O`one Data Structure</title>
		<link>https://zxi.mytechroad.com/blog/data-structure/leetcode-432-all-oone-data-structure/</link>
					<comments>https://zxi.mytechroad.com/blog/data-structure/leetcode-432-all-oone-data-structure/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sat, 07 Apr 2018 04:44:37 +0000</pubDate>
				<category><![CDATA[Data Structure]]></category>
		<category><![CDATA[Hashtable]]></category>
		<category><![CDATA[List]]></category>
		<category><![CDATA[data structure]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[O(1)]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=2434</guid>

					<description><![CDATA[<p>Problem 题目大意：设计一种数据结构，支持inc/dec/getmaxkey/getminkey操作，必须都在O(1)时间内完成。 https://leetcode.com/problems/all-oone-data-structure/description/ Implement a data structure supporting the following operations: Inc(Key) &#8211; Inserts a new key with value 1. Or increments an existing key by&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/data-structure/leetcode-432-all-oone-data-structure/">花花酱 LeetCode 432. All O`one Data Structure</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/wYqLisoH80w?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<h1>Problem</h1>
<p>题目大意：设计一种数据结构，支持inc/dec/getmaxkey/getminkey操作，必须都在O(1)时间内完成。</p>
<p><a href="https://leetcode.com/problems/all-oone-data-structure/description/">https://leetcode.com/problems/all-oone-data-structure/description/</a></p>
<div class="question-description">
<div>
<p>Implement a data structure supporting the following operations:</p>
<ol>
<li>Inc(Key) &#8211; Inserts a new key with value 1. Or increments an existing key by 1. Key is guaranteed to be a <b>non-empty</b> string.</li>
<li>Dec(Key) &#8211; If Key&#8217;s value is 1, remove it from the data structure. Otherwise decrements an existing key by 1. If the key does not exist, this function does nothing. Key is guaranteed to be a <b>non-empty</b> string.</li>
<li>GetMaxKey() &#8211; Returns one of the keys with maximal value. If no element exists, return an empty string <code>""</code>.</li>
<li>GetMinKey() &#8211; Returns one of the keys with minimal value. If no element exists, return an empty string <code>""</code>.</li>
</ol>
<p>Challenge: Perform all these in O(1) time complexity.</p>
</div>
<p><img class="alignnone size-full wp-image-2439" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2018/04/432-ep178.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/04/432-ep178.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/04/432-ep178-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/04/432-ep178-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
</div>
<h1><strong>Solution</strong></h1>
<p>Time complexity: O(1)</p>
<p>Space complexity: O(n), n = # of unique keys</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 32 ms
class AllOne {
public:
  /** Initialize your data structure here. */
  AllOne() {}

  /** Inserts a new key &lt;Key&gt; with value 1. Or increments an existing key by 1. */
  void inc(string key) {
    auto it = m_.find(key);
    
    if (it == m_.end()) {
      if (l_.empty() || l_.front().value != 1) 
        l_.push_front({1, {key}});
      else
        l_.front().keys.insert(key);
      m_[key] = l_.begin();
      return;
    }
    
    auto lit = it-&gt;second;
    
    auto nit = next(lit);
    if (nit == l_.end() || nit-&gt;value != lit-&gt;value + 1)
      nit = l_.insert(nit, {lit-&gt;value + 1, {}});
    nit-&gt;keys.insert(key);
    m_[key] = nit;
    
    remove(lit, key);
  }

  /** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */
  void dec(string key) {
    auto it = m_.find(key);
    if (it == m_.end()) return;
    
    auto lit = it-&gt;second;
        
    if (lit-&gt;value &gt; 1) {
      auto pit = prev(lit);
      if (lit == l_.begin() || pit-&gt;value != lit-&gt;value - 1)
        pit = l_.insert(lit, {lit-&gt;value - 1, {}});
      pit-&gt;keys.insert(key);
      m_[key] = pit;
    } else {
      // value == 1, remove from the data structure
      m_.erase(key);
    }
    
    remove(lit, key);    
  }

  /** Returns one of the keys with maximal value. */
  string getMaxKey() {
    return l_.empty() ? "" : *l_.back().keys.cbegin();
  }

  /** Returns one of the keys with Minimal value. */
  string getMinKey() {
    return l_.empty() ? "" : *l_.front().keys.cbegin();
  }
private:
  struct Node {  
    int value;
    unordered_set&lt;string&gt; keys;
  };
  
  list&lt;Node&gt; l_;
  unordered_map&lt;string, list&lt;Node&gt;::iterator&gt; m_;
  
  // Remove from old node.
  void remove(list&lt;Node&gt;::iterator it, const string&amp; key) {
    it-&gt;keys.erase(key);
    if (it-&gt;keys.empty())
      l_.erase(it);
  }
};</pre><p></p>
<h1><strong>Related Problems</strong></h1>
<ul>
<li><a href="http://zxi.mytechroad.com/blog/hashtable/leetcode-460-lfu-cache/">[解题报告] LeetCode 460. LFU Cache 花花酱</a></li>
<li><a href="http://zxi.mytechroad.com/blog/hashtable/leetcode-146-lru-cache/">[解题报告] LeetCode 146. LRU Cache O(1)</a></li>
<li><a href="http://zxi.mytechroad.com/blog/hashtable/leetcode-380-insert-delete-getrandom-o1/">[解题报告] LeetCode 380. Insert Delete GetRandom O(1)</a></li>
<li><a href="http://zxi.mytechroad.com/blog/hashtable/leetcode-381-insert-delete-getrandom-o1-duplicates-allowed/">[解题报告] LeetCode 381. Insert Delete GetRandom O(1) &amp;#8211; Duplicates allowed</a></li>
</ul>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/data-structure/leetcode-432-all-oone-data-structure/">花花酱 LeetCode 432. All O`one Data Structure</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-432-all-oone-data-structure/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 225. Implement Stack using Queues</title>
		<link>https://zxi.mytechroad.com/blog/data-structure/leetcode-225-implement-stack-using-queues/</link>
					<comments>https://zxi.mytechroad.com/blog/data-structure/leetcode-225-implement-stack-using-queues/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Tue, 13 Mar 2018 09:59:56 +0000</pubDate>
				<category><![CDATA[Data Structure]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[easy]]></category>
		<category><![CDATA[queue]]></category>
		<category><![CDATA[stack]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=2084</guid>

					<description><![CDATA[<p>题目大意：用队列来实现栈。 Problem: https://leetcode.com/problems/implement-stack-using-queues/description/ Implement the following operations of a stack using queues. push(x) &#8212; Push element x onto stack. pop() &#8212; Removes the element on&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/data-structure/leetcode-225-implement-stack-using-queues/">花花酱 LeetCode 225. Implement Stack using Queues</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>题目大意：用队列来实现栈。</p>
<p><strong>Problem:</strong></p>
<p><a href="https://leetcode.com/problems/implement-stack-using-queues/description/">https://leetcode.com/problems/implement-stack-using-queues/description/</a></p>
<p>Implement the following operations of a stack using queues.</p>
<ul>
<li>push(x) &#8212; Push element x onto stack.</li>
<li>pop() &#8212; Removes the element on top of the stack.</li>
<li>top() &#8212; Get the top element.</li>
<li>empty() &#8212; Return whether the stack is empty.</li>
</ul>
<p><b>Notes:</b></p>
<ul>
<li>You must use <i>only</i> standard operations of a queue &#8212; which means only <code>push to back</code>, <code>peek/pop from front</code>, <code>size</code>, and <code>is empty</code> operations are valid.</li>
<li>Depending on your language, queue may not be supported natively. You may simulate a queue by using a list or deque (double-ended queue), as long as you use only standard operations of a queue.</li>
<li>You may assume that all operations are valid (for example, no pop or top operations will be called on an empty stack).</li>
</ul>
<p><strong>Idea:</strong></p>
<p>Using a single queue, for every push, shift the queue (n &#8211; 1) times such that the last element becomes the first element in the queue.</p>
<p>e.g.</p>
<p>push(1): q: [1]</p>
<p>push(2): q: [1, 2] -&gt; [2, 1]</p>
<p>push(3): q: [2, 1, 3] -&gt; [1, 3, 2] -&gt; [3, 2, 1]</p>
<p>push(4): q: [3, 2, 1, 4] -&gt; [2, 1, 4, 3] -&gt; [1, 4, 3, 2] -&gt; [4, 3, 2, 1]</p>
<p><strong>Solution:</strong></p>
<p>Time complexity:</p>
<p>Push: O(n)</p>
<p>Pop/top/empty: O(1)</p>
<p>Space complexity: O(n)</p>
<p>C++</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 3 ms
class MyStack {
public:
  /** Initialize your data structure here. */
  MyStack() {}

  /** Push element x onto stack. */
  void push(int x) {
    q_.push(x);
    for (int i = 1; i &lt; q_.size(); ++i) {
      q_.push(q_.front());
      q_.pop();
    }
  }

  /** Removes the element on top of the stack and returns that element. */
  int pop() {
    int top = q_.front();
    q_.pop();
    return top;
  }

  /** Get the top element. */
  int top() {
    return q_.front();
  }

  /** Returns whether the stack is empty. */
  bool empty() {
    return q_.empty();
  }
private:
  queue&lt;int&gt; q_;  
};</pre><p>&nbsp;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/data-structure/leetcode-225-implement-stack-using-queues/">花花酱 LeetCode 225. Implement Stack using Queues</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-225-implement-stack-using-queues/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
