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

<image>
	<url>https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/cropped-photo-32x32.jpg</url>
	<title>iterator &#8211; Huahua&#8217;s Tech Road</title>
	<link>https://zxi.mytechroad.com/blog</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>花花酱 LeetCode 2296 Design a Text Editor</title>
		<link>https://zxi.mytechroad.com/blog/string/leetcode-2296-design-a-text-editor/</link>
					<comments>https://zxi.mytechroad.com/blog/string/leetcode-2296-design-a-text-editor/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Thu, 03 Apr 2025 04:08:43 +0000</pubDate>
				<category><![CDATA[String]]></category>
		<category><![CDATA[iterator]]></category>
		<category><![CDATA[list]]></category>
		<category><![CDATA[string]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=10252</guid>

					<description><![CDATA[方法1：双向链表来存储文本，迭代器指向光标所在的位置。加一个dummy head会使代码简单很多。 时间复杂度：TextEditor O(1) addText O(&#124;text&#124;) deleteText O(k) cursorLeft O(k) cursorRight(k)空间复杂度：O(n) 由于每个字符需要创建一个节点（17+个字节），虽然没有超时，但实际工程中是不能使用这种方式的。 [crayon-67f03ec69c863708227088/] 方法2: 用两个string来代表光标左边的字符串和光标右边的字符串。注：右边字符串是反转的。 左右两边的字符串只会增长（或者覆盖），不会缩短，这是用空间换时间。 删除的时候就是修改了长度而已，并没有缩短字符串，所以是O(1)的。如果缩短的话需则要O(k)时间，还要加上内存释放/再分配的时间，应该会慢一些但不多。 移动光标的时候，就是把左边字符串的最后k个copy到右边的最后面，或者反过来。同样没有缩短，只会变长。 时间复杂度: TextEditor O(1) addText O(&#124;text&#124;) deleteText O(1)&#8230;]]></description>
										<content:encoded><![CDATA[
<p>方法1：双向链表来存储文本，迭代器指向光标所在的位置。加一个dummy head会使代码简单很多。</p>



<p>时间复杂度：TextEditor O(1) addText O(|text|) deleteText O(k) cursorLeft O(k) cursorRight(k)<br>空间复杂度：O(n)</p>



<p>由于每个字符需要创建一个节点（17+个字节），虽然没有超时，但实际工程中是不能使用这种方式的。</p>



<pre class="urvanov-syntax-highlighter-plain-tag">// https://zxi.mytechroad.com/blog/string/leetcode-2296-design-a-text-editor/
class TextEditor {
public:
  TextEditor(): data_{'$'}, cursor_{begin(data_)} {}
  
  void addText(string text) {
    for (char c : text)
      cursor_ = data_.insert(++cursor_, c);
  }
  
  int deleteText(int k) {
    for (int i = 0; i &lt; k; ++i) {
      if (cursor_ == begin(data_)) return i;
      data_.erase(cursor_--);
    }
    return k;
  }
  
  string cursorLeft(int k) {
    for (int i = 0; i &lt; k; ++i) {
      if (cursor_ == begin(data_)) break;
      cursor_--;
    }
    return getText();
  }
  
  string cursorRight(int k) {
    for (int i = 0; i &lt; k; ++i) {
      if (cursor_ == prev(end(data_))) break;
      cursor_++;
    }
    return getText();
  }
private:
  string getText() {
    string ans;
    auto it = cursor_;
    for (int i = 0; i &lt; 10; ++i) {
      if (it == begin(data_)) break;
      ans += *it--;
    }
    reverse(begin(ans), end(ans));
    return ans;
  }

  list&lt;char&gt; data_;
  list&lt;char&gt;::iterator cursor_;
};</pre>



<p>方法2: 用两个string来代表光标左边的字符串和光标右边的字符串。注：右边字符串是反转的。</p>



<p>左右两边的字符串只会增长（或者覆盖），不会缩短，这是用空间换时间。</p>



<p>删除的时候就是修改了长度而已，并没有缩短字符串，所以是O(1)的。<br>如果缩短的话需则要O(k)时间，还要加上内存释放/再分配的时间，应该会慢一些但不多。</p>



<p>移动光标的时候，就是把左边字符串的最后k个copy到右边的最后面，或者反过来。同样没有缩短，只会变长。</p>



<p>时间复杂度: TextEditor O(1) addText O(|text|) deleteText O(1) cursorLeft O(k) cursorRight(k)<br>空间复杂度：O(n)，n为构建的最长的字符串</p>



<figure class="wp-block-image size-full"><a href="https://zxi.mytechroad.com/blog/wp-content/uploads/2025/04/Screenshot-2025-04-03-at-9.37.22 PM.png"><img fetchpriority="high" decoding="async" width="676" height="511" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2025/04/Screenshot-2025-04-03-at-9.37.22 PM.png" alt="" class="wp-image-10262" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2025/04/Screenshot-2025-04-03-at-9.37.22 PM.png 676w, https://zxi.mytechroad.com/blog/wp-content/uploads/2025/04/Screenshot-2025-04-03-at-9.37.22 PM-300x227.png 300w" sizes="(max-width: 676px) 100vw, 676px" /></a></figure>



<pre class="urvanov-syntax-highlighter-plain-tag">// https://zxi.mytechroad.com/blog/string/leetcode-2296-design-a-text-editor/
class TextEditor {
public:
  TextEditor() {}
  
  void addText(string_view text) {
    ensureSize(l, m + text.size());
    copy(begin(text), end(text), begin(l) + m);
    m += text.size();
  }
  
  int deleteText(int k) {
    k = min(k, m);
    m -= k;
    return k;
  }
  
  string cursorLeft(int k) {
    ensureSize(r, n + k);
    for (k = min(k, m); k &gt; 0; --k)
      r[n++] = l[--m];
    return getText();
  }
  
  string cursorRight(int k) {
    ensureSize(l, m + k);
    for (k = min(k, n); k &gt; 0; --k)
      l[m++] = r[--n];
    return getText();
  }
private:
  inline void ensureSize(string&amp; s, int size) {
    if (s.size() &lt; size)
      s.resize(size);
  }

  string getText() const {
    return string(begin(l) + m - min(m, 10), begin(l) + m);
  }

  string l;
  string r;
  int m = 0;
  int n = 0;
};</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/string/leetcode-2296-design-a-text-editor/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2353. Design a Food Rating System</title>
		<link>https://zxi.mytechroad.com/blog/hashtable/leetcode-2353-design-a-food-rating-system/</link>
					<comments>https://zxi.mytechroad.com/blog/hashtable/leetcode-2353-design-a-food-rating-system/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 30 Mar 2025 00:38:41 +0000</pubDate>
				<category><![CDATA[Hashtable]]></category>
		<category><![CDATA[hashtable]]></category>
		<category><![CDATA[iterator]]></category>
		<category><![CDATA[orderedset]]></category>
		<category><![CDATA[treeset]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=10241</guid>

					<description><![CDATA[Hashtable + TreeSet / OrderedSet 用了三个Hashtable&#8230; 菜名 -> 菜系 菜系 -> Treemap 菜名 -> 所在Treemap中的迭代器 每个菜系用一个TreeSet来保存从高到低的菜色排名，查询的时候只要拿出第一个就好了。 修改的时候，拿出迭代器，删除原来的评分，再把新的评分加入（别忘了更新迭代器） 时间复杂度：构造O(nlogn)，修改O(logn)，查询O(1) 空间复杂度：O(n) [crayon-67f03ec69cef5015121435/]]]></description>
										<content:encoded><![CDATA[
<p>Hashtable + TreeSet / OrderedSet</p>



<p>用了三个Hashtable&#8230;</p>



<ol class="wp-block-list"><li>菜名 -> 菜系</li><li>菜系 -> Treemap</li><li>菜名 -> 所在Treemap中的迭代器</li></ol>



<p>每个菜系用一个TreeSet来保存从高到低的菜色排名，查询的时候只要拿出第一个就好了。</p>



<p>修改的时候，拿出迭代器，删除原来的评分，再把新的评分加入（别忘了更新迭代器）</p>



<p>时间复杂度：构造O(nlogn)，修改O(logn)，查询O(1)</p>



<p>空间复杂度：O(n)</p>



<pre class="urvanov-syntax-highlighter-plain-tag">class FoodRatings {
public:
  FoodRatings(vector&lt;string&gt;&amp; foods, vector&lt;string&gt;&amp; cuisines, vector&lt;int&gt;&amp; ratings) {
    const int n = foods.size();
    for (int i = 0; i &lt; n; ++i) {
      n_[foods[i]] = cuisines[i];
      m_[foods[i]] = c_[cuisines[i]].emplace(-ratings[i], foods[i]).first;
    }
  }
  
  void changeRating(string food, int newRating) {
    const string&amp; cuisine = n_[food];
    c_[cuisine].erase(m_[food]);
    m_[food] = c_[cuisine].emplace(-newRating, food).first;
  }
  
  string highestRated(string cuisine) {
    return begin(c_[cuisine])-&gt;second;
  }
private:
  unordered_map&lt;string, set&lt;pair&lt;int, string&gt;&gt;&gt; c_; // cuisine -&gt; {{-rating, name}}
  unordered_map&lt;string, string&gt; n_; // food -&gt; cuisine  
  unordered_map&lt;string, set&lt;pair&lt;int, string&gt;&gt;::iterator&gt; m_; // food -&gt; set iterator
};

/**
 * Your FoodRatings object will be instantiated and called as such:
 * FoodRatings* obj = new FoodRatings(foods, cuisines, ratings);
 * obj-&gt;changeRating(food,newRating);
 * string param_2 = obj-&gt;highestRated(cuisine);
 */</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/hashtable/leetcode-2353-design-a-food-rating-system/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 3408. Design Task Manager</title>
		<link>https://zxi.mytechroad.com/blog/priority-queue/leetcode-3408-design-task-manager/</link>
					<comments>https://zxi.mytechroad.com/blog/priority-queue/leetcode-3408-design-task-manager/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Fri, 28 Mar 2025 03:45:03 +0000</pubDate>
				<category><![CDATA[Priority Queue]]></category>
		<category><![CDATA[hashtable]]></category>
		<category><![CDATA[iterator]]></category>
		<category><![CDATA[map]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[priority queue]]></category>
		<category><![CDATA[treemap]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=10229</guid>

					<description><![CDATA[pq_ 使用std::map充当优先队列，存储(priority, taskId) -> userId m_ 使用std::unordered_map，存储taskId -> pq_的迭代器 所有操作都是O(logn) [crayon-67f03ec69d0e0996967878/]]]></description>
										<content:encoded><![CDATA[
<ol class="wp-block-list"><li>pq_ 使用std::map充当优先队列，存储(priority, taskId) -> userId</li><li>m_ 使用std::unordered_map，存储taskId -> pq_的迭代器</li></ol>



<p>所有操作都是O(logn)</p>



<pre class="urvanov-syntax-highlighter-plain-tag">class TaskManager {
public:
    TaskManager(vector&lt;vector&lt;int&gt;&gt;&amp; tasks) {
      for (const auto&amp; task : tasks)
        add(task[0], task[1], task[2]);
    }

    void add(int userId, int taskId, int priority) {
      m_[taskId] = pq_.emplace(make_pair(priority, taskId), userId).first;
    }
    
    void edit(int taskId, int newPriority) {
      const int userId = m_[taskId]-&gt;second;
      rmv(taskId);
      add(userId, taskId, newPriority);
    }
    
    void rmv(int taskId) {
      auto it = m_.find(taskId);
      pq_.erase(it-&gt;second);
      m_.erase(it);
    }
    
    int execTop() {
      if (pq_.empty()) return -1;
      auto it = pq_.rbegin();
      const int userId = it-&gt;second;
      const int taskId = (it-&gt;first.second);
      rmv(taskId);
      return userId;
    }
  private:
    map&lt;std::pair&lt;int,int&gt;, int&gt; pq_; // (priority, taskId) -&gt; userId;
    unordered_map&lt;int, map&lt;std::pair&lt;int,int&gt;, int&gt;::iterator&gt; m_; // taskId -&gt; pq iterator
};</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/priority-queue/leetcode-3408-design-task-manager/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2102. Sequentially Ordinal Rank Tracker</title>
		<link>https://zxi.mytechroad.com/blog/data-structure/leetcode-2102-sequentially-ordinal-rank-tracker/</link>
					<comments>https://zxi.mytechroad.com/blog/data-structure/leetcode-2102-sequentially-ordinal-rank-tracker/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 12 Dec 2021 22:07:45 +0000</pubDate>
				<category><![CDATA[Data Structure]]></category>
		<category><![CDATA[data structure]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[iterator]]></category>
		<category><![CDATA[set]]></category>
		<category><![CDATA[treeset]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=9143</guid>

					<description><![CDATA[A scenic location is represented by its&#160;name&#160;and attractiveness&#160;score, where&#160;name&#160;is a&#160;unique&#160;string among all locations and&#160;score&#160;is an integer. Locations can be ranked from the best to the&#8230;]]></description>
										<content:encoded><![CDATA[
<p>A scenic location is represented by its&nbsp;<code>name</code>&nbsp;and attractiveness&nbsp;<code>score</code>, where&nbsp;<code>name</code>&nbsp;is a&nbsp;<strong>unique</strong>&nbsp;string among all locations and&nbsp;<code>score</code>&nbsp;is an integer. Locations can be ranked from the best to the worst. The&nbsp;<strong>higher</strong>&nbsp;the score, the better the location. If the scores of two locations are equal, then the location with the&nbsp;<strong>lexicographically smaller</strong>&nbsp;name is better.</p>



<p>You are building a system that tracks the ranking of locations with the system initially starting with no locations. It supports:</p>



<ul class="wp-block-list"><li><strong>Adding</strong>&nbsp;scenic locations,&nbsp;<strong>one at a time</strong>.</li><li><strong>Querying</strong>&nbsp;the&nbsp;<code>i<sup>th</sup></code>&nbsp;<strong>best</strong>&nbsp;location of&nbsp;<strong>all locations already added</strong>, where&nbsp;<code>i</code>&nbsp;is the number of times the system has been queried (including the current query).<ul><li>For example, when the system is queried for the&nbsp;<code>4<sup>th</sup></code>&nbsp;time, it returns the&nbsp;<code>4<sup>th</sup></code>&nbsp;best location of all locations already added.</li></ul></li></ul>



<p>Note that the test data are generated so that&nbsp;<strong>at any time</strong>, the number of queries&nbsp;<strong>does not exceed</strong>&nbsp;the number of locations added to the system.</p>



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



<ul class="wp-block-list"><li><code>SORTracker()</code>&nbsp;Initializes the tracker system.</li><li><code>void add(string name, int score)</code>&nbsp;Adds a scenic location with&nbsp;<code>name</code>&nbsp;and&nbsp;<code>score</code>&nbsp;to the system.</li><li><code>string get()</code>&nbsp;Queries and returns the&nbsp;<code>i<sup>th</sup></code>&nbsp;best location, where&nbsp;<code>i</code>&nbsp;is the number of times this method has been invoked (including this invocation).</li></ul>



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



<pre class="urvanov-syntax-highlighter-plain-tag">&lt;strong&gt;Input&lt;/strong&gt;
[&quot;SORTracker&quot;, &quot;add&quot;, &quot;add&quot;, &quot;get&quot;, &quot;add&quot;, &quot;get&quot;, &quot;add&quot;, &quot;get&quot;, &quot;add&quot;, &quot;get&quot;, &quot;add&quot;, &quot;get&quot;, &quot;get&quot;]
[[], [&quot;bradford&quot;, 2], [&quot;branford&quot;, 3], [], [&quot;alps&quot;, 2], [], [&quot;orland&quot;, 2], [], [&quot;orlando&quot;, 3], [], [&quot;alpine&quot;, 2], [], []]
&lt;strong&gt;Output&lt;/strong&gt;
[null, null, null, &quot;branford&quot;, null, &quot;alps&quot;, null, &quot;bradford&quot;, null, &quot;bradford&quot;, null, &quot;bradford&quot;, &quot;orland&quot;]
&lt;p&gt;&lt;strong&gt;Explanation&lt;/strong&gt; 
SORTracker tracker = new SORTracker(); // Initialize the tracker system.
tracker.add(&quot;bradford&quot;, 2);            // Add location with name=&quot;bradford&quot; and score=2 to the system.
tracker.add(&quot;branford&quot;, 3);            // Add location with name=&quot;branford&quot; and score=3 to the system.
tracker.get();                         // The sorted locations, from best to worst, are: branford, bradford. 
                                       // Note that branford precedes bradford due to its &lt;strong&gt;higher score&lt;/strong&gt; (3 &amp;gt; 2). 
                                       // This is the 1&lt;sup&gt;st&lt;/sup&gt; time get() is called, so return the best location: &quot;branford&quot;. 
tracker.add(&quot;alps&quot;, 2);                // Add location with name=&quot;alps&quot; and score=2 to the system.
tracker.get();                         // Sorted locations: branford, alps, bradford. 
                                       // Note that alps precedes bradford even though they have the same score (2). 
                                       // This is because &quot;alps&quot; is &lt;strong&gt;lexicographically smaller&lt;/strong&gt; than &quot;bradford&quot;. 
                                       // Return the 2&lt;sup&gt;nd&lt;/sup&gt; best location &quot;alps&quot;, as it is the 2&lt;sup&gt;nd&lt;/sup&gt; time get() is called.
tracker.add(&quot;orland&quot;, 2);              // Add location with name=&quot;orland&quot; and score=2 to the system.
tracker.get();                         // Sorted locations: branford, alps, bradford, orland. 
                                       // Return &quot;bradford&quot;, as it is the 3&lt;sup&gt;rd&lt;/sup&gt; time get() is called. 
tracker.add(&quot;orlando&quot;, 3);             // Add location with name=&quot;orlando&quot; and score=3 to the system.
tracker.get();                         // Sorted locations: branford, orlando, alps, bradford, orland. 
                                       // Return &quot;bradford&quot;. 
tracker.add(&quot;alpine&quot;, 2);              // Add location with name=&quot;alpine&quot; and score=2 to the system.
tracker.get();                         // Sorted locations: branford, orlando, alpine, alps, bradford, orland. 
                                       // Return &quot;bradford&quot;. 
tracker.get();                         // Sorted locations: branford, orlando, alpine, alps, bradford, orland. 
                                       // Return &quot;orland&quot;.
&lt;/p&gt;</pre>



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



<ul class="wp-block-list"><li><code>name</code>&nbsp;consists of lowercase English letters, and is unique among all locations.</li><li><code>1 &lt;= name.length &lt;= 10</code></li><li><code>1 &lt;= score &lt;= 10<sup>5</sup></code></li><li>At any time, the number of calls to&nbsp;<code>get</code>&nbsp;does not exceed the number of calls to&nbsp;<code>add</code>.</li><li>At most&nbsp;<code>4 * 10<sup>4</sup></code>&nbsp;calls&nbsp;<strong>in total</strong>&nbsp;will be made to&nbsp;<code>add</code>&nbsp;and&nbsp;<code>get</code>.</li></ul>



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



<p>Use a treeset to store all the entries and use a iterator that points to the entry to return. When inserting a new entry into the tree, if it&#8217;s higher than the current element then let the iterator go backward one step. </p>



<p>Time complexity:  add O(logn) / get O(1)</p>



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

<pre class="urvanov-syntax-highlighter-plain-tag">// Author: Huahua
class SORTracker {
public:
  SORTracker() {}

  void add(string name, int score) {    
    if (*s.emplace(-score, name).first &lt; *cit) --cit;
  }

  string get() {
    return (cit++)-&gt;second;
  }
private:
  set&lt;pair&lt;int, string&gt;&gt; s;
  // Note: cit points to begin(s) after first insertion.
  set&lt;pair&lt;int, string&gt;&gt;::const_iterator cit = end(s);
};</pre>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/data-structure/leetcode-2102-sequentially-ordinal-rank-tracker/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[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;]]></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 class="wp-block-list"><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 class="wp-block-list"><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 class="wp-block-list"><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 class="wp-block-heading"><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="urvanov-syntax-highlighter-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>
]]></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>Iterables in Python</title>
		<link>https://zxi.mytechroad.com/blog/python/iterables-in-python/</link>
					<comments>https://zxi.mytechroad.com/blog/python/iterables-in-python/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Tue, 30 Jun 2020 01:04:13 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[expcetion]]></category>
		<category><![CDATA[iterables]]></category>
		<category><![CDATA[iterator]]></category>
		<category><![CDATA[python]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=7018</guid>

					<description><![CDATA[Example Code: [crayon-67f03ec69dd5f451300196/]]]></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="可迭代的 Iterables - Python Weekly EP4" width="500" height="281" src="https://www.youtube.com/embed/-PklUOOz4n8?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



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



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

<pre class="urvanov-syntax-highlighter-plain-tag"># Author: Huahua
class MyListIterator:
  def __init__(self, my_list, index=0):
    self.my_list = my_list
    self.index = index

  def __next__(self):
    if self.index &lt; len(self.my_list.data):
      val = self.my_list.data[self.index]
      self.index += 1
      return val
    else:
      raise StopIteration()

  def __iter__(self):
    return MyListIterator(self.my_list, self.index)
    # return self

class MyList:
  def __init__(self, data):
    self.data = list(data)

  def __getitem__(self, index):
    return self.data[index]

  def __len__(self):
    return len(self.data)

  def __iter__(self):
    return MyListIterator(self)

my_list = MyList([1,2,3,4,5])
it = iter(my_list)
next(it)
it2 = iter(it)
next(it)
print('--- it ---')
for x in it:
  print(x) # 3, 4, 5
print('--- it2 ---')
for x in it2:
  print(x) # 2, 3, 4, 5</pre>
</div></div>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/python/iterables-in-python/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
