Showing posts with label dp. Show all posts
Showing posts with label dp. Show all posts

Saturday, May 30, 2015

约瑟夫环问题

来源:Bloomberg Onsite

原帖:http://blog.csdn.net/wuzhekai1985/article/details/6628491

题目:
最近看bloomberg的面经看到出现过几次约瑟夫环问题。这道题的模拟解法非常直观,更好的解法是观察索引的映射关系采用recursion来解。以前没有仔细思考过这个问题。博客链接给了很好的解释。

约瑟夫环问题的原来描述为,设有编号为1,2,……,n的n(n>0)个人围成一个圈,从第1个人开始报数,报到m时停止报数,报m的人出圈,再从他的下一个人起重新报数,报到m时停止报数,报m的出圈,……,如此下去,直到所有人全部出圈为止。当任意给定n和m后,设计算法求n个人出圈的次序。  稍微简化一下。
问题描述:n个人(编号0~(n-1)),从0开始报数,报到(m-1)的退出,剩下的人继续从0开始报数。求胜利者的编号。

代码:
1] Brute force solution
 int JosephusProblem(int n, int m) {   
   if (n < 1 || m < 1)   
     return -1;   
    
   list<int> listInt;   
   unsigned i;   
   //初始化链表   
   for (i = 0; i < n; i++)   
     listInt.push_back(i);    
   list<int>::iterator iterCurrent = listInt.begin();   
   while (listInt.size() > 1) {   
     //前进m - 1步   
     for(i = 0; i < m-1; i++) {   
       if(++iterCurrent == listInt.end())   
         iterCurrent = listInt.begin();   
     }   
     //临时保存删除的结点   
     list<int>::iterator iterDel = iterCurrent;   
     if(++iterCurrent == listInt.end())   
       iterCurrent = listInt.begin();   
     //删除结点   
     listInt.erase(iterDel);   
   }  
   return *iterCurrent;   
 }  

2] dp solution
 int JosephusProblem(int n, int m) {   
   if(n < 1 || m < 1)   
     return -1;   
   vector<int> f(n+1,0);   
   for(unsigned i = 2; i <= n; i++)   
     f[i] = (f[i-1] + m) % i;    
   return f[n];   
 }  

Monday, May 18, 2015

Longest Common Subsequence

来源:nineChapter

原帖:nineChapter; dp

题目:
state: f[i][j]表示前i个字符配上前j个字符的LCS的长度
function: f[i][j] = f[i-1][j-1] + 1 // a[i] == b[j]
                 = MAX(f[i-1][j], f[i][j-1]) // a[i] != b[j]
intialize: f[i][0] = 0
               f[0][j] = 0
answer: f[a.length()][b.length()]

代码:
 int longestCommonSubsequence(string s1, string s2) {  
   int M = s1.size(), N = s2.size();  
   int dp[M + 1][N + 1] = {0};  
   //memset(dp, 0, sizeof(dp));  
   for (int i = 0; i <= M; ++i) {  
     dp[i][0] = 0;  
   }  
     
   for (int j = 0; j <= N; ++j) {  
     dp[0][j] = 0;  
   }  
   for (int i = 1; i <= M; ++i) {  
     for (int j = 1; j <= N; ++j) {  
       if (s1[i - 1] == s2[j - 1]) {  
         dp[i][j] = dp[i - 1][j - 1] + 1;  
       } else {  
         dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);  
       }  
     }  
   }  
   return dp[M][N];  
 }  

Coin Change

来源:g4g, Facebook Onsite

原帖:http://www.geeksforgeeks.org/dynamic-programming-set-7-coin-change/

题目:
Given a value N, if we want to make change for N cents, and we have infinite supply of each of S = { S1, S2, .. , Sm} valued coins, how many ways can we make the change? The order of coins doesn’t matter. For example, for N = 4 and S = {1,2,3}, there are four solutions: {1,1,1,1},{1,1,2},{2,2},{1,3}. So output should be 4. For N = 10 and S = {2, 5, 3, 6}, there are five solutions: {2,2,2,2,2}, {2,2,3,3}, {2,2,6}, {2,3,5} and {5,5}. So the output should be 5.

