算法整理-动态规划和Two Pointers

Posted cookcoder-mr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法整理-动态规划和Two Pointers相关的知识,希望对你有一定的参考价值。

一 .   最长子序列和

  令dp[i] 为以i结尾的最长子序列和。dp[i] = max(dp[i-1] + nums[i], nums[i])。 同时纪录dp[i]遍历结果的中的最大值。需要三个变量,纪录上一个dp,  当前dp和最大的dp.

class Solution 
public:
    int maxSubArray(vector<int>& nums) 
        int len = nums.size();
        if (len == 0) return 0;
        int pre = nums[0];
        int re;
        int max_re = pre;
        for (int i = 1; i < len; i++) 
            if (nums[i] > pre + nums[i]) re = nums[i];
            else re = pre + nums[i];
            pre = re;
            if (re > max_re) max_re = re;
        
        return max_re;
    
;

 

二. House RobberI

   只有dp(n) = max(dp(n-1), notakedp(n-1) + nums[i]))

class Solution // DP
public:  // dp(n) = max(dp(n-1), notakedp(n-1) + nums[i]) 第i个没抢, 抢了
    int rob(vector<int>& nums) 
        int take = 0;
        int notake = 0;
        int dp = 0;
        for(int i = 0; i < nums.size(); i++) 
            take = notake + nums[i];
            notake = dp;
            dp = max(take, notake);
        
        return dp;
    
;

   更难的问题。是一个环,第一家和最后一家也不能抢。则这个问题可以求解为0,1, .. n-1, 的问题和1....n的问题,再求这个两个子数组情况下的最大的最优解。

 

三.  Maximal Square

https://www.cnblogs.com/grandyang/p/4550604.html

    动态规划问题,dp[i][j]表示以matrix[i][j]为右下角的最大的square的边长。则dp[i][j] = min(dp[i-1][j-1], dp[i][j-1], dp[i-1][j]) + 1;。。当然只有matrix[i][j]为‘1’时这个公式才生效。

 

class Solution 
public:
    int maximalSquare(vector<vector<char>>& matrix) 
        if (matrix.empty() || matrix[0].empty()) return 0;
        int m = matrix.size(), n = matrix[0].size(), res = 0;
        vector<vector<int>> dp(m, vector<int>(n, 0));
        for (int i = 0; i < m; ++i) 
            for (int j = 0; j < n; ++j) 
                if (i == 0 || j == 0) dp[i][j] = matrix[i][j] - ‘0‘;
                else if (matrix[i][j] == ‘1‘) 
                    dp[i][j] = min(dp[i - 1][j - 1], min(dp[i][j - 1], dp[i - 1][j])) + 1;
                
                res = max(res, dp[i][j]);
            
        
        return res * res;
    
;

 

四.  Maximal Rectangle  Histogram

https://www.cnblogs.com/grandyang/p/4322653.html

基于pointer的解法,依次找到局部最大值分别进行处理,处理方法为分别求出以局部最大值为右边,所有左边分别能构成的最大面积。  最终通过一个全局最大值返回最优解。

class Solution 
public:
    int largestRectangleArea(vector<int> &height) 
        int res = 0;
        for (int i = 0; i < height.size(); ++i) 
            if (i + 1 < height.size() && height[i] <= height[i + 1]) 
                continue;
            
            int minH = height[i];
            for (int j = i; j >= 0; --j) 
                minH = min(minH, height[j]);
                int area = minH * (i - j + 1);
                res = max(res, area);
            
        
        return res;
    
;

 

基于单调递增栈的解法

 在原始数组最右边加入一个0,单调递增依次进栈, 找到一个局部最大值,处理当前局部最大值前面所有比它小的数字。首先处理栈顶元素下标对应的高度,面积范围为以栈顶为高,范围为局部最大值为右边界(不包括), pop后的新的栈顶坐标为左边界(不包括)。

class Solution 
public:
    int largestRectangleArea(vector<int>& heights) 
        int res = 0;
        stack<int> st;
        heights.push_back(0);
        for (int i = 0; i < heights.size(); ++i) 
            while (!st.empty() && heights[st.top()] >= heights[i]) 
                int cur = st.top(); st.pop();
                res = max(res, heights[cur] * (st.empty() ? i : (i - st.top() - 1)));
            
            st.push(i);
        
        return res;
    
;

 

五:Maximal Reactangle

   类似于maximal square, 可以先构造一个新的二维数组,而后根据maximal histogram进行统计。

class Solution 
public:
    int maximalRectangle(vector<vector<char>>& matrix) 
        int m = matrix.size();
        if (m<1) return 0;
        int n = matrix[0].size();
        if (n<1) return 0;
        vector<vector<int>> matrix_int(m, vector<int>(n, 0));
        for (int i = 0; i < m; i++)
          for (int j = 0; j < n; j++) 
            matrix_int[i][j] = matrix[i][j] - ‘0‘;
            if (matrix_int[i][j] == 1) 
            if (i>0)
            matrix_int[i][j] += matrix_int[i-1][j];
            
            
        
       int max_re = INT_MIN;
       for (int i=0; i < m; i++) 
          int max_tmp = maxHist(matrix_int[i]);
          if (max_re < max_tmp) max_re = max_tmp;
          cout << max_tmp << endl;
       

      return max_re;
    

private:
   int maxHist(vector<int> nums) 
       int len = nums.size();
       nums.push_back(0);
       int max_area = 0;
       for (int i=0; i < len; i++)
           if(nums[i] > nums[i+1]) 
               int max_local = 0;
               int min_h = nums[i];
               if (i==0) max_local = nums[i];
               else 
                  for(int j = i; j >=0; j--) 
                    if (nums[j] < min_h)
                        min_h = nums[j];
                    
                    max_local = max(max_local, min_h * (i-j + 1));
                   
               
               if(max_local > max_area) max_area = max_local;
           
      
      return max_area;
   
;

 

六.  WordBreak

DP[i] 表示 s[0,1,2 ... i-1] 是否能wordbreak成功,dp[i] = dp[j] && substr[j, j+1, .... i-1]为在word dict中的某个字符串。其中  0<=j <= i-1, 能找到一个就为true。C++ string.str的用法,第一个为开始字符下标,第二个参数为字符串长度。

class Solution 
public:
    bool wordBreak(string s, vector<string>& wordDict) 
        int len = s.size();
        if (len < 1) return false;
        set<string> dict;
        vector<bool> flags(len+1, false);
        flags[0] = true;
        for (int i=0; i < wordDict.size(); i++)
            dict.insert(wordDict[i]);
        for (int i = 1; i<= len; i++) 
            for (int j=0; j<i; j++) 
               if(flags[j] == true && dict.count(s.substr(j, i - j)) > 0)   
                 flags[i] = true;
                 break;
               
            
        
        return flags[len];
    
;

 

以上是关于算法整理-动态规划和Two Pointers的主要内容,如果未能解决你的问题,请参考以下文章

动态规划分析总结——怎样设计和实现动态规划算法

数据结构与算法|讲解|动态规划一脸懵?看完之后轻松掌握!

动态规划的推法 谢谢

冲刺大厂每日算法&面试题,动态规划21天——第九天

冲刺大厂每日算法&面试题,动态规划21天——第五天

冲刺大厂每日算法&面试题,动态规划21天——第十三天