<?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>dynamic programming Archives - Huahua&#039;s Tech Road</title>
	<atom:link href="https://zxi.mytechroad.com/blog/tag/dynamic-programming/feed/" rel="self" type="application/rss+xml" />
	<link>https://zxi.mytechroad.com/blog/tag/dynamic-programming/</link>
	<description></description>
	<lastBuildDate>Fri, 30 Aug 2019 06:32:55 +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>dynamic programming Archives - Huahua&#039;s Tech Road</title>
	<link>https://zxi.mytechroad.com/blog/tag/dynamic-programming/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>花花酱 LeetCode 1143. Longest Common Subsequence</title>
		<link>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1143-longest-common-subsequence/</link>
					<comments>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1143-longest-common-subsequence/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Fri, 30 Aug 2019 06:24:35 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[dynamic programming]]></category>
		<category><![CDATA[LCS]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[O(mn)]]></category>
		<category><![CDATA[string]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=5504</guid>

					<description><![CDATA[<p>Given two strings&#160;text1&#160;and&#160;text2, return the length of their longest common subsequence. A&#160;subsequence&#160;of a string is a new string generated from the original string with some&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1143-longest-common-subsequence/">花花酱 LeetCode 1143. Longest Common Subsequence</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Given two strings&nbsp;<code>text1</code>&nbsp;and&nbsp;<code>text2</code>, return the length of their longest common subsequence.</p>



<p>A&nbsp;<em>subsequence</em>&nbsp;of a string is a new string generated from the original string with some characters(can be none) deleted without changing the relative order of the remaining characters. (eg, &#8220;ace&#8221; is a subsequence of &#8220;abcde&#8221; while &#8220;aec&#8221; is not).&nbsp;A&nbsp;<em>common subsequence</em>&nbsp;of two strings is a subsequence that is common to both strings.</p>



<p>If there is no common subsequence, return 0.</p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> text1 = "abcde", text2 = "ace" 
<strong>Output:</strong> 3  
<strong>Explanation:</strong> The longest common subsequence is "ace" and its length is 3.
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> text1 = "abc", text2 = "abc"
<strong>Output:</strong> 3
<strong>Explanation:</strong> The longest common subsequence is "abc" and its length is 3.
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> text1 = "abc", text2 = "def"
<strong>Output:</strong> 0
<strong>Explanation:</strong> There is no such common subsequence, so the result is 0.
</pre>



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



<ul><li><code>1 &lt;= text1.length &lt;= 1000</code></li><li><code>1 &lt;= text2.length &lt;= 1000</code></li><li>The input strings consist of lowercase English characters only.</li></ul>



<p><strong>Solution: DP</strong></p>



<p>Use dp[i][j] to represent the length of longest common sub-sequence of text1[0:i] and text2[0:j]<br>dp[i][j] = dp[i &#8211; 1][j &#8211; 1]  + 1 if text1[i &#8211; 1] == text2[j &#8211; 1] else max(dp[i][j &#8211; 1], dp[i &#8211; 1][j])</p>



<p>Time complexity: O(mn)<br>Space complexity: O(mn) -&gt; O(n)</p>



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

<pre class="crayon-plain-tag">// Author: Huahua, 16ms 14.9 MB
class Solution {
public:
  int longestCommonSubsequence(string text1, string text2) {
    int m = text1.length();
    int n = text2.length();
    vector&lt;vector&lt;int&gt;&gt; dp(m + 1, vector&lt;int&gt;(n + 1));
    for (int i = 0; i &lt; m; ++i)
      for (int j = 0; j &lt; n; ++j)
        if (text1[i] == text2[j])
          dp[i + 1][j + 1] = dp[i][j] + 1;
        else
          dp[i + 1][j + 1] = max(dp[i][j + 1], dp[i + 1][j]);      
    return dp[m][n];
  }
};</pre>

</div><h2 class="tabtitle">C++/V2</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">// Author: Huahua, 8ms, 8.8MB
class Solution {
public:
  int longestCommonSubsequence(string text1, string text2) {
    int m = text1.length();
    int n = text2.length();    
    vector&lt;int&gt; dp(n + 1);    
    for (int i = 0; i &lt; m; ++i) {
      int prev = 0; // dp[i][j]
      for (int j = 0; j &lt; n; ++j) {        
        int curr = dp[j + 1]; // dp[i][j + 1]
        if (text1[i] == text2[j])
          // dp[i + 1][j + 1] = dp[i][j] + 1
          dp[j + 1] = prev + 1; 
        else
          // dp[i + 1][j + 1] = max(dp[i][j + 1], dp[i + 1][j])
          dp[j + 1] = max(curr, dp[j]);
        prev = curr;
      }    
    }    
    return dp[n]; // dp[m][n]
  }
};</pre>

</div><h2 class="tabtitle">C++/V3</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  int longestCommonSubsequence(string text1, string text2) {
    int m = text1.length();
    int n = text2.length();    
    vector&lt;int&gt; dp1(n + 1);
    vector&lt;int&gt; dp2(n + 1);
    for (int i = 0; i &lt; m; ++i) {      
      for (int j = 0; j &lt; n; ++j)
        if (text1[i] == text2[j])
          dp2[j + 1] = dp1[j] + 1; 
        else          
          dp2[j + 1] = max(dp1[j + 1], dp2[j]);              
      swap(dp1, dp2);
    }    
    return dp1[n];
  }
};</pre>
</div></div>



<p></p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1143-longest-common-subsequence/">花花酱 LeetCode 1143. Longest Common Subsequence</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-1143-longest-common-subsequence/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode Weekly Contest 137</title>
		<link>https://zxi.mytechroad.com/blog/leetcode/leetcode-weekly-contest-137/</link>
					<comments>https://zxi.mytechroad.com/blog/leetcode/leetcode-weekly-contest-137/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 19 May 2019 04:00:15 +0000</pubDate>
				<category><![CDATA[Leetcode]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[dynamic programming]]></category>
		<category><![CDATA[weekly contest]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=5206</guid>

					<description><![CDATA[<p>1046.&#160;Last Stone Weight Solution: Simulation (priority_queue) Time complexity: O(nlogn)Space complexity: O(n) [crayon-663e82543470c618564524/] 1047. Remove All Adjacent Duplicates In String Solution: Stack / Deque Time complexity:&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/leetcode/leetcode-weekly-contest-137/">花花酱 LeetCode Weekly Contest 137</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2><strong>1046.&nbsp;Last Stone Weight</strong></h2>



<p>Solution: Simulation (priority_queue)</p>



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



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

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  int lastStoneWeight(vector&lt;int&gt;&amp; stones) {
    priority_queue&lt;int&gt; q;
    for (int s : stones)
      q.push(s);
    while (q.size() &gt; 1) {
      int x = q.top(); q.pop();
      int y = q.top(); q.pop();
      if (x == y) continue;
      q.push(abs(x - y));
    }
    return q.empty() ? 0 : q.top();
  }
};</pre>
</div></div>



<h2><strong>1047. Remove All Adjacent Duplicates In String</strong></h2>



<p>Solution: Stack / Deque</p>



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



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

<pre class="crayon-plain-tag">class Solution {
public:
  string removeDuplicates(string S) {
    deque&lt;char&gt; s;
    for (char c : S) {
      if (!s.empty() &amp;&amp; s.back() == c) s.pop_back();
      else s.push_back(c);
    }    
    return {begin(s), end(s)};
  }
};</pre>
</div></div>



<h2><strong>1048.&nbsp;Longest String Chain</strong></h2>



<p>Solution: DP</p>



<p>dp[i] := max length of chain of (A[0] ~ A[i-1])</p>



<p>dp[i] = max{dp[j] + 1} if A[j] is prederrsor of A[i], 1 &lt;= j &lt;i</p>



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



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

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  int longestStrChain(vector&lt;string&gt;&amp; words) {
    int n = words.size();
    sort(begin(words), end(words), [](const string&amp; a, const string&amp; b) { 
      return a.length() &lt; b.length();
    });
    vector&lt;int&gt; dp(n, 1);    
    for (int i = 0; i &lt; n; ++i)
      for (int j = 0; j &lt; i; ++j) 
        if (valid(words[j], words[i]))
          dp[i] = dp[j] + 1;
    return *max_element(begin(dp), end(dp));
  }
private:
  bool valid(const string&amp; a, const string&amp; b) {
    if (a.length() + 1 != b.length()) return false;
    int count = 0;
    for (int i = 0, j = 0; i &lt; a.length() &amp;&amp; j &lt; b.length();) {
      if (a[i] == b[j]) {
        ++i; ++j;
      } else { 
        ++count; ++j; 
      }
    }
    return count &lt;= 1;
  }
};</pre>
</div></div>



<h2><strong>1049.&nbsp;Last Stone Weight II</strong></h2>



<p><a href="https://leetcode.com/contest/weekly-contest-137/"></a>Solution: DP / target sum</p>



<p>Time complexity: O(n * S) = O(n * 100)</p>



<p>Space complexity: O(S) = O(100)</p>



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

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  int lastStoneWeightII(vector&lt;int&gt;&amp; stones) {
    const int n = stones.size();
    const int max_sum = accumulate(begin(stones), end(stones), 0);    
    unordered_set&lt;int&gt; sums;
    sums.insert(stones[0]);
    sums.insert(-stones[0]);
    for (int i = 1; i &lt; n; ++i) {
      unordered_set&lt;int&gt; tmp;
      for (int s : sums) {
        tmp.insert(s + stones[i]);
        tmp.insert(s - stones[i]);
      }
      swap(tmp, sums);
    }
    int ans = INT_MAX;
    for (int s : sums)           
      ans = min(ans, abs(s));
    return ans;
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/leetcode/leetcode-weekly-contest-137/">花花酱 LeetCode Weekly Contest 137</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/leetcode/leetcode-weekly-contest-137/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1000. Minimum Cost to Merge Stones</title>
		<link>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1000-minimum-cost-to-merge-stones/</link>
					<comments>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1000-minimum-cost-to-merge-stones/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 03 Mar 2019 05:46:35 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[dynamic programming]]></category>
		<category><![CDATA[hard]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=4930</guid>

					<description><![CDATA[<p>There are&#160;N&#160;piles of stones arranged in a row.&#160; The&#160;i-th pile has&#160;stones[i]&#160;stones. A&#160;move&#160;consists of merging&#160;exactly&#160;K&#160;consecutive&#160;piles into one pile, and the cost of this move is equal&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1000-minimum-cost-to-merge-stones/">花花酱 LeetCode 1000. Minimum Cost to Merge Stones</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/FabkoUzs64o?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<p>There are&nbsp;<code>N</code>&nbsp;piles of stones arranged in a row.&nbsp; The&nbsp;<code>i</code>-th pile has&nbsp;<code>stones[i]</code>&nbsp;stones.</p>



<p>A&nbsp;<em>move</em>&nbsp;consists of merging&nbsp;<strong>exactly&nbsp;<code>K</code>&nbsp;consecutive</strong>&nbsp;piles into one pile, and the cost of this move is equal to the total number of stones in these&nbsp;<code>K</code>&nbsp;piles.</p>



<p>Find the minimum cost to merge all piles of stones into one pile.&nbsp; If it is impossible, return&nbsp;<code>-1</code>.</p>



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



<pre class="wp-block-preformatted crayon:false"><strong>Input: </strong>stones = [3,2,4,1], K = 2
<strong>Output: </strong>20
<strong>Explanation: </strong>
We start with [3, 2, 4, 1].
We merge [3, 2] for a cost of 5, and we are left with [5, 4, 1].
We merge [4, 1] for a cost of 5, and we are left with [5, 5].
We merge [5, 5] for a cost of 10, and we are left with [10].
The total cost was 20, and this is the minimum possible.
</pre>



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



<pre class="wp-block-preformatted crayon:false"><strong>Input: </strong>stones = [3,2,4,1], K = 3
<strong>Output: </strong>-1
<strong>Explanation: </strong>After any merge operation, there are 2 piles left, and we can't merge anymore.  So the task is impossible.
</pre>



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



<pre class="wp-block-preformatted crayon:false"><strong>Input: </strong>stones = [3,5,1,2,6], K = 3
<strong>Output: </strong>25
<strong>Explanation: </strong>
We start with [3, 5, 1, 2, 6].
We merge [5, 1, 2] for a cost of 8, and we are left with [3, 8, 6].
We merge [3, 8, 6] for a cost of 17, and we are left with [17].
The total cost was 25, and this is the minimum possible.
</pre>



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



<ul><li><code>1 &lt;= stones.length &lt;= 30</code></li><li><code>2 &lt;= K &lt;= 30</code></li><li><code>1 &lt;= stones[i] &lt;= 100</code></li></ul>



<figure class="wp-block-image"><img width="960" height="540" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2019/03/1000-ep245-1.png" alt="" class="wp-image-4947" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2019/03/1000-ep245-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2019/03/1000-ep245-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2019/03/1000-ep245-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/03/1000-ep2452.png" alt="" class="wp-image-4948" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2019/03/1000-ep2452.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2019/03/1000-ep2452-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2019/03/1000-ep2452-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/03/1000-ep245-3.png" alt="" class="wp-image-4949" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2019/03/1000-ep245-3.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2019/03/1000-ep245-3-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2019/03/1000-ep245-3-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></figure>



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



<p>dp[i][j][k] := min cost to merge subarray i ~ j into k piles<br>Init: dp[i][j][k] = 0 if i==j and k == 1 else inf<br>ans: dp[0][n-1][1]<br>transition: <br>1. dp[i][j][k] = min{dp[i][m][1] + dp[m+1][j][k-1]} for all  i &lt;= m &lt; j<br>2. dp[i][j][1] = dp[i][j][K] + sum(A[i]~A[j])</p>



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



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

<pre class="crayon-plain-tag">// Running time: 12 ms, 12.1 MB
class Solution {
public:
  int mergeStones(vector&lt;int&gt;&amp; stones, int K) {
    const int n = stones.size();
    if ((n - 1) % (K - 1)) return -1;
    const int kInf = 1e9;    
    vector&lt;int&gt; sums(n + 1);
    for (int i = 0; i &lt; stones.size(); ++i)
      sums[i + 1] = sums[i] + stones[i];
    // dp[i][j][k] := min cost to merge subarray i~j into k piles.
    vector&lt;vector&lt;vector&lt;int&gt;&gt;&gt; dp(n, vector&lt;vector&lt;int&gt;&gt;(n, vector&lt;int&gt;(K + 1, kInf)));
    for (int i = 0; i &lt; n; ++i)
      dp[i][i][1] = 0;
    
    for (int l = 2; l &lt;= n; ++l) // subproblem length
      for (int i = 0; i &lt;= n - l; ++i) { // start
        int j = i + l - 1; // end
        for (int k = 2; k &lt;= K; ++k) // piles
          for (int m = i; m &lt; j; m += K - 1) // split point
            dp[i][j][k] = min(dp[i][j][k], dp[i][m][1] + dp[m + 1][j][k - 1]);
        dp[i][j][1] = dp[i][j][K] + sums[j + 1] - sums[i];
      }        
    return dp[0][n - 1][1];
  }
};</pre>

</div><h2 class="tabtitle">C++/top down</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">// Author: Huahua, running time: 12 ms
class Solution {
public:
  int mergeStones(vector&lt;int&gt;&amp; stones, int K) {
    const int n = stones.size();
    if ((n - 1) % (K - 1)) return -1;
    const int kInf = 1e9;
    vector&lt;int&gt; sums(n + 1);
    for (int i = 0; i &lt; stones.size(); ++i)
      sums[i + 1] = sums[i] + stones[i];
    
    vector&lt;vector&lt;vector&lt;int&gt;&gt;&gt; cache(n, vector&lt;vector&lt;int&gt;&gt;(n, vector&lt;int&gt;(K + 1, INT_MAX)));
    std::function&lt;int(int, int, int)&gt; dp = [&amp;stones, &amp;sums, &amp;cache, kInf, n, K, &amp;dp](int i, int j, int k) {
      if ((j - i + 1 - k) % (K - 1)) return kInf;
      if (i == j) return k == 1 ? 0 : kInf;
      if (cache[i][j][k] != INT_MAX) return cache[i][j][k];      
      if (k == 1)
        return cache[i][j][k] = dp(i, j, K) + sums[j + 1] - sums[i];
      int ans = kInf;
      for (int m = i; m &lt; j; m += K - 1) {
        int l = dp(i, m, 1);
        if (l &gt;= ans) continue;
        int r = dp(m + 1, j, k - 1);
        if (r &gt;= ans) continue;
        ans = min(ans, l + r);
      }
      return cache[i][j][k] = ans;
    };
    return dp(0, n - 1, 1);
  }
};</pre>
</div></div>



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



<p>dp[l][i] := min cost to merge [i, i + l) into as less piles as possible. Number of merges will be (l-1) / (K &#8211; 1) and <br>Transition: dp[l][i] = min(dp[m][i] + dp[l &#8211; m][i + m]) for 1 &lt;= m &lt; l<br>if ((l &#8211; 1) % (K &#8211; 1) == 0) [i, i + l) can be merged into 1 pile, dp[l][i] += sum(A[i:i+l])</p>



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



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

<pre class="crayon-plain-tag">// Author: Huahua 4ms, 9.6 MB
class Solution {
public:
  int mergeStones(vector&lt;int&gt;&amp; stones, int K) {
    const int n = stones.size();
    if ((n - 1) % (K - 1)) return -1;
        
    vector&lt;int&gt; sums(n + 1);
    for (int i = 0; i &lt; stones.size(); ++i) 
      sums[i + 1] = sums[i] + stones[i];
    
    const int kInf = 1e9;
    // dp[i][j] := min cost to merge subarray A[i] ~ A[j] into (j-i)%(K-1) + 1 piles
    vector&lt;vector&lt;int&gt;&gt; dp(n, vector&lt;int&gt;(n, kInf));
    for (int i = 0; i &lt; n; ++i) dp[i][i] = 0;
    
    for (int l = 2; l &lt;= n; ++l) // subproblem length 
      for (int i = 0; i &lt;= n - l; ++i) { // start        
        int j = i + l - 1;
        for (int m = i; m &lt; j ; m += K - 1) // split point
            dp[i][j] = min(dp[i][j], dp[i][m] + dp[m + 1][j]);
        // If the current length can be merged into 1 pile
        // The cost is independent of the merge orders.
        if ((l - 1) % (K - 1) == 0)
          dp[i][j] += sums[j + 1] - sums[i];
      }
    return dp[0][n - 1];
  }
};</pre>

</div><h2 class="tabtitle">C++/Top-Down</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">// Author: Huahua, 4 ms
class Solution {
public:
  int mergeStones(vector&lt;int&gt;&amp; stones, int K) {
    const int n = stones.size();
    if ((n - 1) % (K - 1)) return -1;
    const int kInf = 1e9;
    vector&lt;vector&lt;int&gt;&gt; cache(n, vector&lt;int&gt;(n, kInf));    
    vector&lt;int&gt; sums(n + 1);
    for (int i = 0; i &lt; stones.size(); ++i) sums[i + 1] = sums[i] + stones[i];
    
    std::function&lt;int(int, int)&gt; dp;
    dp = [&amp;stones, &amp;sums, &amp;cache, &amp;dp, K, kInf](int i, int j) {
      const int l = j - i + 1;
      if (l &lt; K) return 0;
      if (cache[i][j] != kInf) return cache[i][j];
      int ans = kInf;
      for (int m = i; m &lt; j ; m += K - 1) // split point
        ans = min(ans, dp(i, m) + dp(m + 1, j));
      if ((l - 1) % (K - 1) == 0)
        ans += sums[j + 1] - sums[i];
      return cache[i][j] = ans;
    };    
    return dp(0, n - 1);  
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1000-minimum-cost-to-merge-stones/">花花酱 LeetCode 1000. Minimum Cost to Merge Stones</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-1000-minimum-cost-to-merge-stones/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 Leetcode 140. Word Break II</title>
		<link>https://zxi.mytechroad.com/blog/leetcode/leetcode-140-word-break-ii/</link>
					<comments>https://zxi.mytechroad.com/blog/leetcode/leetcode-140-word-break-ii/#comments</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 03 Sep 2017 00:22:43 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[Leetcode]]></category>
		<category><![CDATA[combination]]></category>
		<category><![CDATA[dynamic programming]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[word break]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=52</guid>

					<description><![CDATA[<p>Problem Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, add spaces in s to construct a sentence where each word is a valid dictionary word. You may assume&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/leetcode/leetcode-140-word-break-ii/">花花酱 Leetcode 140. Word Break II</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/JqOIRBC0_9c?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<h1><strong>Problem</strong></h1>
<p>Given a <b>non-empty</b> string <i>s</i> and a dictionary <i>wordDict</i> containing a list of <b>non-empty</b> words, add spaces in <i>s</i> to construct a sentence where each word is a valid dictionary word. You may assume the dictionary does not contain duplicate words.</p>
<p>Return all such possible sentences.</p>
<p>For example, given<br />
<i>s</i> = <code>"catsanddog"</code>,<br />
<i>dict</i> = <code>["cat", "cats", "and", "sand", "dog"]</code>.</p>
<p>A solution is <code>["cats and dog", "cat sand dog"]</code>.</p>
<p><b><span style="color: red;">UPDATE (2017/1/4):</span></b><br />
The <i>wordDict</i> parameter had been changed to a list of strings (instead of a set of strings). Please reload the code definition to get the latest changes.</p>
<h1><strong>Solution</strong></h1>
<p>Time complexity: O(2^n)</p>
<p>Space complexity: O(2^n)</p>
<p>C++</p><pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
    vector&lt;string&gt; wordBreak(string s, vector&lt;string&gt;&amp; wordDict) {
        unordered_set&lt;string&gt; dict(wordDict.cbegin(), wordDict.cend());
        return wordBreak(s, dict);
    }
private:
    // &gt;&gt; append({"cats and", "cat sand"}, "dog");
    // {"cats and dog", "cat sand dog"}
    vector&lt;string&gt; append(const vector&lt;string&gt;&amp; prefixes, const string&amp; word) {
        vector&lt;string&gt; results;
        for(const auto&amp; prefix : prefixes)
            results.push_back(prefix + " " + word);
        return results;
    }
    
    const vector&lt;string&gt;&amp; wordBreak(string s, unordered_set&lt;string&gt;&amp; dict) {
        // Already in memory, return directly
        if(mem_.count(s)) return mem_[s];
        
        // Answer for s
        vector&lt;string&gt; ans;
        
        // s in dict, add it to the answer array
        if(dict.count(s)) 
            ans.push_back(s);
        
        for(int j=1;j&lt;s.length();++j) {
            // Check whether right part is a word
            const string&amp; right = s.substr(j);
            if (!dict.count(right)) continue;
            
            // Get the ans for left part
            const string&amp; left = s.substr(0, j);
            const vector&lt;string&gt; left_ans = 
                append(wordBreak(left, dict), right);
            
            // Notice, can not use mem_ here,
            // since we haven't got the ans for s yet.
            ans.insert(ans.end(), left_ans.begin(), left_ans.end());
        }
        
        // memorize and return
        mem_[s].swap(ans);
        return mem_[s];
    }
private:
    unordered_map&lt;string, vector&lt;string&gt;&gt; mem_;
};</pre><p>Python3</p><pre class="crayon-plain-tag">"""
Author: Huahua
Running time: 56 ms
"""
class Solution:
  def wordBreak(self, s, wordDict):
    words = set(wordDict)
    mem = {}
    def wordBreak(s):
      if s in mem: return mem[s]
      ans = []
      if s in words: ans.append(s)
      for i in range(1, len(s)):
        right = s[i:]
        if right not in words: continue        
        ans += [w + " " + right for w in wordBreak(s[0:i])]
      mem[s] = ans
      return mem[s]
    return wordBreak(s)</pre><p>&nbsp;</p>
<h1><strong>Related Problems</strong></h1>
<ul>
<li><a href="http://zxi.mytechroad.com/blog/leetcode/leetcode-139-word-break/">[解题报告] Leetcode 139. Word Break 花花酱</a></li>
<li><a href="http://zxi.mytechroad.com/blog/searching/127-word-ladder/">[解题报告] LeetCode 127. Word Ladder</a></li>
<li><a href="http://zxi.mytechroad.com/blog/searching/leetcode-126-word-ladder-ii/">[解题报告] LeetCode 126. Word Ladder II</a></li>
</ul>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/leetcode/leetcode-140-word-break-ii/">花花酱 Leetcode 140. Word Break II</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/leetcode/leetcode-140-word-break-ii/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 Leetcode 139. Word Break</title>
		<link>https://zxi.mytechroad.com/blog/leetcode/leetcode-139-word-break/</link>
					<comments>https://zxi.mytechroad.com/blog/leetcode/leetcode-139-word-break/#comments</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sat, 02 Sep 2017 23:48:16 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[Leetcode]]></category>
		<category><![CDATA[dynamic programming]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[recursion]]></category>
		<category><![CDATA[string]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=49</guid>

					<description><![CDATA[<p>Problem Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine if s can be segmented into a space-separated sequence of one or more dictionary words. You may assume&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/leetcode/leetcode-139-word-break/">花花酱 Leetcode 139. Word Break</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/ptlwluzeC1I?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<h1>
<strong>Problem</strong></h1>
<p>Given a <b>non-empty</b> string <i>s</i> and a dictionary <i>wordDict</i> containing a list of <b>non-empty</b> words, determine if <i>s</i> can be segmented into a space-separated sequence of one or more dictionary words. You may assume the dictionary does not contain duplicate words.</p>
<p>For example, given<br />
<i>s</i> = <code>"leetcode"</code>,<br />
<i>dict</i> = <code>["leet", "code"]</code>.</p>
<p>Return true because <code>"leetcode"</code> can be segmented as <code>"leet code"</code>.</p>
<p><b><span style="color: red;">UPDATE (2017/1/4):</span></b><br />
The <i>wordDict</i> parameter had been changed to a list of strings (instead of a set of strings). Please reload the code definition to get the latest changes.</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></p>
<h1><strong>Idea:</strong></h1>
<p>DP</p>
<p>Time complexity O(n^2)</p>
<p>Space complexity O(n^2)</p>
<p><a href="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/139.png"><img class="alignnone size-full wp-image-652" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/139.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/139.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/139-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/139-768x432.png 768w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/139-624x351.png 624w" sizes="(max-width: 960px) 100vw, 960px" /></a></p>
<h1><strong>Solutions:</strong></h1>
<p>C++</p><pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
    bool wordBreak(string s, vector&lt;string&gt;&amp; wordDict) {
        // Create a hashset of words for fast query.
        unordered_set&lt;string&gt; dict(wordDict.cbegin(), wordDict.cend());
        // Query the answer of the original string.
        return wordBreak(s, dict);
    }
    
    bool wordBreak(const string&amp; s, const unordered_set&lt;string&gt;&amp; dict) {
        // In memory, directly return.
        if(mem_.count(s)) return mem_[s];
        // Whole string is a word, memorize and return.
        if(dict.count(s)) return mem_[s]=true;
        // Try every break point.
        for(int j=1;j&lt;s.length();j++) {
            const string left = s.substr(0,j);
            const string right = s.substr(j);
            // Find the solution for s.
            if(dict.count(right) &amp;&amp; wordBreak(left, dict))
                return mem_[s]=true;
        }
        // No solution for s, memorize and return.
        return mem_[s]=false;
    }
private:
    unordered_map&lt;string, bool&gt; mem_;
};</pre><p>C++ V2 without using dict. Updated: 1/9/2018</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 9 ms
class Solution {
public:
    bool wordBreak(string s, vector&lt;string&gt;&amp; wordDict) {
      // Mark evert word as breakable.
      for (const string&amp; word : wordDict)
        mem_.emplace(word, true);

      // Query the answer of the original string.
      return wordBreak(s);
    }
    
    bool wordBreak(const string&amp; s) {
      // In memory, directly return.
      if (mem_.count(s)) return mem_[s];

      // Try every break point.
      for (int j = 1; j &lt; s.length(); j++) {         
          auto it = mem_.find(s.substr(j));
          // Find the solution for s.
          if (it != mem_.end() &amp;&amp; it-&gt;second &amp;&amp; wordBreak(s.substr(0, j)))
            return mem_[s] = true;
      }
      
      // No solution for s, memorize and return.
      return mem_[s] = false;
    }
private:
    unordered_map&lt;string, bool&gt; mem_;
};</pre><p>&nbsp;</p>
<p>Java</p><pre class="crayon-plain-tag">// Author: Huahua
// Runtime: 13 ms
class Solution {
    public boolean wordBreak(String s, List&lt;String&gt; wordDict) {
        Set&lt;String&gt; dict = new HashSet&lt;String&gt;(wordDict);
        Map&lt;String, Boolean&gt; mem = new HashMap&lt;String, Boolean&gt;();
        return wordBreak(s, mem, dict);
    }

    private boolean wordBreak(String s,
                              Map&lt;String, Boolean&gt; mem, 
                              Set&lt;String&gt; dict) {
        if (mem.containsKey(s)) return mem.get(s);
        if (dict.contains(s)) {
            mem.put(s, true);
            return true;
        }
        
        for (int i = 1; i &lt; s.length(); ++i) {
            if (dict.contains(s.substring(i)) &amp;&amp; wordBreak(s.substring(0, i), mem, dict)) {
                mem.put(s, true);
                return true;
            }
        }
        
        mem.put(s, false);
        return false;
    }
}</pre><p>Python</p><pre class="crayon-plain-tag">"""
Author: Huahua
Runtime: 42 ms
"""
class Solution(object):
    def wordBreak(self, s, wordDict):
        def canBreak(s, m, wordDict):
            if s in m: return m[s]
            if s in wordDict: 
                m[s] = True
                return True
            
            for i in range(1, len(s)):
                r = s[i:]
                if r in wordDict and canBreak(s[0:i], m, wordDict):
                    m[s] = True
                    return True
            
            m[s] = False
            return False
            
        return canBreak(s, {}, set(wordDict))</pre><p>&nbsp;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/leetcode/leetcode-139-word-break/">花花酱 Leetcode 139. Word Break</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/leetcode/leetcode-139-word-break/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 486. Predict the Winner</title>
		<link>https://zxi.mytechroad.com/blog/leetcode/leetcode-486-predict-the-winner/</link>
					<comments>https://zxi.mytechroad.com/blog/leetcode/leetcode-486-predict-the-winner/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sat, 25 Mar 2017 05:38:38 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[Leetcode]]></category>
		<category><![CDATA[dynamic programming]]></category>
		<category><![CDATA[game]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[min-max]]></category>
		<category><![CDATA[recursion]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=37</guid>

					<description><![CDATA[<p>Problem Given an array of scores that are non-negative integers. Player 1 picks one of the numbers from either end of the array followed by&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/leetcode/leetcode-486-predict-the-winner/">花花酱 LeetCode 486. Predict the Winner</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/g5wLHFTodm0?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<h1><strong>Problem</strong></h1>
<p>Given an array of scores that are non-negative integers. Player 1 picks one of the numbers from either end of the array followed by the player 2 and then player 1 and so on. Each time a player picks a number, that number will not be available for the next player. This continues until all the scores have been chosen. The player with the maximum score wins.</p>
<p>Given an array of scores, predict whether player 1 is the winner. You can assume each player plays to maximize his score.</p>
<p><strong>Example 1:</strong><br />
Input: [1, 5, 2]<br />
Output: False<br />
Explanation: Initially, player 1 can choose between 1 and 2.<br />
If he chooses 2 (or 1), then player 2 can choose from 1 (or 2) and 5. If player 2 chooses 5, then player 1 will be left with 1 (or 2).<br />
So, final score of player 1 is 1 + 2 = 3, and player 2 is 5.<br />
Hence, player 1 will never be the winner and you need to return False.</p>
<p><strong>Example 2:</strong><br />
Input: [1, 5, 233, 7]<br />
Output: True<br />
Explanation: Player 1 first chooses 1. Then player 2 have to choose between 5 and 7. No matter which number player 2 choose, player 1 can choose 233.<br />
Finally, player 1 has more score (234) than player 2 (12), so you need to return True representing player1 can win.<br />
Note:<br />
1 &lt;= length of the array &lt;= 20.<br />
Any scores in the given array are non-negative integers and will not exceed 10,000,000.<br />
If the scores of both players are equal, then player 1 is still the winner.</p>
<p><img class="alignnone size-full wp-image-2768" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2017/03/486-ep185.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2017/03/486-ep185.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/03/486-ep185-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2017/03/486-ep185-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<h1><strong>Solution 1: Recursion</strong></h1>
<p>Time complexity: O(2^n)</p>
<p>Space complexity: O(n)</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 67 ms
class Solution {
public:
  bool PredictTheWinner(vector&lt;int&gt;&amp; nums) {    
    return getScore(nums, 0, nums.size() - 1) &gt;= 0;
  }
private:  
  // Max diff (my_score - op_score) of subarray nums[l] ~ nums[r].
  int getScore(vector&lt;int&gt;&amp; nums, int l, int r) {
    if (l == r) return nums[l];
    return max(nums[l] - getScore(nums, l + 1, r), 
               nums[r] - getScore(nums, l, r - 1));    
  }
};</pre><p></p>
<h1><strong>Solution 2: Recursion + Memoization</strong></h1>
<p>Time complexity: O(n^2)</p>
<p>Space complexity: O(n)</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 4 ms
class Solution {
public:
  bool PredictTheWinner(vector&lt;int&gt;&amp; nums) {
    m_ = vector&lt;vector&lt;int&gt;&gt;(nums.size(), vector&lt;int&gt;(nums.size(), INT_MIN));
    return getScore(nums, 0, nums.size() - 1) &gt;= 0;
  }
private:
  vector&lt;vector&lt;int&gt;&gt; m_;
  // Max diff (my_score - op_score) of subarray nums[l] ~ nums[r].
  int getScore(vector&lt;int&gt;&amp; nums, int l, int r) {
    if (l == r) return nums[l];    
    if (m_[l][r] != INT_MIN) return m_[l][r];
    m_[l][r] = max(nums[l] - getScore(nums, l + 1, r), 
                   nums[r] - getScore(nums, l, r - 1));
    return m_[l][r];
  }    
};</pre><p>DP version</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 4 ms
class Solution {
public:
  bool PredictTheWinner(vector&lt;int&gt;&amp; nums) {
    const int n = nums.size();
    vector&lt;vector&lt;int&gt;&gt; dp(n, vector&lt;int&gt;(n, INT_MIN));
    for (int i = 0; i &lt; n; ++i)
      dp[i][i] = nums[i];
    for (int l = 2; l &lt;= n; ++l)
      for (int i = 0; i &lt;= n - l; ++i) {
        int j = i + l - 1;
        dp[i][j] = max(nums[i] - dp[i + 1][j], nums[j] - dp[i][j - 1]);
      }
    return dp[0][n - 1] &gt;= 0;
  }
};</pre><p></p>
<h1><strong>Related Problem</strong></h1>
<ul>
<li><a href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-877-stone-game/">花花酱 LeetCode 877. Stone Game</a></li>
</ul>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/leetcode/leetcode-486-predict-the-winner/">花花酱 LeetCode 486. Predict the Winner</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/leetcode/leetcode-486-predict-the-winner/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