代码:
 #include <iostream>  
 #include <string>  
 #include <vector>  
 using namespace std;  
   
 int changeCoins(int m, vector<int>& amount, int idx) {  
   if (idx == 0) return m % amount[idx] == 0 ? 1 : 0;  
   int count = 0;  
   for (int i = 0; i * amount[idx] <= m; ++i) {  
     count += changeCoins(m - i * amount[idx], amount, idx - 1);  
   }  
   return count;  
 }  
   
 vector<int> amount = {2, 3, 5};  
 int main() {  
   int m = 7;  
   int idx = amount.size();  
   cout << changeCoins(m, amount, idx-1);  
   return 0;  
 }  

二维dp
 int count( int S[], int m, int n )  
 {  
   int i, j, x, y;  
    
   // We need n+1 rows as the table is consturcted in bottom up manner using   
   // the base case 0 value case (n = 0)  
   int table[n+1][m];  
     
   // Fill the enteries for 0 value case (n = 0)  
   for (i=0; i<m; i++)  
     table[0][i] = 1;  
    
   // Fill rest of the table enteries in bottom up manner   
   for (i = 1; i < n+1; i++)  
   {  
     for (j = 0; j < m; j++)  
     {  
       // Count of solutions including S[j]  
       x = (i-S[j] >= 0)? table[i - S[j]][j]: 0;  
    
       // Count of solutions excluding S[j]  
       y = (j >= 1)? table[i][j-1]: 0;  
    
       // total count  
       table[i][j] = x + y;  
     }  
   }  
   return table[n][m-1];  
 }  
    

Longest Common Substring

来源:nineChapter

原帖:nineChapter; dp

题目:
state: f[i][j]表示前i个字符配上前j个字符的LCS‘的长度 (一定以第i个和第j个结尾的LCS’)
function: f[i][j]  = f[i-1][j-1] + 1 // a[i] == b[j]
                  = 0 // a[i] != b[j]
intialize: f[i][0] = 0
            f[0][j] = 0
