<?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>SP Archives - Huahua&#039;s Tech Road</title>
	<atom:link href="https://zxi.mytechroad.com/blog/category/sp/feed/" rel="self" type="application/rss+xml" />
	<link>https://zxi.mytechroad.com/blog/category/sp/</link>
	<description></description>
	<lastBuildDate>Mon, 04 Jan 2021 07:17:22 +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>SP Archives - Huahua&#039;s Tech Road</title>
	<link>https://zxi.mytechroad.com/blog/category/sp/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>花花酱 Min Heap SP21</title>
		<link>https://zxi.mytechroad.com/blog/sp/min-heap-sp21/</link>
					<comments>https://zxi.mytechroad.com/blog/sp/min-heap-sp21/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Wed, 18 Nov 2020 09:30:19 +0000</pubDate>
				<category><![CDATA[SP]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=7678</guid>

					<description><![CDATA[<p>[crayon-663c0e25a69c9832722857/] [crayon-663c0e25a69ce154538713/]</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/min-heap-sp21/">花花酱 Min Heap SP21</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="花花酱 Min Heap - 刷题找工作 SP21" width="500" height="281" src="https://www.youtube.com/embed/mnSMdTPBG1U?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<figure class="wp-block-image size-large"><img width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/sp21-1.png" alt="" class="wp-image-7685" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/sp21-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/sp21-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/sp21-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/sp21-2.png" alt="" class="wp-image-7686" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/sp21-2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/sp21-2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/sp21-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/sp21-3.png" alt="" class="wp-image-7687" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/sp21-3.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/sp21-3-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/sp21-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/sp21-4.png" alt="" class="wp-image-7688" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/sp21-4.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/sp21-4-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/sp21-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/sp21-6.png" alt="" class="wp-image-7689" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/sp21-6.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/sp21-6-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/sp21-6-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/sp21-7.png" alt="" class="wp-image-7690" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/sp21-7.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/sp21-7-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/sp21-7-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/sp21-8.png" alt="" class="wp-image-7691" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/sp21-8.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/sp21-8-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/sp21-8-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/sp21-9.png" alt="" class="wp-image-7692" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/sp21-9.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/sp21-9-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/11/sp21-9-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
#include &lt;assert.h&gt;

#include &lt;iostream&gt;
#include &lt;vector&gt;

using namespace std;

class MinHeap {
public:
  // Return the min element.
  int peek() const { return data_[0]; }

  // Extract the min element.
  int pop() {
    // Swap the min element with the last one. O(1)
    swap(data_.back(), data_[0]);
    // Get the min element. O(1)
    int min_el = data_.back();
    // Evict the min element. O(1)
    data_.pop_back();
    // Maintain heap property. &theta;(logn)
    heapifyDown(0);
    return min_el;
  }

  // Add a new element to the heap.
  void push(int key) {
    // Add the element to the end of the array. O(1)
    data_.push_back(key);
    // Maintain heap property. &theta;(logn)
    heapifyUp(data_.size() - 1);
  }

  // Return the size of the heap.
  int size() const { return data_.size(); }
private:
  void heapifyUp(int index) {
    // Stop at root.
    if (index == 0) return;
    int parent = (index - 1) / 2;
    // Stop if greater or euqal to parent.
    if (data_[index] &gt;= data_[parent]) return;
    // Swap with parent.
    swap(data_[index], data_[parent]);
    // Continue heapifyUp on parent.
    heapifyUp(parent);
  }

  void heapifyDown(int index) {
    int left = index * 2 + 1;
    int right = index * 2 + 2;
    // Stop if has no left child.
    if (left &gt;= data_.size()) return;
    // Get the min child.
    int min_child = 
      right &lt; data_.size() &amp;&amp; data_[right] &lt; data_[left] ? right : left;
    // Stop if less or euqal to min child.
    if (data_[index] &lt;= data_[min_child])
      return;
    // Swap with min child.
    swap(data_[index], data_[min_child]);
    // Continue heapifyDown on min_child.
    heapifyDown(min_child);
  }

  vector&lt;int&gt; data_;
};

int main() {
  vector&lt;int&gt; data{5,1,3,5,3,4,3,7};
  MinHeap heap;
  for (int x : data)
    heap.push(x);
  vector&lt;int&gt; output;
  while (heap.size())
    output.push_back(heap.pop());
  assert(output == vector&lt;int&gt;({1,3,3,3,4,5,5,7}));
}</pre>

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

<pre class="crayon-plain-tag"># Author: Huahua
class MinHeap:
  def __init__(self, data = None):
    self.data = list(data) if data else []
    for i in range((len(self.data)) // 2, -1, -1):
      self.heapifyDown(i)

  def push(self, key):
    self.data.append(key)
    self.heapifyUp(len(self.data) - 1)
 
  def pop(self):
    self.swap(0, -1)
    min_el = self.data.pop()
    self.heapifyDown(0)
    return min_el
 
  def size(self):
    return len(self.data)
 
  def swap(self, i, j):
    self.data[i], self.data[j] = self.data[j], self.data[i]
 
  def heapifyDown(self, i):
    smallest = i
    for c in [2 * i + 1, 2 * i + 2]:
      if c &lt; self.size() and self.data[c] &lt; self.data[smallest]: smallest = c
    if smallest != i:
      self.swap(i, smallest)
      self.heapifyDown(smallest)
 
  def heapifyUp(self, i):
    if i == 0: return
    parent = (i - 1) // 2
    if self.data[i] &gt;= self.data[parent]: return
    self.swap(i, parent)
    self.heapifyUp(parent)

def test():
  data = [5,1,3,5,3,4,3,7]
  heap = MinHeap()
  for x in data: heap.push(x)
  output = []
  while heap.size():
    output.append(heap.pop())
  assert output == sorted(data)

def testBuildHeap():
  data = [5,1,3,5,3,4,3,7]
  heap = MinHeap(data)
  output = []
  while heap.size():
    output.append(heap.pop())
  assert output == sorted(data)

def main():
  test()
  testBuildHeap()
 
if __name__ == '__main__':
  main()</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/min-heap-sp21/">花花酱 Min Heap SP21</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/sp/min-heap-sp21/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Fast Power for DP SP20</title>
		<link>https://zxi.mytechroad.com/blog/sp/fast-power-for-dp-sp20/</link>
					<comments>https://zxi.mytechroad.com/blog/sp/fast-power-for-dp-sp20/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Thu, 16 Apr 2020 03:37:45 +0000</pubDate>
				<category><![CDATA[SP]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=6621</guid>

					<description><![CDATA[<p>Iterative DP usually takes O(n) to compute dp[n] from dp[0], we could do better if the problem can be written as matrix multiplication. With fast&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/fast-power-for-dp-sp20/">Fast Power for DP SP20</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="花花酱 Fast Power for DP - 刷题找工作 SP20" width="500" height="375" src="https://www.youtube.com/embed/Ol1e4TOHvno?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<p>Iterative DP usually takes O(n) to compute dp[n] from dp[0], we could do better if the problem can be written as matrix multiplication. With fast power, dp[n] can be computed in O(logn)</p>



<figure class="wp-block-image size-large"><img width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/04/sp-20-1.png" alt="" class="wp-image-6622" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/04/sp-20-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/04/sp-20-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/04/sp-20-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/04/sp-20-2.png" alt="" class="wp-image-6623" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/04/sp-20-2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/04/sp-20-2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/04/sp-20-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/04/sp-20-3.png" alt="" class="wp-image-6624" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/04/sp-20-3.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/04/sp-20-3-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/04/sp-20-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/04/sp20-4.png" alt="" class="wp-image-6625" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/04/sp20-4.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/04/sp20-4-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/04/sp20-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/04/sp20-5.png" alt="" class="wp-image-6626" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/04/sp20-5.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/04/sp20-5-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/04/sp20-5-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/04/sp-20-6.png" alt="" class="wp-image-6627" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2020/04/sp-20-6.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/04/sp-20-6-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2020/04/sp-20-6-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></figure>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/fast-power-for-dp-sp20/">Fast Power for DP SP20</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/sp/fast-power-for-dp-sp20/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>KMP Algorithm SP19</title>
		<link>https://zxi.mytechroad.com/blog/sp/kmp-algorithm-sp19/</link>
					<comments>https://zxi.mytechroad.com/blog/sp/kmp-algorithm-sp19/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Wed, 01 Apr 2020 03:29:45 +0000</pubDate>
				<category><![CDATA[SP]]></category>
		<category><![CDATA[kmp]]></category>
		<category><![CDATA[prefix]]></category>
		<category><![CDATA[sp]]></category>
		<category><![CDATA[suffix]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=6556</guid>

					<description><![CDATA[<p>KMP Algorithm, KMP 字符串搜索算法 Time complexity: O(m+n)Space complexity: O(m) Implementation [crayon-663c0e25a6e49686052149/] [crayon-663c0e25a6e4c331801580/] Applications LeetCode 28. strStr() [crayon-663c0e25a6e4e956327083/] LeetCode 459.&#160;Repeated Substring Pattern [crayon-663c0e25a6e4f440359097/] 1392.&#160;Longest Happy Prefix&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/kmp-algorithm-sp19/">KMP Algorithm SP19</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="花花酱 KMP Algorithm - 刷题找工作 SP19" width="500" height="375" src="https://www.youtube.com/embed/uKr9qIZMtzw?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<p>KMP Algorithm, KMP 字符串搜索算法</p>



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



<h2><strong>Implementation</strong></h2>



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

<pre class="crayon-plain-tag">#include &lt;iostream&gt;
#include &lt;vector&gt;
using namespace std;

// Author: Huahua
namespace KMP {
vector&lt;int&gt; Build(const string&amp; p) {
  const int m = p.length();
  vector&lt;int&gt; nxt{0, 0};
  for (int i = 1, j = 0; i &lt; m; ++i) {
    while (j &gt; 0 &amp;&amp; p[i] != p[j])
      j = nxt[j];
    if (p[i] == p[j])
      ++j;
    nxt.push_back(j);
  }
  return nxt;
}

vector&lt;int&gt; Match(const string&amp; s, const string&amp; p) {
  vector&lt;int&gt; nxt(Build(p));
  vector&lt;int&gt; ans;
  const int n = s.length();
  const int m = p.length();
  for (int i = 0, j = 0; i &lt; n; ++i) {
    while (j &gt; 0 &amp;&amp; s[i] != p[j])
      j = nxt[j];
    if (s[i] == p[j])
      ++j;
    if (j == m) {
      ans.push_back(i - m + 1);
      j = nxt[j];
    }
  }
  return ans;
}
};  // namespace KMP

void CheckEQ(const vector&lt;int&gt;&amp; actual, const vector&lt;int&gt;&amp; expected) {
  if (actual != expected) {
    std::cout &lt;&lt; &quot;expected:&quot;;
    for (int v : expected)
      std::cout &lt;&lt; &quot; &quot; &lt;&lt; v;
    std::cout &lt;&lt; &quot; actual:&quot;;
    for (int v : actual)
      std::cout &lt;&lt; &quot; &quot; &lt;&lt; v;
    std::cout &lt;&lt; std::endl;
  } else {
    std::cout &lt;&lt; &quot;PASS&quot; &lt;&lt; std::endl;
  }
}

int main(int argc, char** argv) {
  CheckEQ(KMP::Build(&quot;ABCDABD&quot;), {0, 0, 0, 0, 0, 1, 2, 0});
  CheckEQ(KMP::Build(&quot;AB&quot;), {0, 0, 0});
  CheckEQ(KMP::Build(&quot;A&quot;), {0, 0});
  CheckEQ(KMP::Build(&quot;AA&quot;), {0, 0, 1});
  CheckEQ(KMP::Build(&quot;AAA&quot;), {0, 0, 1, 2});
  CheckEQ(KMP::Build(&quot;AABA&quot;), {0, 0, 1, 0, 1});
  CheckEQ(KMP::Match(&quot;ABC ABCDAB ABCDABCDABDE&quot;, &quot;ABCDABD&quot;), {15});
  CheckEQ(KMP::Match(&quot;ABC ABCDAB ABCDABCDABDE&quot;, &quot;AB&quot;), {0, 4, 8, 11, 15, 19});
  CheckEQ(KMP::Match(&quot;ABC ABCDAB ABCDABCDABDE&quot;, &quot;B&quot;), {1, 5, 9, 12, 16, 20});
  CheckEQ(KMP::Match(&quot;AAAAA&quot;, &quot;A&quot;), {0, 1, 2, 3, 4});
  CheckEQ(KMP::Match(&quot;AAAAA&quot;, &quot;AA&quot;), {0, 1, 2, 3});
  CheckEQ(KMP::Match(&quot;AAAAA&quot;, &quot;AAA&quot;), {0, 1, 2});
  CheckEQ(KMP::Match(&quot;ABC&quot;, &quot;ABC&quot;), {0});
  return 0;
}</pre>

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

<pre class="crayon-plain-tag">#!/usr/bin/env python3
from typing import List

# Author: Huahua


def Build(p: str) -&gt; List[int]:
    m = len(p)
    nxt = [0, 0]
    j = 0
    for i in range(1, m):
        while j &gt; 0 and p[i] != p[j]:
            j = nxt[j]
        if p[i] == p[j]:
            j += 1
        nxt.append(j)
    return nxt


def Match(s: str, p: str) -&gt; List[int]:
    n, m = len(s), len(p)
    nxt = Build(p)
    ans = []
    j = 0
    for i in range(n):
        while j &gt; 0 and s[i] != p[j]:
            j = nxt[j]
        if s[i] == p[j]:
            j += 1
        if j == m:
            ans.append(i - m + 1)
            j = nxt[j]
    return ans


def CheckEQ(actual, expected):
    if actual != expected:
        print('actual: %s, expected: %s' % (actual, expected))
    else:
        print('Pass')


if __name__ == &quot;__main__&quot;:
    CheckEQ(Build(&quot;ABCDABD&quot;), [0, 0, 0, 0, 0, 1, 2, 0])
    CheckEQ(Build(&quot;AB&quot;), [0, 0, 0])
    CheckEQ(Build(&quot;A&quot;), [0, 0])
    CheckEQ(Build(&quot;AA&quot;), [0, 0, 1])
    CheckEQ(Build(&quot;AAAA&quot;), [0, 0, 1, 2, 3])
    CheckEQ(Build(&quot;AABA&quot;), [0, 0, 1, 0, 1])
    CheckEQ(Match(&quot;ABC ABCDAB ABCDABCDABDE&quot;, &quot;ABCDABD&quot;), [15])
    CheckEQ(Match(&quot;ABC ABCDAB ABCDABCDABDE&quot;, &quot;AB&quot;), [0, 4, 8, 11, 15, 19])
    CheckEQ(Match(&quot;ABC ABCDAB ABCDABCDABDE&quot;, &quot;B&quot;), [1, 5, 9, 12, 16, 20])
    CheckEQ(Match(&quot;AAAAA&quot;, &quot;A&quot;), [0, 1, 2, 3, 4])
    CheckEQ(Match(&quot;AAAAA&quot;, &quot;AA&quot;), [0, 1, 2, 3])
    CheckEQ(Match(&quot;AAAAA&quot;, &quot;AAAA&quot;), [0, 1])
    CheckEQ(Match(&quot;AAAAA&quot;, &quot;AAAAA&quot;), [0])
    CheckEQ(Match(&quot;AABAABA&quot;, &quot;AABA&quot;), [0, 3])</pre>
</div></div>



<h2><strong>Applications</strong></h2>



<p>LeetCode 28. strStr()</p>



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

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  int strStr(string haystack, string needle) {
    if (needle.empty()) return 0;
    auto matches = KMP::Match(haystack, needle);
    return matches.empty() ? -1 : matches[0];
  }
};</pre>
</div></div>



<p>LeetCode 459.&nbsp;Repeated Substring Pattern</p>



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

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  bool repeatedSubstringPattern(string str) {
    const int n = str.length();
    auto nxt = KMP::Build(str);
    return nxt[n] &amp;amp;&amp;amp; nxt[n] % (n - nxt[n]) == 0;
  }
};</pre>
</div></div>



<p><a href="https://zxi.mytechroad.com/blog/string/leetcode-1392-longest-happy-prefix/">1392.&nbsp;Longest Happy Prefix</a></p>



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

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  string longestPrefix(const string&amp;amp; s) {    
    return s.substr(0, KMP::Build(s).back());
  }
};</pre>
</div></div>



<p></p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/kmp-algorithm-sp19/">KMP Algorithm SP19</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/sp/kmp-algorithm-sp19/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 Minimum Spanning Tree (MST) 最小生成树 SP18</title>
		<link>https://zxi.mytechroad.com/blog/sp/minimum-spanning-tree-sp18/</link>
					<comments>https://zxi.mytechroad.com/blog/sp/minimum-spanning-tree-sp18/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Fri, 24 Jan 2020 15:59:23 +0000</pubDate>
				<category><![CDATA[SP]]></category>
		<category><![CDATA[graph]]></category>
		<category><![CDATA[MST]]></category>
		<category><![CDATA[O(ElogV)]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=6124</guid>

					<description><![CDATA[<p>Prim&#8217;s Algorithm Time complexity: O(ElogV)Space complexity: O(V+E) [crayon-663c0e25a704b765844402/] [crayon-663c0e25a704e892660667/] Kruskal&#8217;s Algorithm Time complexity: O(ElogV)Space complexity: O(V+E) [crayon-663c0e25a7050272969303/] [crayon-663c0e25a7051509806706/]</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/minimum-spanning-tree-sp18/">花花酱 Minimum Spanning Tree (MST) 最小生成树 SP18</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 - 最小生成树 (Minimum Spanning Tree) 刷题找工作 SP18" width="500" height="281" src="https://www.youtube.com/embed/wmW8G8SrXDs?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<h2><strong>Prim&#8217;s Algorithm</strong></h2>



<p>Time complexity: O(ElogV)<br>Space complexity: O(V+E)</p>



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

<pre class="crayon-plain-tag">// Author: Huahua
#include &lt;iostream&gt;
#include &lt;queue&gt;
#include &lt;vector&gt;
using namespace std;

int main(int argc, char** argv) {
  const int n = 4;
  vector&lt;vector&lt;int&gt;&gt; edges{{0,1,1},{0,3,3},{0,2,6},{2,3,2},{1,2,4},{1,3,5}};
  vector&lt;vector&lt;pair&lt;int, int&gt;&gt;&gt; g(n);
  for (const auto&amp; e : edges) {
    g[e[0]].emplace_back(e[1], e[2]);
    g[e[1]].emplace_back(e[0], e[2]);
  }

  priority_queue&lt;pair&lt;int, int&gt;&gt; q; // (-w, v)
  vector&lt;int&gt; seen(n);
  q.emplace(0, 0); // (-w, v)

  int cost = 0;
  for (int i = 0; i &lt; n; ++i) {
    while (true) {
      const int w = -q.top().first;
      const int v = q.top().second;
      q.pop();
      if (seen[v]++) continue;
      cost += w;
      for (const auto&amp; p : g[v]) {
        if (seen[p.first]) continue;
        q.emplace(-p.second, p.first);
      }
      break;
    }
  }
  cout &lt;&lt; cost &lt;&lt; endl;
  return 0;
}</pre>
</div></div>



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

<pre class="crayon-plain-tag"># Author: Huahua
from collections import defaultdict
from heapq import *

n = 4
edges = [[0,1,1],[0,3,3],[0,2,6],[2,3,2],[1,2,4],[1,3,5]]
g = defaultdict(list)
for e in edges:
  g[e[0]].append((e[1], e[2]))
  g[e[1]].append((e[0], e[2]))

q = []
cost = 0
seen = set()
heappush(q, (0, 0))
for _ in range(n):
  while True:
    w, u = heappop(q)
    if u in seen: continue  
    cost += w
    seen.add(u)
    for v, w in g[u]:
      if v in seen: continue
      heappush(q, (w, v))
    break

print(cost)</pre>
</div></div>



<h2><strong>Kruskal&#8217;s Algorithm</strong></h2>



<p>Time complexity: O(ElogV)<br>Space complexity: O(V+E)</p>



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

<pre class="crayon-plain-tag">// Author: Huahua
#include &lt;iostream&gt;
#include &lt;queue&gt;
#include &lt;vector&gt;
#include &lt;functional&gt;
#include &lt;numeric&gt;
using namespace std;

int main(int argc, char** argv) {
  const int n = 4;
  vector&lt;vector&lt;int&gt;&gt; edges{{0,1,1},{0,3,3},{0,2,6},{2,3,2},{1,2,4},{1,3,5}};    
  vector&lt;vector&lt;int&gt;&gt; q; // (w, u, v)  
  for (const auto&amp; e : edges)    
    q.push_back({e[2], e[0], e[1]});
  sort(begin(q), end(q));

  vector&lt;int&gt; p(n);
  iota(begin(p), end(p), 0);

  function&lt;int(int)&gt; find = [&amp;](int x) {
    return x == p[x] ? x : p[x] = find(p[p[x]]);
  };

  int cost = 0;
  for (const auto&amp; t : q) {    
    int w = t[0], u = t[1], v = t[2];      
    int ru = find(u), rv = find(v);      
    if (ru == rv) continue;
    p[ru] = rv; // merge (u, v)      
    cost += w;
  }  
  cout &lt;&lt; cost &lt;&lt; endl;

  return 0;
}</pre>
</div></div>



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

<pre class="crayon-plain-tag">from collections import defaultdict
from heapq import *

n = 4
edges = [[0,1,1],[0,3,3],[0,2,6],[2,3,2],[1,2,4],[1,3,5]]
p = list(range(n))


def find(x):
  if x != p[x]: p[x] = find(p[p[x]])
  return p[x]

cost = 0
for u, v, w in sorted(edges, key=lambda x: x[2]):
  ru, rv = find(u), find(v)
  if ru == rv: continue
  p[ru] = rv
  cost += w

print(cost)</pre>
</div></div>



<p></p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/minimum-spanning-tree-sp18/">花花酱 Minimum Spanning Tree (MST) 最小生成树 SP18</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/sp/minimum-spanning-tree-sp18/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 Binary Search II SP17</title>
		<link>https://zxi.mytechroad.com/blog/sp/binary-search-ii-sp17/</link>
					<comments>https://zxi.mytechroad.com/blog/sp/binary-search-ii-sp17/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sat, 20 Apr 2019 16:48:35 +0000</pubDate>
				<category><![CDATA[SP]]></category>
		<category><![CDATA[binary search]]></category>
		<category><![CDATA[sp]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=5082</guid>

					<description><![CDATA[<p>Binary Search I SP5 For the given function g(x) and a range [l, r] find the smallest int number m such that g(m) is True,&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/binary-search-ii-sp17/">花花酱 Binary Search II SP17</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe width="500" height="375" src="https://www.youtube.com/embed/J-IQxfYRTto?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<p><a href="https://zxi.mytechroad.com/blog/sp/sp5-binary-search/">Binary Search I SP5</a></p>



<p>For the given function g(x) and a range [l, r] find the smallest int number m such that g(m) is True, if not found, return r + 1.</p>



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



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



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



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



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



<figure class="wp-block-image"><img width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2019/04/6.png" alt="" class="wp-image-5089" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2019/04/6.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2019/04/6-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2019/04/6-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></figure>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/binary-search-ii-sp17/">花花酱 Binary Search II SP17</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/sp/binary-search-ii-sp17/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>LeetCode 进入千题时代该如何刷题？</title>
		<link>https://zxi.mytechroad.com/blog/sp/leetcode-1000-problems-era/</link>
					<comments>https://zxi.mytechroad.com/blog/sp/leetcode-1000-problems-era/#comments</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sat, 16 Feb 2019 18:15:46 +0000</pubDate>
				<category><![CDATA[SP]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=4851</guid>

					<description><![CDATA[<p>题目列表：https://bit.ly/2E8yBHq 总结一下： 大家的刷题经验都比我丰富，找到最适合自己的方法就好了 200～300题刷2-3边，至少100+小时的投入 同一类型题目一起刷，总结规律和差异 多看别人的（优秀）代码 完整的手写实现，不要copy代码，增强肌肉记忆（视频中没提到） 培养代码风格</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/leetcode-1000-problems-era/">LeetCode 进入千题时代该如何刷题？</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe width="500" height="375" src="https://www.youtube.com/embed/NdWYxz3izH4?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>


<p><script async="" src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script><br>
<ins class="adsbygoogle" style="display:block" data-ad-format="fluid" data-ad-layout-key="-fb+5w+4e-db+86" data-ad-client="ca-pub-2404451723245401" data-ad-slot="2162692788"></ins><br>
<script><br />
     (adsbygoogle = window.adsbygoogle || []).push({});<br />
</script></p>


<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe width="500" height="375" src="https://www.youtube.com/embed/NxGWDh-0jAg?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<p>题目列表：<a href="https://bit.ly/2E8yBHq">https://bit.ly/2E8yBHq</a></p>



<p>总结一下： </p>



<ul><li> 大家的刷题经验都比我丰富，找到最适合自己的方法就好了 </li><li>200～300题刷2-3边，至少100+小时的投入</li><li>同一类型题目一起刷，总结规律和差异 </li><li>多看别人的（优秀）代码</li><li>完整的手写实现，不要copy代码，增强肌肉记忆（视频中没提到） </li><li>培养代码风格 </li></ul>


<p><script async="" src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script><br>
<ins class="adsbygoogle" style="display:block" data-ad-format="fluid" data-ad-layout-key="-fb+5w+4e-db+86" data-ad-client="ca-pub-2404451723245401" data-ad-slot="2162692788"></ins><br>
<script><br />
     (adsbygoogle = window.adsbygoogle || []).push({});<br />
</script></p><p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/leetcode-1000-problems-era/">LeetCode 进入千题时代该如何刷题？</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/sp/leetcode-1000-problems-era/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 Segment Tree 线段树 SP14</title>
		<link>https://zxi.mytechroad.com/blog/sp/segment-tree-sp14/</link>
					<comments>https://zxi.mytechroad.com/blog/sp/segment-tree-sp14/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Wed, 30 Jan 2019 16:41:06 +0000</pubDate>
				<category><![CDATA[SP]]></category>
		<category><![CDATA[O(logn)]]></category>
		<category><![CDATA[range sum]]></category>
		<category><![CDATA[segment tree]]></category>
		<category><![CDATA[tree]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=4738</guid>

					<description><![CDATA[<p>Segment tree is a balanced binary tree with O(logn) height given n input segments.Segment tree supports fast range query O(logn + k), and update O(logn).Building&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/segment-tree-sp14/">花花酱 Segment Tree 线段树 SP14</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe width="500" height="375" src="https://www.youtube.com/embed/rYBtViWXYeI?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<p>Segment tree is a balanced binary tree with O(logn) height given n input segments.<br>Segment tree supports fast range query O(logn + k), and update O(logn).<br>Building such a tree takes O(n) time if the input is an array of numbers.</p>



<p>Tree之所以大行其道就是因为其结构和人类组织结构非常接近。就拿公司来说好了，CEO统领全局(root)，下面CTO，CFO等各自管理一个部门，每个部门下面又正好有好两个VP，每个VP下面又有两个director，每个director下面又有2个manager，每个manager下面又有2个底层员工(leaf)，为什么是2？因为我们用二叉树啊~</p>



<p>故事还是要从LeetCode 307. Range Sum Query &#8211; Mutable说起。</p>



<p>题目大意是：给你一个数组，再给你一个范围，让你求这个范围内所有元素的和，其中元素的值是可变的，通过update(index, val)更新。&nbsp;</p>



<p>nums = [1, 3, 5]，<br>sumRange(0, 2) = 1+3+5 = 9<br>update(1, 2) =&gt; [1, 2, 5]<br>sumRange(0, 2) = 1 + 2 + 5 = 7</p>



<p>暴力求解就是扫描一下这个范围。</p>



<p>时间复杂度：Update O(1), Query O(n)。</p>



<p>如果数组元素不变的话（303题），我们可以使用动态规划求出前n个元素的和然后存在sums数组中。i到j所有元素的和等于0~j所有元素的和减去0~(i-1)所有元素的和，即：</p>



<p>sumRange(i, j) := sums[j] &#8211; sums[i &#8211; 1] if i &gt; 0 else sums[j]</p>



<p>这样就可以把query的时间复杂度降低到O(1)。</p>



<p>但是这道题元素的值可变，那么就需要维护sums，虽然可以把query的时间复杂度降低到了O(1)，但update的时间复杂度是O(n)，并没有比暴力求解快。</p>



<p>这个时候就要请出我们今天的主人公Segment Tree了，可以做到</p>



<p>Update: O(logn)，Query: O(logn+k)</p>



<p>其实Segment Tree的思想还是很好理解的，比我们之前讲过的Binary Indexed Tree要容易理解的多（回复&nbsp;<strong>SP3</strong>&nbsp;获取视频），但是代码量又是另外一回事情了&#8230;</p>



<p>回到一开始讲的公司组织结构上面，假设一个公司有200个底层员工，</p>



<p>最原始的信息（元素的值）只掌握在他们工手里，层层上报。每个manager把他所管理的人的元素值求和之后继续上报，直到CEO。CEO知道但仅知道0-199的和。</p>



<p>当你问CEO，5到199的和是多少？他手上只有0-199的和，一下子慌了，赶紧找来CTO，CFO说你们把5到199的和给报上来，CFO一看报表，心中暗喜：还好我负责的这个区间(100~199)已经计算过了，就直接把之前的总和上报了。CTO一看报表，自己负责0-99这个区间，只知道0-99的和，但5-99的和，还是问下面的人吧&#8230; 最后结果再一层层返回给CEO。</p>



<p>说到这里大家应该已经能想象Segment Tree是怎么工作了吧：</p>



<p>每个leaf负责一个元素的值</p>



<p>每个parent负责的范围是他的children所负责的范围的union，并把所有范围内的元素值相加。</p>



<p>同一层的节点没有overlap。</p>



<p>root存储的是所有元素的和。</p>



<p>所以一个SegmentTreeNode需要记录以下信息</p>



<p>start #起始范围<br>end #终止范围<br>mid #拆分点，通常是 (start + end) // 2<br>val #所有子元素的和<br>left #左子树<br>right #右子树</p>



<p>Update: 由于每次只更新一个元素的值，所以CEO知道这个员工是哪个人管的，派发下去就行了，然后把新的结果再返回回来。</p>



<pre class="crayon-plain-tag">def update(root, index, val):
  # 到底层员工了，直接更新
  if root.start == index and root.end == index:
    root.val = val
    return
  # 根据拆分点，更新左子树或右子树
  if val &lt;= root.mid:
    update(root.left, index, val)
  else:
    update(root.right, index, val)
  # 重新计算和
  root.val = root.left?.val + root.right?.val</pre>



<p>T(n) = T(n/2) + 1 =&gt; O(logn)</p>



<p>Query: query的range可以是任意的，就有以下三种情况：</p>



<p>case 1: 这个range正好和我负责的range完全相同。比如sumQuery(CTO, 0, 99)，这个时候CTO直接返回已经求解过的所有下属的和即可。</p>



<p>case 2: 这个range只由我其中一个下属负责。比如sumQuery(CEO, 0, 10)，CEO知道0~10全部由CFO负责，那么他就直接返回sumQuery(CTO, 0, 10)。</p>



<p>case 3: 这个range覆盖了我的两个下属，那么我就需要调用2次。比如sumQuery(CEO, 80, 120)，CEO知道0~99由CTO管，100~199由CFO管，所以他只需要返回：</p>



<p>sumQuery(CTO, 80, 99) + sumQuery(CFO, 100, 120)<br></p>



<p>由此可见sumQuery的时间复杂度是不确定的，运气好时O(1)，运气不好时是O(logn+k)，k是需要访问的节点的数量。 </p>



<p>我做了一个实验，给定N，尝试所有的(i,j)组合，看sumQuery的最坏情况和平均情况，结果如下图：</p>



<figure class="wp-block-image"><img width="600" height="371" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2019/02/query_nodes.png" alt="" class="wp-image-4795" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2019/02/query_nodes.png 600w, https://zxi.mytechroad.com/blog/wp-content/uploads/2019/02/query_nodes-300x186.png 300w" sizes="(max-width: 600px) 100vw, 600px" /></figure>



<p>Query需要访问到的节点数量的worst和average case。Worst case 大约访问 4*logn &#8211; 3 个节点，这个数字远远小于n。和n成对数关系。<br></p>



<p>虽然不像Binary Indexed Tree query是严格的O(logn)，但Segment tree query的worst case增长的非常慢，可以说是对数级别的。当N是2^20的时候，worst case也“只需要”访问77个节点。</p>



<p>最后我们再来讲一下这棵树是怎么创建的，其实方法有很多种，一分为二是比较常规的一种做法。</p>



<p>CEO管200人，那么就找2个人(CTO，CFO各管100人。CTO管100人，再找2个VP各管50人，以此类推，直到manager管2个人，2个人都是底层员工(leaf)，没有人管（双关）。</p>



<pre class="crayon-plain-tag">def buildTree(start, end):
  # 超过范围返回空节点
  if start &amp;gt; end: return None
  boss.start = start
  boss.end = end
  # 如果是叶子节点，记录元素的值
  if start == end: boss.val = nums[start]
  boss.mid = (start + end) // 2
  # 递归构建子树
  boss.left = buildTree(start, mid)
  boss.right = buildTree(mid + 1, end)
  # 求和
  boss.val += boss.left?.val + boss.right?.val
  return boss</pre>



<p>CEO = buildTree(0, 199)</p>



<p>CEO.left # CTO 负责0~99<br>CEO.right # CFO&nbsp;负责100~199</p>



<hr class="wp-block-separator is-style-wide"/>



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



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



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



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



<p>Query: # of nodes visited: Average and worst are both ~O(logn)</p>



<h2>Applications</h2>



<p><a href="https://zxi.mytechroad.com/blog/data-structure/307-range-sum-query-mutable/">LeetCode&nbsp;307&nbsp;Range&nbsp;Sum&nbsp;Query&nbsp;&#8211;&nbsp;Mutable</a></p>



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

<pre class="crayon-plain-tag">// Author: Huahua, running time: 24 ms
class SegmentTreeNode {
public:
  SegmentTreeNode(int start, int end, int sum,
                  SegmentTreeNode* left = nullptr,
                  SegmentTreeNode* right = nullptr): 
    start(start),
    end(end),
    sum(sum),
    left(left),
    right(right){}      
  SegmentTreeNode(const SegmentTreeNode&amp;) = delete;
  SegmentTreeNode&amp; operator=(const SegmentTreeNode&amp;) = delete;
  ~SegmentTreeNode() {
    delete left;
    delete right;
    left = right = nullptr;
  }
  
  int start;
  int end;
  int sum;
  SegmentTreeNode* left;
  SegmentTreeNode* right;
};

class NumArray {
public:
  NumArray(vector&lt;int&gt; nums) {
    nums_.swap(nums);
    if (!nums_.empty())
      root_.reset(buildTree(0, nums_.size() - 1));
  }

  void update(int i, int val) {
    updateTree(root_.get(), i, val);
  }

  int sumRange(int i, int j) {
    return sumRange(root_.get(), i, j);
  }
private:
  vector&lt;int&gt; nums_;
  std::unique_ptr&lt;SegmentTreeNode&gt; root_;
  
  SegmentTreeNode* buildTree(int start, int end) {  
    if (start == end) {      
      return new SegmentTreeNode(start, end, nums_[start]);
    }
    int mid = start + (end - start) / 2;
    auto left = buildTree(start, mid);
    auto right = buildTree(mid + 1, end);
    auto node = new SegmentTreeNode(start, end, left-&gt;sum + right-&gt;sum, left, right);    
    return node;
  }
  
  void updateTree(SegmentTreeNode* root, int i, int val) {
    if (root-&gt;start == i &amp;&amp; root-&gt;end == i) {
      root-&gt;sum = val;
      return;
    }
    int mid = root-&gt;start + (root-&gt;end - root-&gt;start) / 2;
    if (i &lt;= mid) {
      updateTree(root-&gt;left, i, val);
    } else {      
      updateTree(root-&gt;right, i, val);
    }
    root-&gt;sum = root-&gt;left-&gt;sum + root-&gt;right-&gt;sum;
  }
  
  int sumRange(SegmentTreeNode* root, int i, int j) {    
    if (i == root-&gt;start &amp;&amp; j == root-&gt;end) {
      return root-&gt;sum;
    }
    int mid = root-&gt;start + (root-&gt;end - root-&gt;start) / 2;
    if (j &lt;= mid) {
      return sumRange(root-&gt;left, i, j);
    } else if (i &gt; mid) {
      return sumRange(root-&gt;right, i, j);
    } else {
      return sumRange(root-&gt;left, i, mid) + sumRange(root-&gt;right, mid + 1, j);
    }
  }
};</pre>

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

<pre class="crayon-plain-tag"># Author: Huahua, running time: 176 ms
class SegmentTreeNode:
  def __init__(self, start, end, val, left=None, right=None):
    self.start = start
    self.end = end
    self.mid = start + (end - start) // 2
    self.val = val
    self.left = left
    self.right = right

class NumArray:
  def __init__(self, nums):
    self.nums = nums
    if self.nums:
      self.root = self._buildTree(0, len(nums) - 1)

  def update(self, i, val):      
    self._updateTree(self.root, i, val)

  def sumRange(self, i, j):
    return self._sumRange(self.root, i, j)
    
  
  def _buildTree(self, start, end):
    if start == end: return SegmentTreeNode(start, end, self.nums[start])
    mid = start + (end - start) // 2
    left = self._buildTree(start, mid)
    right = self._buildTree(mid + 1, end)
    return SegmentTreeNode(start, end, left.val + right.val, left, right)
  
  def _updateTree(self, root, i, val):
    if root.start == i and root.end == i:
      root.val = val
      return    
    if i &lt;= root.mid:
      self._updateTree(root.left, i, val)
    else:
      self._updateTree(root.right, i, val)
    root.val = root.left.val + root.right.val
  
  def _sumRange(self, root, i, j):
    if root.start == i and root.end == j:
      return root.val
    if j &lt;= root.mid:
      return self._sumRange(root.left, i, j)
    elif i &gt; root.mid:
      return self._sumRange(root.right, i, j)
    else:
      return self._sumRange(root.left, i, root.mid) + self._sumRange(root.right, root.mid + 1, j)</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/segment-tree-sp14/">花花酱 Segment Tree 线段树 SP14</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/sp/segment-tree-sp14/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode Binary Trees 二叉树 SP12</title>
		<link>https://zxi.mytechroad.com/blog/sp/leetcode-binary-trees-sp12/</link>
					<comments>https://zxi.mytechroad.com/blog/sp/leetcode-binary-trees-sp12/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 16 Dec 2018 18:24:48 +0000</pubDate>
				<category><![CDATA[SP]]></category>
		<category><![CDATA[BST]]></category>
		<category><![CDATA[sp]]></category>
		<category><![CDATA[tree]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=4449</guid>

					<description><![CDATA[<p>Binary tree is one of the most frequently asked question type during interview. 二叉树是面试中经常会问到的问题。 The candidate needs to understand the recursively defined TreeNode and solve&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/leetcode-binary-trees-sp12/">花花酱 LeetCode Binary Trees 二叉树 SP12</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/PbGl8_-bZxI?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></p>
<p>Binary tree is one of the most frequently asked question type during interview.</p>
<p>二叉树是面试中经常会问到的问题。</p>
<p>The candidate needs to understand the recursively defined TreeNode and solve the problem through recursion.</p>
<p>面试者需要理解递归定义的TreeNode数据类型，并且通过使用递归的方式来解决问题。</p>
<p>&nbsp;</p>
<p><img class="alignnone size-large wp-image-4450" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-1.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-1-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /><br />
<img class="alignnone size-large wp-image-4451" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-2.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-2-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /><br />
<img class="alignnone size-large wp-image-4452" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-3.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-3.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-3-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-3-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /><br />
<img class="alignnone size-large wp-image-4453" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-4.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-4.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-4-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-4-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /><br />
<img class="alignnone size-large wp-image-4454" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-5.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-5.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-5-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-5-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /><br />
<img class="alignnone size-large wp-image-4455" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-6.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-6.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-6-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-6-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /><br />
<img class="alignnone size-large wp-image-4456" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-7.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-7.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-7-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-7-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /><br />
<img class="alignnone size-large wp-image-4457" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-8.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-8.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-8-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-8-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /><br />
<img class="alignnone size-large wp-image-4458" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-9.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-9.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-9-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-9-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /><br />
<img class="alignnone size-large wp-image-4459" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-10.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-10.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-10-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/12/sp12-10-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/leetcode-binary-trees-sp12/">花花酱 LeetCode Binary Trees 二叉树 SP12</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/sp/leetcode-binary-trees-sp12/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Knapsack Problem 背包问题</title>
		<link>https://zxi.mytechroad.com/blog/sp/knapsack-problem/</link>
					<comments>https://zxi.mytechroad.com/blog/sp/knapsack-problem/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sat, 10 Nov 2018 17:37:14 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[SP]]></category>
		<category><![CDATA[combination]]></category>
		<category><![CDATA[DFS]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[knapsack]]></category>
		<category><![CDATA[optimization]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=4270</guid>

					<description><![CDATA[<p>Videos 上期节目中我们对动态规划做了一个总结，这期节目我们来聊聊背包问题。 背包问题是一个NP-complete的组合优化问题，Search的方法需要O(2^N)时间才能获得最优解。而使用动态规划，我们可以在伪多项式（pseudo-polynomial time）时间内获得最优解。 0-1 Knapsack Problem 0-1背包问题 Problem Given N items, w[i] is the weight of the i-th item and v[i] is value of&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/knapsack-problem/">Knapsack Problem 背包问题</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1>Videos</h1>
<p><iframe width="500" height="375" src="https://www.youtube.com/embed/CO0r6kcwHUU?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></p>
<p><iframe width="500" height="375" src="https://www.youtube.com/embed/rM_G4dboKhc?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></p>
<h1></h1>
<p>上期节目中我们对动态规划做了一个总结，这期节目我们来聊聊背包问题。</p>
<p>背包问题是一个NP-complete的组合优化问题，Search的方法需要O(2^N)时间才能获得最优解。而使用动态规划，我们可以在<strong>伪多项式（pseudo-polynomial time）</strong>时间内获得最优解。</p>
<h1><strong>0-1 Knapsack Problem 0-1背包问题</strong></h1>
<h2>Problem</h2>
<p><span style="font-weight: 400;">Given N items, w[i] is the weight of the i-th item and v[i] is value of the i-th item. Given a knapsack with capacity W. Maximize the total value. Each item can be use </span><span style="color: #ff0000;"><b>0 or 1 time</b></span><span style="font-weight: 400;">.</span></p>
<p>0-1背包问题的通常定义是：一共有N件物品，第i件物品的重量为w[i]，价值为v[i]。在总重量不超过背包承载上限W的情况下，能够获得的最大价值是多少？每件物品可以使用<strong>0次或者1次</strong>。</p>
<p>例子：</p>
<p>重量 w = [1, 1, 2, 2]</p>
<p>价值 v = [1, 3, 4, 5]</p>
<p>背包承重 W = 4</p>
<p>最大价值为9，可以选第1,2,4件物品，也可以选第3，4件物品；总重量为4，总价值为9。</p>
<p>动态规划的状态转移方程为：</p><pre class="crayon-plain-tag">dp[i][j] = max(dp[i-1][j], dp[i][j-w[i]] + v[i])</pre><p><img class="alignnone wp-image-4295 size-full" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-1.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-1-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><img class="alignnone size-large wp-image-4276" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-2.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-2-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><img class="alignnone wp-image-4290 size-full" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-3.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-3.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-3-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-3-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><img class="alignnone wp-image-4293 size-full" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-4.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-4.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-4-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-4-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><img class="alignnone size-full wp-image-4303" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-1.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-1-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<h2><strong>Solutions</strong></h2>
<p><div class="responsive-tabs">
<h2 class="tabtitle">Search</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">def knapsack01DFS(w, v, W):
  def dfs(s, cur_w, cur_v, ans):
    ans[0] = max(ans[0], cur_v)
    if s == N: return
    for i in range(s, N):
      if cur_w + w[i] &lt;= W:
        dfs(i + 1, cur_w + w[i], cur_v + v[i], ans)
  ans = [0]
  dfs(0, 0, 0, ans)
  return ans[0]</pre><p></div><h2 class="tabtitle">DP2</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">def knapsack01(w, v, W):
  dp = [[0] * (W + 1) for _ in range(N+1)]
  for i in range(1, N + 1):
    dp[i] = dp[i-1].clone()
    for j in range(w[i], W + 1):
      dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i - 1]] + v[i - 1])
  return max(dp[N])</pre><p></div><h2 class="tabtitle">DP1/tmp</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">def knapsack01R(w, v, W):
  dp = [0] * (W + 1)
  for i in range(0, N):
    tmp = list(dp)
    for j in range(w[i], W + 1):
      tmp[j] = max(tmp[j], dp[j - w[i]] + v[i])
    dp = tmp
  return max(dp)</pre><p></div><h2 class="tabtitle">DP1/push</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">def knapsack01R2(w, v, W):
  dp = [0] * (W + 1)
  for i in range(0, N):
    for j in range(W, w[i] - 1, -1):
      dp[j] = max(dp[j], dp[j - w[i]] + v[i])
  return max(dp)</pre><p></div><h2 class="tabtitle">DP1/pull</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">def knapsack01R1(w, v, W):
  dp = [0] * (W + 1)
  for i in range(0, N):
    for j in range(W - w[i], -1, -1):
      dp[j + w[i]] = max(dp[j + w[i]], dp[j] + v[i])
  return max(dp)</pre><p></div></div></p>
<p>&nbsp;</p>
<h1><strong>Unbounded Knapsack Problem 完全背包</strong></h1>
<p><strong>完全背包</strong>、<strong>多重背包</strong>是常见的变形。和01背包的区别在于，完全背包每件物品可以使用<strong>无限多次</strong>，而多重背包每件物品最多可以使用<strong>n[i]次</strong>。两个问题都可以转换成01背包问题进行求解。</p>
<p>但是Naive的转换会大大增加时间复杂度：</p>
<p>完全背包：“复制”第i件物品到一共有 W/w[i] 件</p>
<p>多重背包：“复制”第i件物品到一共有 n[i] 件</p>
<p>然后直接调用01背包进行求解。</p>
<p>时间复杂度：</p>
<p>完全背包 O(Σ(W/w[i])*W)</p>
<p>多重背包 O(Σn[i]*W)</p>
<p>不难看出时间复杂度 = O(物品数量*背包承重)</p>
<p>背包承重是给定的，要降低运行时候，只有减少物品数量。但怎样才能减少总的物品数量呢？</p>
<p>这就涉及到二进制思想：任何一个正整数都可以用 (1, 2, 4, &#8230;, 2^K)的组合来表示。例如14 = 2 + 4 + 8。<br />
原本需要放入14件相同的物品，现在只需要放入3件（重量和价值是原物品的2倍，4倍，8倍）。大幅降低了总的物品数量从而降低运行时间。</p>
<p>完全背包：对于第i件物品，我们只需要创建k = log(W/w[i])件虚拟物品即可。</p>
<p>每件虚拟物品的重量和价值为：1*(w[i], v[i]), 2*(w[i], v[i]), &#8230;, 2^k*(w[i], v[i])。</p>
<p>多重背包：对于第i件物品，我们只需要创建k + 1件虚拟物品即可，其中k = log(n[i])。</p>
<p>每件虚拟物品的重量和价值为：1*(w[i], v[i]), 2*(w[i], v[i]), &#8230;, 2^(k-1)*(w[i], v[i]), 以及 (<strong>n[i] &#8211; 2^k &#8211; 1</strong>) * (w[i], v[i])。</p>
<p>例如：n[i] = 14, k = 3, 虚拟物品的倍数为 1, 2, 4 和 7，这4个数组合可以组成1 ~ 14中的任何一个数，并且不会&gt;14，即不超过n[i]。</p>
<p>二进制转换后直接调用01背包即可</p>
<p>时间复杂度：</p>
<p>完全背包 O(Σlog(W/w[i])*W)</p>
<p>多重背包 O(Σlog(n[i])*W)</p>
<p>空间复杂度 O(W)</p>
<p>其实完全背包和多重背包都可以在 O(NW)时间内完成，前者在视频中有讲到，后者属于<strong>超纲内容</strong>，以后有机会再和大家深入分享。</p>
<p><img class="alignnone size-full wp-image-4300" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-2.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-2-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><img class="alignnone size-full wp-image-4301" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-3.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-3.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-3-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-3-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<h1><strong>Bounded Knapsack Problem 多重背包</strong></h1>
<p><img class="alignnone wp-image-4304 size-full" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-4.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-4.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-4-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-4-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p>&nbsp;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/knapsack-problem/">Knapsack Problem 背包问题</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/sp/knapsack-problem/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode DP Summary 动态规划总结</title>
		<link>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-dp-summary/</link>
					<comments>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-dp-summary/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Fri, 02 Nov 2018 06:18:52 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[SP]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[summary]]></category>
		<category><![CDATA[template]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=4233</guid>

					<description><![CDATA[<p>Summary: Input size / sub-problem size / sub-problem complexity / time complexity / space complexity [crayon-663c0e25a76b4094637404/] [crayon-663c0e25a76b6053837430/] &#160; Summary and slides</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-dp-summary/">花花酱 LeetCode DP Summary 动态规划总结</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/3mY5W0yojtA?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></p>
<p><iframe width="500" height="375" src="https://www.youtube.com/embed/eLlZEYzZVyQ?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></p>
<p>Summary: Input size / sub-problem size / sub-problem complexity / time complexity / space complexity</p>
<p><div class="responsive-tabs">
<h2 class="tabtitle">Category 1.1</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">Input: O(n)
Sub-problems: O(n)
Each sub-problem depends on O(1) smaller problems
Time complexity: O(n)
Space complexity: O(n) -&gt; O(1)
dp[i] := solution of A[1-&gt;i] // prefix</pre><p></div><h2 class="tabtitle">Template</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">dp = new int[n + 1]
for i = 1 to n:
  dp[i] = f(A[i], dp[i-1], dp[i-2], ...)
return dp[n]</pre><p></div></div></p>
<p>&nbsp;</p>
<p>Summary and slides</p>
<p><img class="alignnone size-full wp-image-4234" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-1.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-1-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><img class="alignnone size-full wp-image-4235" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-2.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-2-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><img class="alignnone size-large wp-image-4236" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-3.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-3.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-3-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-3-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><img class="alignnone size-large wp-image-4237" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-4.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-4.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-4-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-4-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><img class="alignnone wp-image-4244 size-full" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-5.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-5.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-5-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-5-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><img class="alignnone size-large wp-image-4239" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-6.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-6.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-6-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-6-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><img class="alignnone size-large wp-image-4240" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-7.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-7.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-7-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp9-7-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-dp-summary/">花花酱 LeetCode DP Summary 动态规划总结</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-dp-summary/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 Amortized Analysis 均摊分析 SP7</title>
		<link>https://zxi.mytechroad.com/blog/sp/amortized-analysis/</link>
					<comments>https://zxi.mytechroad.com/blog/sp/amortized-analysis/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Tue, 18 Sep 2018 02:16:30 +0000</pubDate>
				<category><![CDATA[SP]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=4011</guid>

					<description><![CDATA[<p>Amortized Analysis Amortized analysis can help us understand the actual cost of n operations on a data structure. Since some operations can be really fast&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/amortized-analysis/">花花酱 Amortized Analysis 均摊分析 SP7</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 title="花花酱 LeetCode Amortized Analysis 均摊分析 - 刷题找工作 SP7" width="500" height="375" src="https://www.youtube.com/embed/OwMhWDOxX94?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></p>
<h1><strong>Amortized Analysis</strong></h1>
<p>Amortized analysis can help us understand the actual cost of n operations on a data structure. Since some operations can be really fast e.g. O(1), but some operations can be really slow e.g. O(n). We could say the time complexity of that operation is O(n). However, it does not reflect the actual performance. And turns out, we can prove that certain operations have an amortized cost of O(1) while they can take O(n) in the worst case.</p>
<p>均摊分析可以帮助我们了解对一个数据结构进行n次操作的真实代价。对于相同的操作，有时候可以非常快，例如在O(1)时间内完成，而有时候则需要O(n)。我们当然可以说这个操作最坏情况下的时间复杂度是O(n)，但是这并不能真实反映它的实际复杂度。通过均摊分析，我们可以证明，尽管有些操作在最坏情况下是O(n)的时间复杂度，但是均摊下来只需要O(1)。</p>
<p><img class="alignnone size-large wp-image-4016" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/09/sp7-1.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/09/sp7-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/09/sp7-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/09/sp7-1-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p>&nbsp;</p>
<h1>Dynamic Array</h1>
<p>dynamic array doubles its size when it&#8217;s full which could take O(i) time where i is the number of elements in the array. Otherwise just store the element which only cost O(1). We can use aggregate method to compute the amortized cost of dynamic array.</p>
<p>动态数组在容量满时将容量翻翻，这一步需要O(i)时间，i是当前数组中的元素个数。如果没有满，只需要将元素存储下来即可，只需要花费O(1)时间。我们可以使用聚合法来计算均摊成本。</p>
<p>((1 + 1) + (1 + 2) + (1) + (1 + 4) + (1) + (1) + (1) + (1+8) + &#8230; + (1+n)) / n, assuming n is 2^k.</p>
<p>= (1 * n + (1 + 2 + 4 + 8 + &#8230; + n)) / n = (n + 2n &#8211; 1) / n = 3. O(1)</p>
<p><div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">#include &lt;iostream&gt;
#include &lt;algorithm&gt;
using namespace std;

class DynamicArray {
public:
  DynamicArray() {
    data_ = new int[1];
    capcity_ = 1;
  }
  void add(int x) {
    data_[size_++] = x;
    ++total_cost_;
    if (size_ == capcity_) {
      capcity_ *= 2;
      total_cost_ += size_;
      int* new_data = new int[capcity_];
      copy(data_, data_ + size_, new_data);
      swap(new_data, data_);
      delete [] new_data;
    }
  }
  int totalCost() const { return total_cost_; }
private:
  int total_cost_ = 0;
  int size_ = 0;
  int capcity_;
  int* data_;
};

int main() {
  DynamicArray arr;
  for (int i = 1; i &lt;= 16; ++i) {
    arr.add(i);
    cout &lt;&lt; i &lt;&lt; " average cost: " &lt;&lt; arr.totalCost() / static_cast&lt;float&gt;(i) &lt;&lt; endl;
  }
}</pre><p></div><h2 class="tabtitle">Output</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">1 average cost: 2
2 average cost: 2.5
3 average cost: 2
4 average cost: 2.75
5 average cost: 2.4
6 average cost: 2.16667
7 average cost: 2
8 average cost: 2.875
9 average cost: 2.66667
10 average cost: 2.5
11 average cost: 2.36364
12 average cost: 2.25
13 average cost: 2.15385
14 average cost: 2.07143
15 average cost: 2
16 average cost: 2.9375
[Finished in 0.4s]</pre><p></div></div></p>
<p>&nbsp;</p>
<p><img class="alignnone wp-image-4022 size-full" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/09/sp7-2.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/09/sp7-2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/09/sp7-2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/09/sp7-2-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<h1><strong>Monotonic Stack</strong></h1>
<p>例子2: 单调栈</p>
<p>往单调栈push一个元素的时候，会删除上所有小于等于它的元素。这步操作在最优情况下是O(1)时间，如果它比栈顶元素要小。在最坏情况下是O(i)时间，栈上有i个元素，它比这i个元素都要大，所以一共要pop i次。</p>
<p>聚合法：</p>
<p>由于每个元素都会被push到栈上去1次，最多会被pop1次，所以总的操作数 &lt;= 2n。 2n / n = 2 O(1)。</p>
<p>会计法：</p>
<p>每次push之前先存k块钱，k=2, 一块钱用于push自己，一块钱留着用于pop自己。</p>
<p>push的时候扣除1块钱，pop的时候再扣除1块钱。但不管怎样，我的账户上的钱永远&gt;=0。这样我们可以说push的均摊成本是k=2。同样是O(1)，尽管它的worst case是O(n)。</p>
<p><div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;stack&gt;
using namespace std;

class MonotonicStack {
public:
  void push(int x) {
    while (!data_.empty() &amp;&amp; x &gt; data_.top()) {
      this-&gt;pop();
    }
    ++total_cost_;
    data_.push(x);
  }

  int pop() {
    ++total_cost_;
    int t = data_.top();
    data_.pop();
    return t;
  }
  int totalCost() const { return total_cost_; }
private:
  int total_cost_ = 0;
  stack&lt;int&gt; data_;
};

int main() {
  srand(1);
  MonotonicStack s;
  for (int i = 1; i &lt;= 32; ++i) {
    s.push(rand());
    cout &lt;&lt; i &lt;&lt; " average cost: " &lt;&lt; s.totalCost() / static_cast&lt;float&gt;(i) &lt;&lt; endl;
  }  
}</pre><p></div><h2 class="tabtitle">Output</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">1 average cost: 1
2 average cost: 1.5
3 average cost: 1.66667
4 average cost: 1.5
5 average cost: 1.6
6 average cost: 1.5
7 average cost: 1.42857
8 average cost: 1.75
9 average cost: 1.77778
10 average cost: 1.9
11 average cost: 1.81818
12 average cost: 1.83333
13 average cost: 1.84615
14 average cost: 1.78571
15 average cost: 1.8
16 average cost: 1.8125
17 average cost: 1.82353
18 average cost: 1.77778
19 average cost: 1.78947
20 average cost: 1.75
21 average cost: 1.80952
22 average cost: 1.86364
23 average cost: 1.82609
24 average cost: 1.91667
25 average cost: 1.88
26 average cost: 1.84615
27 average cost: 1.81481
28 average cost: 1.85714
29 average cost: 1.82759
30 average cost: 1.86667
31 average cost: 1.90323
32 average cost: 1.875
[Finished in 0.5s]</pre><p></div></div></p>
<p>&nbsp;</p>
<p><img class="alignnone size-full wp-image-4014" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/09/sp7-3.png" alt="" width="960" height="540"></p>
<h1><strong>Related Problem</strong></h1>
<ul>
<li><a href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-901-online-stock-span/">花花酱 LeetCode 901. Online Stock Span</a></li>
</ul>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/amortized-analysis/">花花酱 Amortized Analysis 均摊分析 SP7</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/sp/amortized-analysis/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 SP5 Binary Search</title>
		<link>https://zxi.mytechroad.com/blog/sp/sp5-binary-search/</link>
					<comments>https://zxi.mytechroad.com/blog/sp/sp5-binary-search/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Mon, 13 Aug 2018 06:41:04 +0000</pubDate>
				<category><![CDATA[Binary Search]]></category>
		<category><![CDATA[SP]]></category>
		<category><![CDATA[binary search]]></category>
		<category><![CDATA[boundary]]></category>
		<category><![CDATA[sp]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=3504</guid>

					<description><![CDATA[<p>Template: Time complexity: O(log(r-l)) * O(f(m) + g(m)) Space complexity: O(1) [crayon-663c0e25a7a66632338842/] &#160; Slides: Lower Bound / Upper Bound [crayon-663c0e25a7a69437834852/] Mentioned Problems 花花酱 LeetCode. 69&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/sp5-binary-search/">花花酱 SP5 Binary Search</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/v57lNF2mb_s?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<p>Template:</p>
<p>Time complexity: O(log(r-l)) * O(f(m) + g(m))</p>
<p>Space complexity: O(1)</p><pre class="crayon-plain-tag">"""
Returns the smallest number m such that g(m) is true.
"""
def binary_search(l, r):
  while l &lt; r:
    m = l + (r - l) // 2
    if f(m): return m    # if m is the answer
    if g(m):
      r = m              # new range [l, m)
    else
      l = m + 1          # new range [m+1, r)
  return l               # or not found</pre><p>&nbsp;</p>
<p>Slides:</p>
<p><img class="alignnone size-full wp-image-3510" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/08/sp5-1.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/08/sp5-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/08/sp5-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/08/sp5-1-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><img class="alignnone size-full wp-image-3509" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/08/sp5-2.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/08/sp5-2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/08/sp5-2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/08/sp5-2-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><img class="alignnone size-full wp-image-3508" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/08/sp5-3.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/08/sp5-3.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/08/sp5-3-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/08/sp5-3-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><img class="alignnone size-full wp-image-3507" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/08/sp5-4.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/08/sp5-4.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/08/sp5-4-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/08/sp5-4-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><img class="alignnone size-full wp-image-3506" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/08/sp5-5.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/08/sp5-5.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/08/sp5-5-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/08/sp5-5-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /><img class="alignnone size-full wp-image-3505" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/08/sp5-6.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/08/sp5-6.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/08/sp5-6-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/08/sp5-6-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p>Lower Bound / Upper Bound</p><pre class="crayon-plain-tag">#include &lt;iostream&gt;
#include &lt;vector&gt;
using namespace std;

int upper_bound(const vector&lt;int&gt;&amp; A, int val, int l, int r) {
  while (l &lt; r) {
    int m = l + (r - l) / 2;
    if (A[m] &gt; val)
      r = m;
    else      
      l = m + 1;
  }
  return l;
}

int lower_bound(const vector&lt;int&gt;&amp; A, int val, int l, int r) {
  while (l &lt; r) {
    int m = l + (r - l) / 2;
    if (A[m] &gt;= val)
      r = m;
    else
      l = m + 1;
  }
  return l;
}

int main() {
  vector&lt;int&gt; A{1, 2, 2, 2, 4, 4, 5};
  cout &lt;&lt; lower_bound(A, 0, 0, A.size()) &lt;&lt; endl; // 0
  cout &lt;&lt; lower_bound(A, 2, 0, A.size()) &lt;&lt; endl; // 1
  cout &lt;&lt; lower_bound(A, 3, 0, A.size()) &lt;&lt; endl; // 4
  cout &lt;&lt; upper_bound(A, 2, 0, A.size()) &lt;&lt; endl; // 4
  cout &lt;&lt; upper_bound(A, 4, 0, A.size()) &lt;&lt; endl; // 6
  cout &lt;&lt; upper_bound(A, 5, 0, A.size()) &lt;&lt; endl; // 7
}</pre><p></p>
<h1><strong>Mentioned Problems</strong></h1>
<ul>
<li><a href="https://zxi.mytechroad.com/blog/math/leetcode-69-sqrtx/">花花酱 LeetCode. 69 Sqrt(x)</a></li>
<li><a href="https://zxi.mytechroad.com/blog/algorithms/array/leetcode-704-binary-search/">花花酱 LeetCode 704. Binary Search</a></li>
<li><a href="https://zxi.mytechroad.com/blog/algorithms/binary-search/leetcode-875-koko-eating-bananas/">花花酱 LeetCode 875. Koko Eating Bananas</a></li>
<li><a href="https://zxi.mytechroad.com/blog/algorithms/binary-search/leetcode-378-kth-smallest-element-in-a-sorted-matrix/">花花酱 LeetCode 378. Kth Smallest Element in a Sorted Matrix</a></li>
</ul>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/sp5-binary-search/">花花酱 SP5 Binary Search</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/sp/sp5-binary-search/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱  Time/Space Complexity of Recursion Functions SP4</title>
		<link>https://zxi.mytechroad.com/blog/sp/time-space-complexity-of-recursion-functions-sp4/</link>
					<comments>https://zxi.mytechroad.com/blog/sp/time-space-complexity-of-recursion-functions-sp4/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Thu, 08 Feb 2018 04:48:37 +0000</pubDate>
				<category><![CDATA[SP]]></category>
		<category><![CDATA[recusion]]></category>
		<category><![CDATA[space complexity]]></category>
		<category><![CDATA[time complexity]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=1777</guid>

					<description><![CDATA[<p>&#160; How to analyze the time and space complexity of a recursion function? 如何分析一个递归函数的时间/空间复杂度？ We can answer that using master theorem or induction in most&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/time-space-complexity-of-recursion-functions-sp4/">花花酱  Time/Space Complexity of Recursion Functions SP4</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/OQi4n8EKRD8?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<p>&nbsp;</p>
<p>How to analyze the time and space complexity of a recursion function?</p>
<p>如何分析一个递归函数的时间/空间复杂度？</p>
<p>We can answer that using <a href="https://en.wikipedia.org/wiki/Master_theorem_(analysis_of_algorithms)">master theorem</a> or induction in most of the cases.</p>
<p>在大部分时候我们可以使用主方法和数学归纳法来进行解答。</p>
<p>First of all, we need to write down the recursion relation of a function.</p>
<p>首先我们要写出一个函数的递归表达式。</p><pre class="crayon-plain-tag">def func(n):
  if n &lt; 0: return 1
  return func(n/2) + func(n/2)</pre><p>Let&#8217;s use T(n) to denote the running time of func with input size of n.</p>
<p>让我们用T(n)来表示func函数在输入规模为n的运行时间。</p>
<p>Then we have：</p>
<p>那么我们有：</p>
<p>T(n) = 2*T(n/2) + O(1)</p>
<p>a = 2, b = 2, c_crit = logb(a) = 1, f(n) = n^c, c = 0.</p>
<p>c &lt; c_crit, apply master theorem case 1:</p>
<p>根据主方法第一条我们得到</p>
<p>T(n) =  Θ(n^c_crit) = Θ(n)</p>
<p>&nbsp;</p>
<p>Let&#8217;s look at another example:</p><pre class="crayon-plain-tag">def func(n):
  if n &lt; 0: return 1
  s = 0
  for i in range(n):
    s += i
  return s + func(n/2) + func(n/2)</pre><p>T(n) = 2*T(n/2) + O(n)</p>
<p>a = 2, b = 2, c_crit = logb(a) = 1, f(n) = n^c, c = 1,</p>
<p>c = c_crit, apply master theorem case 2:</p>
<p>根据主方法第二条我们得到</p>
<p>T(n) =Θ(n^c_crit * (logn)^1)) = Θ(nlogn)</p>
<p><strong>Cheatsheet</strong></p>
<table>
<tbody>
<tr>
<th>Equation</th>
<th>Time</th>
<th>Space</th>
<th>Examples</th>
</tr>
<tr>
<td>T(n) = 2*T(n/2) + O(n)</td>
<td>O(nlogn)</td>
<td>O(logn)</td>
<td>quick_sort</td>
</tr>
<tr>
<td>T(n) = 2*T(n/2) + O(n)</td>
<td>O(nlogn)</td>
<td>O(n + logn)</td>
<td>merge_sort</td>
</tr>
<tr>
<td>T(n) = T(n/2) + O(1)</td>
<td>O(logn)</td>
<td>O(logn)</td>
<td>Binary search</td>
</tr>
<tr>
<td>T(n) = 2*T(n/2) + O(1)</td>
<td>O(n)</td>
<td>O(logn)</td>
<td>Binary tree traversal</td>
</tr>
<tr>
<td>T(n) = T(n-1) + O(1)</td>
<td>O(n)</td>
<td>O(n)</td>
<td>Binary tree traversal</td>
</tr>
<tr>
<td>T(n) = T(n-1) + O(n)</td>
<td>O(n^2)</td>
<td>O(n)</td>
<td>quick_sort(worst case)</td>
</tr>
<tr>
<td>T(n) = n * T(n-1)</td>
<td>O(n!)</td>
<td>O(n)</td>
<td>permutation</td>
</tr>
<tr>
<td>T(n) = T(n-1)+T(n-2)+&#8230;+T(1)</td>
<td>O(2^n)</td>
<td>O(n)</td>
<td>combination</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><strong>For recursion with memorization:</strong></p>
<p>Time complexity: |# of subproblems| * |exclusive running time of a subproblem|</p>
<p>Space complexity:|# of subproblems|  + |max recursion depth| * |space complexity of a subproblem|</p>
<p><strong>Example 1:</strong></p><pre class="crayon-plain-tag">def fib(n):
  if n &lt; 1: return 1
  if m[n]: return m[n]
  m[n] = fib(n - 1) + fib(n - 2)
  return m[n]</pre><p>To solve fib(n), there are n subproblems fib(0), fib(1), &#8230;, fib(n)</p>
<p>each sub problem takes O(1) to solve</p>
<p>Time complexity: O(n)</p>
<p>Space complexity: O(n) + O(n) * O(1) = O(n)</p>
<p><strong>Example 2:</strong></p>
<p><a href="http://zxi.mytechroad.com/blog/dynamic-programming/leetcode-741-cherry-pickup/">LC 741 Cherry Pickup</a></p><pre class="crayon-plain-tag">dp(x1, y1, x2):
 if min(x1, y1, x2) &lt; 0: return 0
 if m[x1][y1][x2]: return m[x1][y1][x2]
 ans = max(dp(x1 - 1, y1, x2 - 1), 
           dp(x1, y1 - 1, x2),
           dp(x1, y1 - 1, x2 - 1), 
           dp(x1 - 1, y1, x2))
 m[x1][y1][x2] = ans
 return m[x1][y1][x2]</pre><p>To solve dp(n, n, n), there are n^3 subproblems</p>
<p>each subproblem takes O(1) to solve</p>
<p>Max recursion depth O(n)</p>
<p>Time complexity: O(n^3) * O(1) = O(n^3)</p>
<p>Space complexity: O(n^3) + O(n) * O(1) = O(n^3)</p>
<p><strong>Example 3:</strong></p>
<p><a href="http://zxi.mytechroad.com/blog/dynamic-programming/leetcode-312-burst-balloons/">LC 312: Burst Balloon</a></p><pre class="crayon-plain-tag">dp(i, j):
 if m[i][j]: return m[i][j]
 for k in range(i, j + 1):
   ans = max(ans, dp(i, k - 1) + C + dp(k + 1, j))
 m[i][j] = ans
 return m[i][j]</pre><p>To solve dp(0, n), there are n^2 subproblems dp(0, 0), dp(0, 1), &#8230;, dp(n-1, n)</p>
<p>each subproblem takes O(n) to solve</p>
<p>Max recursion depth O(n)</p>
<p>Time complexity: O(n^2) * O(n) = O(n^3)</p>
<p>Space complexity: O(n^2) + O(n) * O(1) = O(n^2)</p>
<p><strong>Slides:</strong></p>
<p><img class="alignnone size-full wp-image-1783" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2018/02/sp4-1.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/02/sp4-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/02/sp4-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/02/sp4-1-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><img class="alignnone size-full wp-image-1781" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2018/02/sp4-3.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/02/sp4-3.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/02/sp4-3-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/02/sp4-3-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /> <img class="alignnone size-full wp-image-1782" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2018/02/sp4-2.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/02/sp4-2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/02/sp4-2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/02/sp4-2-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p>&nbsp;</p>
<p><img class="alignnone size-full wp-image-1780" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2018/02/sp4-4.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/02/sp4-4.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/02/sp4-4-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/02/sp4-4-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><img class="alignnone size-full wp-image-1779" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2018/02/sp4-5.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/02/sp4-5.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/02/sp4-5-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/02/sp4-5-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><img class="alignnone size-full wp-image-1778" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2018/02/sp4-6.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/02/sp4-6.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/02/sp4-6-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/02/sp4-6-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/time-space-complexity-of-recursion-functions-sp4/">花花酱  Time/Space Complexity of Recursion Functions SP4</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/sp/time-space-complexity-of-recursion-functions-sp4/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 Fenwick Tree / Binary Indexed Tree / 树状数组 SP3</title>
		<link>https://zxi.mytechroad.com/blog/sp/fenwick-tree-binary-indexed-tree-sp3/</link>
					<comments>https://zxi.mytechroad.com/blog/sp/fenwick-tree-binary-indexed-tree-sp3/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Thu, 04 Jan 2018 07:09:20 +0000</pubDate>
				<category><![CDATA[SP]]></category>
		<category><![CDATA[binary indexed tree]]></category>
		<category><![CDATA[fenwick tree]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=1491</guid>

					<description><![CDATA[<p>本期节目中我们介绍了Fenwick Tree/Binary Indexed Tree/树状数组的原理和实现以及它在leetcode中的应用。 In this episode, we will introduce Fenwick Tree/Binary Indexed Tree, its idea and implementation and show its applications in leetcode. Fenwick&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/fenwick-tree-binary-indexed-tree-sp3/">花花酱 Fenwick Tree / Binary Indexed Tree / 树状数组 SP3</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 title="花花酱 Fenwick Tree / Binary Indexed Tree - 刷题找工作 SP3" width="500" height="375" src="https://www.youtube.com/embed/WbafSgetDDk?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></p>
<p>本期节目中我们介绍了Fenwick Tree/Binary Indexed Tree/树状数组的原理和实现以及它在leetcode中的应用。<br>
In this episode, we will introduce Fenwick Tree/Binary Indexed Tree, its idea and implementation and show its applications in leetcode.</p>
<p>Fenwick Tree is mainly designed for solving the single point update range sum problems. e.g. what&#8217;s the sum between i-th and j-th element while the values of the elements are mutable.</p>
<p>Init the tree (include building all prefix sums) takes O(nlogn)</p>
<p>Update the value of an element takes O(logn)</p>
<p>Query the range sum takes O(logn)</p>
<p>Space complexity: O(n)</p>
<p><img class="alignnone size-full wp-image-1496" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2018/01/sp3-1.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/01/sp3-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/01/sp3-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/01/sp3-1-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script></p>
<p><ins class="adsbygoogle" style="display: block; text-align: center;" data-ad-layout="in-article" data-ad-format="fluid" data-ad-client="ca-pub-2404451723245401" data-ad-slot="7983117522"></ins><br>
<script><br />
     (adsbygoogle = window.adsbygoogle || []).push({});<br />
</script></p>
<p><img class="alignnone size-full wp-image-1495" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2018/01/sp3-2.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/01/sp3-2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/01/sp3-2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/01/sp3-2-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><strong>Applications:</strong></p>
<ul>
<li><a href="http://zxi.mytechroad.com/blog/data-structure/307-range-sum-query-mutable/">花花酱 307. Range Sum Query &#8211; Mutable</a></li>
<li><a href="http://zxi.mytechroad.com/blog/difficulty/hard/315-count-of-smaller-numbers-after-self/">花花酱 315. Count of Smaller Numbers After Self</a></li>
</ul>
<p><strong>Implementation:</strong></p>
<div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">class FenwickTree {    
public:
    FenwickTree(int n): sums_(n + 1, 0) {}
    
    void update(int i, int delta) {
        while (i &lt; sums_.size()) {
            sums_[i] += delta;
            i += lowbit(i);
        }
    }
    
    int query(int i) const {        
        int sum = 0;
        while (i &gt; 0) {
            sum += sums_[i];
            i -= lowbit(i);
        }
        return sum;
    }
private:
    static inline int lowbit(int x) { 
        return x &amp; (-x); 
    }
    vector&lt;int&gt; sums_;
};</pre>

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

<pre class="crayon-plain-tag">class FenwickTree {
    int sums_[];
    public FenwickTree(int n) {
        sums_ = new int[n + 1];
    }
    
    public void update(int i, int delta) {
        while (i &lt; sums_.length) {
            sums_[i] += delta;
            i += i &amp; -i;
        }
    }
    
    public int query(int i) {
        int sum = 0;
        while (i &gt; 0) {
            sum += sums_[i];
            i -= i &amp; -i;
        }
        return sum;
    }
}</pre>

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

<pre class="crayon-plain-tag">class FenwickTree:
    def __init__(self, n):
        self._sums = [0 for _ in range(n + 1)]
        
    def update(self, i, delta):
        while i &lt; len(self._sums):
            self._sums[i] += delta
            i += i &amp; -i
    
    def query(self, i):
        s = 0
        while i &gt; 0:
            s += self._sums[i]
            i -= i &amp; -i
        return s</pre>
</div></div>


<h2><strong>Applications</strong></h2>



<ul><li><a href="https://zxi.mytechroad.com/blog/data-structure/307-range-sum-query-mutable/">https://zxi.mytechroad.com/blog/data-structure/307-range-sum-query-mutable/</a></li><li><a href="https://zxi.mytechroad.com/blog/algorithms/array/leetcode-315-count-of-smaller-numbers-after-self/">https://zxi.mytechroad.com/blog/algorithms/array/leetcode-315-count-of-smaller-numbers-after-self/</a></li><li><a href="https://zxi.mytechroad.com/blog/simulation/leetcode-1409-queries-on-a-permutation-with-key/">https://zxi.mytechroad.com/blog/simulation/leetcode-1409-queries-on-a-permutation-with-key/</a></li></ul>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/fenwick-tree-binary-indexed-tree-sp3/">花花酱 Fenwick Tree / Binary Indexed Tree / 树状数组 SP3</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/sp/fenwick-tree-binary-indexed-tree-sp3/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode Input Size V.S. Time Complexity SP2</title>
		<link>https://zxi.mytechroad.com/blog/sp/input-size-v-s-time-complexity/</link>
					<comments>https://zxi.mytechroad.com/blog/sp/input-size-v-s-time-complexity/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Fri, 29 Dec 2017 02:52:44 +0000</pubDate>
				<category><![CDATA[SP]]></category>
		<category><![CDATA[complexity]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=1345</guid>

					<description><![CDATA[<p>本期节目介绍了输入数据规模和时间复杂度上限的关系，可以通过数据规模推算使用算法的类型。 &#160; &#60; 10: O(n!) permutation &#60; 15: O(2^n) combination &#60; 50: O(n^4) DP &#60; 200: O(n^3) DP, all pairs shortest path &#60; 1,000: O(n^2)&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/input-size-v-s-time-complexity/">花花酱 LeetCode Input Size V.S. Time Complexity SP2</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/eG99FDBeuJo?feature=oembed" frameborder="0" gesture="media" allow="encrypted-media" allowfullscreen></iframe></p>
<p>本期节目介绍了输入数据规模和时间复杂度上限的关系，可以通过数据规模推算使用算法的类型。</p>
<p>&nbsp;</p>
<p><img class="alignnone size-full wp-image-1349" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/12/sp2.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2017/12/sp2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/12/sp2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/12/sp2-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<ul>
<li>&lt; 10: O(n!) permutation</li>
<li>&lt; 15: O(2^n) combination</li>
<li>&lt; 50: O(n^4) DP</li>
<li>&lt; 200: O(n^3) DP, all pairs shortest path</li>
<li>&lt; 1,000: O(n^2) DP, all pairs, dense graph</li>
<li>&lt; 1,000,000: O(nlogn), sorting-based (greedy), heap, divide &amp; conquer</li>
<li>&lt; 1,000,000: O(n), DP, graph traversal / topological sorting (V+E), tree traversal</li>
<li>&lt; INT_MAX: O(sqrt(n)), prime, square sum</li>
<li>&lt; INT_MAX: O(logn), binary search</li>
<li>&lt; INT_MAX: O(1) Math</li>
</ul>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/input-size-v-s-time-complexity/">花花酱 LeetCode Input Size V.S. Time Complexity SP2</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/sp/input-size-v-s-time-complexity/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