answer: MAX(f[0..a.length()][0..b.length()]

代码:
 int longestCommonSubstring(string s1, string s2) {  
   int M = s1.size(), N = s2.size();   
   vector<vector<int> > dp(M, vector<int>(N,0));  
   for (int i = 0; i <= M; ++i)  
     dp[i][0] = 0;  
   for (int j = 0; j <= N; ++j)  
     dp[0][j] = 0;  
   int maximum = 0;  
   for (int i = 1; i <= M; ++i) {  
     for (int j = 1; j <= N; ++j) {  
       if (s1[i - 1] == s2[j - 1]) {  
         dp[i][j] = dp[i - 1][j - 1] + 1;  
       } else {  
         dp[i][j] = 0;  
       }  
       maximum = max(maximum, dp[i][j]);  
     }  
   }  
   return maximum;  
 }  


Longest Increasing Subsequence

来源:nineChapter

原帖:nineChapter; dp

题目:
Longest Increasing Subsequence
1 1000 2 3 4
10 11 12 1 2 3 4 13

代码:
 int longestIncreasingSubsequence(const vector<int> &nums) {  
   vector<int> dp(nums.size(), 0);  
   dp[0] = 1;  
   unordered_map<int, vector<int> > map;  
   map[0] = {nums[0]};  
   for (int i = 1; i < nums.size(); ++i) {  
     for (int j = 0; j < i; ++j) {  
       if (nums[i] > nums[j] && dp[i] < dp[j] + 1) {  
         map[i] = move(map[j]);  
         map[i].push_back(nums[i]);  
         dp[i] = max(dp[i], dp[j] + 1);  
       }  
     }  
   }  
   for (auto i : map[nums.size()-1]) cout << i << " ";  
   cout << endl;   
   return dp[nums.size() - 1];  
 }  
   
 int main() {  
   vector<int> nums = {1,2,4,3,2,7,8,9};  
   longestIncreasingSubsequence(nums);  
   return 0;  
 }  


Interleaving String

来源:Leetcode

原帖:http://oj.leetcode.com/problems/interleaving-string/

题目:
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.
For example,
Given:
s1 = "aabcc",
s2 = "dbbca",
When s3 = "aadbbcbcac", return true.
When s3 = "aadbbbaccc", return false.

Solution: 1. dp. O(MN) time & space. 'dp[i][j] == true' means that there is at least one way to construct the string s3[0...i+j-1] by interleaving s1[0...j-1] and s2[0...i-1].

代码:
 class Solution {  
 public:  
   //Version 1: dp  
   bool isInterleave(string s1, string s2, string s3) {  
     int M = s1.size(), N = s2.size(), K = s3.size();  
     if (M + N != K) return false;  
     if (s1.empty()) return s2 == s3; // corner case  
     if (s2.empty()) return s1 == s3;  
     vector<vector<bool> > dp(N + 1, vector<bool>(M + 1, false));  
     for (int i = 1; i <= N; ++i)  
       dp[i][0] = s2[i - 1] == s3[i - 1];  
     for (int j = 1; j <= M; ++j)  
       dp[0][j] = s1[j - 1] == s3[j - 1];        
     for (int i = 1; i <= N; ++i) {  
       for (int j = 1; j <= M; ++j) {  
         dp[i][j] = dp[i - 1][j] && s2[i - 1] == s3[i + j - 1] ||  
               dp[i][j - 1] && s1[j - 1] == s3[i + j - 1];          
       }  
     }  
     return dp[N][M];  
   }  
 };  

Palindrome Partitioning II

来源:Leetcode

原帖:https://oj.leetcode.com/problems/palindrome-partitioning-ii/

题目:
Given a string s, partition s such that every substring of the partition is a palindrome. Return the minimum cuts needed for a palindrome partitioning of s.
For example, given s = "aab",
Return 1 since the palindrome partitioning ["aa","b"] could be produced using 1 cut.

代码:
 class Solution {  
 public:  
   int minCut(string s) {  
     int N = s.size();  
     // isP[0]: [0,i] is palindrome  
     bool isP[N]; // [j,i] is palindrome; j = [0, 1, ..., i-1]  
     int dp[N];  
     dp[0] = 0;  
     for (int i = 1; i < N; ++i) { // end point  
       isP[i] = true;  
       dp[i] = dp[i-1] + 1; // dp[i-1] + single word cut  
       for (int j = 0; j < i; ++j) {  
         isP[j] = (s[i] == s[j]) ? isP[j+1] : false; // isP[j] == true  -> [j...i] is a palindrome; ascending order  
                           // isP[j+1] == true -> [j+1...i-1] is a palindrome  
         if (isP[j]) {  
           dp[i] = (j == 0) ? 0 : min(dp[i], dp[j-1] + 1); // dp[i] -> minCount for [0...i]            
         }  
       }  
     }  
     return dp[N-1];  
   }  
 };  
   
 // Time Limit Exceed  
 class Solution {  
 public:  
   //Version 2: sequence dp; easier to understand isP  
   void getIsPalindrome(const string &s, vector<vector<bool> > &isP) {  
     int N = s.size();  
     // isP[i][j] (start i, end j is palindrome)  
     for (int i = 0; i < N; ++i) {  
       isP[i][i] = true;        
     }  
     for (int l = 2; l <= N; ++l) {  
       for (int i = 0; i <= N - l; ++i) {  
         isP[i][i + l - 1] = false;  
         if (l == 2) {  
           isP[i][i + l - 1] = (s[i] == s[i + 1]);  
         } else {  
           isP[i][i + l - 1] = (s[i] == s[i + l - 1] && isP[i + 1][i + l - 2]);  
         }    
       }  
     }  
   }  
   
   int minCut(string s) {  
     int N = s.size();  
     vector<vector<bool>> isP(N, vector<bool>(N, false));  
     getIsPalindrome(s, isP);  
     vector<int> dp(N, 0);  
     dp[0] = 0;  
     for (int i = 1; i < N; ++i) {  
       dp[i] = dp[i - 1] + 1;  
       for (int j = 0; j < i; ++j) {  
         if (j == 0 && isP[j][i]) {  
           dp[i] = 0;   
           break;  
         } else if (isP[j][i]) {  
           dp[i] = min(dp[i], dp[j - 1] + 1);  
         }  
       }  
     }  
     return dp[N - 1];  
   }  
 };  


Scramble String

来源:Leetcode

原帖:http://oj.leetcode.com/problems/scramble-string/

题目:
Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively.
Below is one possible representation of s1 = "great":
       great
      /     \
     gr    eat
    / \    /  \
   g   r  e   at
              / \
             a   t
To scramble the string, we may choose any non-leaf node and swap its two children. For example, if we choose the node "gr" and swap its two children, it produces a scrambled string "rgeat".
       rgeat
      /     \
     rg    eat
    / \    /  \
   r   g  e   at
              / \
             a   t
We say that "rgeat" is a scrambled string of "great". Similarly, if we continue to swap the children of nodes "eat" and "at", it produces a scrambled string "rgtae".
      rgtae
      /    \
     rg    tae
    / \    /  \
   r   g  ta  e
          / \
         t   a
We say that "rgtae" is a scrambled string of "great". Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1.
Solution: 1. 3-dimensional dp.
              'dp[k][i][j] == true' means string s1(start from i, length k) is a scrambled string of
              string s2(start from j, length k).

代码:
 class Solution {  
 public:  
   bool isScramble(string s1, string s2) {  
     if(s1.size() != s2.size()) return false;  
     int N = s1.size();  
     bool dp[N + 1][N][N];  
     for (int k = 1; k <= N; ++k) { // string length k  
       for (int i = 0; i <= N-k; ++i) { // start i  
         for (int j = 0; j <= N-k; ++j) { // start j   
           dp[k][i][j] = false;  
           if (k == 1)  
             dp[1][i][j] = (s1[i] == s2[j]);    
           for (int p = 1; p < k; ++p) { // 把树分成两子树,如果满足scramble,则分成的两个子树一定是scramble  
             if (dp[p][i][j] && dp[k - p][i + p][j + p]   
              || dp[p][i][j + k - p] && dp[k - p][i + p][j]) {  
               dp[k][i][j] = true;   
               break;              
             }  
           }  
         }  
       }  
     }  
     return dp[N][0][0];  
   }  
 };  


Longest Increasing Box

来源:cc150, itint5

原帖:http://www.itint5.com/oj/#34

题目:
有n块积木,每块积木有体积vol和重量weight两个属性,用二元组(vol, weight)表示。积木需要搭成竖直的塔状,上面积木的体积和重量必须都比它下面的积木小。问最多可以搭多少个积木。样例:
有7个积木boxes:
 [(65, 100), (70, 150), (56, 90), (75, 190), (60, 95), (68, 110), (80, 12)]
最多可以搭6个积木,从上到下分别为:
 (56, 90), (60, 95), (65, 100), (68, 110), (70, 150), (75, 190)
所以函数应该返回6。

题目来源:CRACKING THE CODING INTERVIEW 9.7
Solution: 先按照vol进行排序,题目就变成了根据weight寻找最长严格递增子序列。

代码:
 /*积木的定义(请不要在代码中定义该结构)  
 struct Box {  
  int vol, weight;  
 };*/  
    
 int mycompare(const Box& a, const Box& b) {  
   if (a.vol == b.vol)  
     return a.weight < b.weight;  
   return a.vol < b.vol;  
 }  
   
 int maxBoxes(vector<Box> &boxes) {  
   int N = boxes.size();  
   if (N == 0) return 0;  
   sort(boxes.begin(), boxes.end(), mycompare);  
   vector<int> dp(N, 0);  
   int res = 1;  
   for (int i = 0; i < N; ++i) {  
     dp[i] = 1;  
     for (int j = 0; j < i; ++j)  
       if (boxes[i].vol > boxes[j].vol && boxes[i].weight > boxes[j].weight)  
         dp[i] = max(dp[i], dp[j] + 1);  
     res = max(res, dp[i]);  
   }  
   return res;  
 }  

Minimum Path Sum

来源:Leetcode

原帖:http://oj.leetcode.com/problems/minimum-path-sum/

题目:
Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.
Note: You can only move either down or right at any point in time.
Solution: Dynamic Programming. Space O(N).

代码:
 class Solution {  
 public:  
   int minPathSum(vector<vector<int> > &grid) {  
     if (grid.empty()) return INT_MIN;  
     int M = grid.size(), N = grid[0].size(); // col  
     vector<int> dp(N, 0);  
     dp[0] = grid[0][0];  
     for (int i = 1; i < N; ++i) {  
       dp[i] = grid[0][i] + dp[i - 1];        
     }      
     for (int i = 1; i < M; ++i) { // row  
       dp[0] += grid[i][0];  
       for (int j = 1; j < N; ++j) { // col  
         dp[j] = min(dp[j - 1], dp[j]) + grid[i][j];  
       }  
     }  
     return dp[N - 1];  
   }  
 };  



Pascal's Triangle II

来源:Leetcode

原帖:https://oj.leetcode.com/problems/pascals-triangle-ii/

题目:
Given an index k, return the kth row of the Pascal's triangle. For example, given k = 3, Return [1,3,3,1].
Note: Could you optimize your algorithm to use only O(k) extra space?

代码:
 class Solution {  
 public:  
   vector<int> getRow(int rowIndex) {  
     vector<int> res(rowIndex + 1, 1);  
     for (int i = 1; i <= rowIndex; ++i) {  
       for (int j = i - 1; j >= 1; --j) {  
         res[j] += res[j - 1];  
       }  
     }  
     return res;  
   }  
 };  


Pascal's Triangle I

来源:Leetcode

原帖:https://oj.leetcode.com/problems/pascals-triangle/

题目:
Given numRows, generate the first numRows of Pascal's triangle.
For example, given numRows = 5,
Return
 [
      [1],
     [1,1]
    [1,2,1],
   [1,3,3,1],
  [1,4,6,4,1]
 ]

代码:
 class Solution {  
 public:  
   vector<vector<int> > generate(int numRows) {  
     vector<vector<int> > res(numRows);  
     for (int i = 0; i < numRows; ++i) {  
       res[i].push_back(1);  
       for (int j = 1; j < i; ++j) {  
         res[i].push_back(res[i - 1][j - 1] + res[i - 1][j]);  
       }  
       if (i >= 1) {  
        res[i].push_back(1);  
       }  
     }  
     return res;  
   }  
 };  

Triangle

来源:Leetcode

原帖:https://oj.leetcode.com/problems/triangle/

题目:
Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below. For example, given the following triangle
 [
    [2],
   [3,4],
  [6,5,7],
 [4,1,8,3]
 ]
The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11).
Note:
Bonus point if you are able to do this using only O(n) extra space, where n is the total number
of rows in the triangle.

Solution: Note that there are n elements in the n-th row (n starts from 1).
           1. DFS. (Time Limit Exceeded for large test data).
           2. DP. Do not need additional spaces (happen in-place).
           3. DP. O(n) space (If the input 'triangle' can not be changed).

代码:
 class Solution {  
 public:  
   //top -> bottom  
   int minimumTotal(vector<vector<int>> &triangle) {  
     int res = INT_MAX;  
     minimumTotalHelper(triangle, 0, res, 0, 0);  
     return res;  
   }  
   
   void minimumTotalHelper(vector<vector<int>> &triangle, int partSum, int &res, int deep, int pos) {  
     if (deep == triangle.size()) {  
       res = min(res, partSum);  
       return;  
     }  
     // 'pos' start position at level 'deep'  
     for (int i = pos; i < triangle[deep].size() && i <= pos + 1; ++i) {  
       minimumTotalHelper(triangle, partSum + triangle[deep][i], res, deep + 1, i);  
     }  
   }  
 };  
   
 class Solution {  
 public:  
   int minimumTotal(vector<vector<int>> &triangle) {  
     // bottom to up  
     for (int i = triangle.size() - 2; i >= 0; --i) {  
       for (int j = 0; j < i + 1; ++j) {  
         triangle[i][j] = triangle[i][j] + min(triangle[i + 1][j], triangle[i + 1][j + 1]);        
       }  
     }  
     return triangle[0][0];  
   }  
 };  
   
 class Solution {  
 public:  
   //Version 3: dp[n], bottom to up  
   int minimumTotal(vector<vector<int>> &triangle) {  
     int N = triangle.size();  
     vector<int> dp(N, 0);  
     for (int i = 0; i < N; ++i) {  
       dp[i] = triangle[N - 1][i];  
     }   
     for (int i = N - 2; i >= 0; --i) {  
       for (int j = 0; j < i + 1; ++j) {  
         dp[j] = triangle[i][j] + min(dp[j], dp[j + 1]);  
       }  
     }  
     return dp[0];  
   }  
 };  
   

Word Break II

来源:Leetcode

原帖:http://oj.leetcode.com/problems/word-break-ii/

题目:
Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each word is a valid dictionary word. Return all such possible sentences.
For example, given s = "catsanddog", dict = ["cat", "cats", "and", "sand", "dog"].
A solution is ["cats and dog", "cat sand dog"].

代码:
 class Solution {  
 public:  
   //Version 1: DFS  
   vector<string> wordBreak(string s, unordered_set<string> &dict) {  
     vector<string> res;  
     if (!wordBreakPossible(s, dict)) { // timeout if not check this! TLE  
       return res;   
     }  
     wordBreakHelper(s, dict, 0, "", res);  
     return res;  
   }  
     
   void wordBreakHelper(const string &s, unordered_set<string> &dict,   
            int start, string sentence, vector<string> &res) {  
     if (start == s.size()) {  
       res.push_back(sentence);  
       return;  
     }  
     if (start != 0) {  
       sentence.push_back(' '); // gap between words        
     }  
   
     for (int i = start; i < s.size(); ++i) {  
       string word = s.substr(start, i - start + 1);  
       if (dict.find(word) == dict.end()) {  
         continue;  
       }  
       wordBreakHelper(s, dict, i+1, sentence + word, res);  
     }  
   }  
     
   bool wordBreakPossible(const string &s, const unordered_set<string> &dict) {  
     int N = s.size();  
     vector<bool> canBreak(N+1, false);  
     canBreak[0] = true;  
     for (int i = 1; i <= N; ++i) {  
       for (int j = i - 1; j >= 0; --j) {  
         if (canBreak[j] && dict.find(s.substr(j, i - j)) != dict.end()) {  
           canBreak[i] = true;  
           break;  
         }  
       }  
     }  
     return canBreak[N];  
   }  
 };  
   
   
 class Solution {  
 public:  
   //Version 2: dp: map<string, vector<string> >  
   typedef unordered_map<string, vector<string> > MAP;  
   vector<string> wordBreak(string s, unordered_set<string> &dict) {  
     MAP map;  
     return wordBreak(s, dict, map);  
   }  
     
   vector<string> wordBreak(string s, unordered_set<string> &dict, MAP &map) {  
     vector<string> result;  
     if (s.size() == 0) return result;  
     if (map.find(s) != map.end()) { // memory search  
       return map[s];  
     }  
     for (int len = 1; len <= s.size(); ++len) {  
       string prefix = s.substr(0, len);  
       if (dict.find(prefix) != dict.end()) {  
         if (prefix.size() == s.size()) {  
           result.push_back(s);  
         } else {  
           string post = s.substr(len); // (pos, len)   
           vector<string> items = wordBreak(post, dict, map);     
           for (int i = 0; i < items.size(); ++i) {  
             string item = prefix + " " + items[i];  
             result.push_back(item);  
           }  
         }  
       }  
     }  
       
     map[s] = result;  
     return result;  
   }  
 };  


Word Break I

来源:Leetcode

原帖:http://oj.leetcode.com/problems/word-break/

题目:
Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words.
For example, given
s = "leetcode",
dict = ["leet", "code"].
Return true because "leetcode" can be segmented as "leet code".

代码:
 class Solution {  
 public:  
   void getMaxMinLength(unordered_set<string> &dict, int &maxLength, int &minLength) {  
     maxLength = INT_MIN;  
     minLength = INT_MAX;  
     for (auto elem : dict) {  
       maxLength = max(maxLength, elem.size());  
       minLength = min(minLength, elem.size());  
     }  
   }  
   
   bool wordBreak(string s, unordered_set<string> &dict) {  
     int N = s.size();  
     vector<bool> canBreak(N + 1, false);  
     canBreak[0] = true;  
     int maxLength, minLength;  
     getMaxMinLength(dict, maxLength, minLength);  
     for (int i = 1; i <= N; ++i) {  
       for (int j = i - minLength; j >= 0 && j >= i - maxLength; --j) {  
         if (canBreak[j] && dict.find(s.substr(j, i-j)) != dict.end()) {  
           canBreak[i] = true;  
           break;  
         }  
       }  
     }  
     return canBreak[N];  
   }  
 };  

Climbing Stairs

来源:Leetcode

原帖:http://oj.leetcode.com/problems/climbing-stairs/

题目:
You are climbing a stair case. It takes n steps to reach to the top. Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?
Solution: Climd one step from last stair or climb 2 steps from the last last stair.
Fibnacacci number.

代码:
 class Solution {  
 public:  
   int climbStairs(int n) {  
     int last = 1;  
     int lastlast = 1;  
     for (int i = 2; i <= n; i++) {  
       int step = last + lastlast;  
       lastlast = last;  
       last = step;  
     }  
     return last;  
   }  
 };  
   
 // {{1,1}, {1,0}} ^ n = {{f(n), f(n-1)}, {f(n-1), f(n-2)}};  
 class Solution {  
 public:  
   void multiply(int a[2][2], int b[2][2]) {  
     int c[2][2] = {0};  
     for (int i = 0; i < 2; ++i) {  
       for (int j = 0; j < 2; ++j) {  
         for (int k = 0; k < 2; ++k) {  
           c[i][j] += a[i][k] * b[k][j];  
         }  
       }  
     }  
     for (int i = 0; i < 2; ++i) {  
       for (int j = 0; j < 2; ++j) {  
         a[i][j] = c[i][j];  
       }  
     }  
   
   }  
   
   void power(int a[2][2], int n) {  
     if (n <= 1) return;  
     int c[2][2] = {{1,1}, {1,0}};  
     power(a, n/2);  
     multiply(a,a);  
     if (n % 2 == 0) return;  
     multiply(a, c);  
   }  
   
   int climbStairs(int n) {  
     if (n == 1) return 1;  
     int matrix[2][2] = {{1, 1}, {1, 0}};  
     power(matrix, n);  
     return matrix[0][0];  
   }  
 };  
   


Unique Paths II

来源:Leetcode

原帖:http://oj.leetcode.com/problems/unique-paths-ii/

题目:
Follow up for "Unique Paths":
Now consider if some obstacles are added to the grids. How many unique paths would there be?
An obstacle and empty space is marked as 1 and 0 respectively in the grid.
For example,
There is one obstacle in the middle of a 3x3 grid as illustrated below.
 [
  [0,0,0],
  [0,1,0],
  [0,0,0]
 ]
The total number of unique paths is 2.
Note: m and n will be at most 100.

代码:
 class Solution {  
 public:  
   int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid) {  
     int m = obstacleGrid.size(), n = obstacleGrid[0].size();  
     int dp[m][n];  
     if (obstacleGrid[0][0] == 1) return 0;  
     dp[0][0] = 1;  
     for (int i = 1; i < m; i++)  
       dp[i][0] = obstacleGrid[i][0] == 1 ? 0 : dp[i - 1][0];        
     for (int j = 1; j < n; j++)  
       dp[0][j] = obstacleGrid[0][j] == 1 ? 0 : dp[0][j - 1];        
     for (int i = 1; i < m; i++) {  
       for (int j = 1; j < n; j++) {  
         dp[i][j] = obstacleGrid[i][j] == 1 ? 0: dp[i - 1][j] + dp[i][j - 1];                
       }  
     }   
     return dp[m - 1][n - 1];  
   }  
 };  
   
 // space complexity O(n).   
 class Solution {  
 public:  
   int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid) {  
     if (obstacleGrid.size() == 0 || obstacleGrid[0].size() == 0) return 0;  
     int m = obstacleGrid.size(), n=obstacleGrid[0].size();  
     vector<int> dp(n + 1, 0);  
     dp[1] = obstacleGrid[0][0] == 1 ? 0 : 1;  
     for (int i = 0; i < m; i++) {  
       for (int j = 1; j <= n; j++){  
         dp[j] = obstacleGrid[i][j-1] == 1 ? 0 : dp[j] + dp[j-1];  
       }  
     }  
     return dp[n];  
   }  
 };  


Unique Paths I

来源:Leetcode

原帖:http://oj.leetcode.com/problems/unique-paths/

题目:
A robot is located at the top-left corner of a m x n grid. The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below). How many possible unique paths are there?
Solution:
Dynamic programming. UP(i,j) = UP(i-1,j) + UP(i,j-1).

代码:
 class Solution {  
 public:  
   int uniquePaths(int m, int n) {  
     int dp[m][n];  
     for (int i = 0; i < m; i++) {  
       dp[i][0] = 1;  
     }    
     for (int j = 0; j < n; j++) {  
       dp[0][j] = 1;  
     }    
     for (int i = 1; i < m; i++) {  
       for (int j = 1; j < n; j++) {  
         dp[i][j] = dp[i - 1][j] + dp[i][j - 1];  
       }  
     }  
     return dp[m - 1][n - 1];  
   }  
 };  
   
 class Solution {  
 public:  
   // 滚动数组  
   int uniquePaths(int m, int n) {  
     int dp[2][n];  
     for (int i = 0; i < n; ++i) {  
       dp[0][i] = 1;  
     }  
     dp[1][0] = 1;  
     int row = 0;  
     for (int i = 1; i < m; ++i) {  
       row = !row;  
       for (int j = 1; j < n; ++j) {  
         dp[row][j] = dp[!row][j] + dp[row][j - 1];  
       }  
     }  
     return dp[row][n - 1];  
   }  
 };  
   
 class Solution {  
 public:  
   int uniquePaths(int m, int n) {  
     vector<int> dp(n, 1);  
     for (int i = 1; i < m; ++i) {  
       for (int j = 1; j < n; ++j) {  
         dp[j] = dp[j-1] + dp[j];  
       }  
     }  
     return dp[n-1];  
   }  
 };  
   


Sunday, May 17, 2015

Jump Game II

来源:Leetcode

原帖:https://oj.leetcode.com/problems/jump-game-ii/

题目:
Given an array of non-negative integers, you are initially positioned at the first index of the array.
Each element in the array represents your maximum jump length at that position. Your goal is to reach the last index in the minimum number of jumps.
For example:
Given array A = [2,3,1,1,4]. The minimum number of jumps to reach the last index is 2. (Jump 1 step from index 0 to 1, then 3 steps to the last index.)
Solution: Jump to the position where we can jump farthest (index + A[index]) next time.

代码:
   
 class Solution {  
 public:  
   // greedy method  
   int jump(int A[], int n) {  
     int start = 0, steps = 0;  
     while (start < n - 1) {  
       steps++;  
       if (start + A[start] >= n - 1)  
         return steps;          
       int next = start;  
       for (int i = start + 1; i <= start + A[start]; ++i) {  
         if (i + A[i] >= next + A[next])  
           next = i;  
       }  
       if (next == start) // cannot jump over the end  
         return INT_MAX;   
       start = next;  
     }  
   }  
 };  


Jump Game I

来源:Leetcode

原帖:http://oj.leetcode.com/problems/jump-game/

题目:
Given an array of non-negative integers, you are initially positioned at the first index of the array. Each element in the array represents your maximum jump length at that position. Determine if you are able to reach the last index.
For example:
A = [2,3,1,1,4], return true.
A = [3,2,1,0,4], return false.
Solution: Updated solution: try every reachable index.

代码:
 class Solution {  
 public:  
   bool canJump(int A[], int n) {  
     int start = 0, farthest = 0; // farthest: 最多可以到达的状态  
     while (start <= farthest && farthest < n - 1) {  
       farthest = max(farthest, start + A[start]);  
       start++;  
     }  
     return farthest >= (n-1);  
   }  
 };