美文网首页动态规划
动态规划 && 贪婪算法

动态规划 && 贪婪算法

作者: YOLO哈哈哈 | 来源:发表于2019-01-17 06:44 被阅读4次

动态规划 && 贪婪算法

1· 剪绳子(14 剑指offer )
  • 需要先从 base case 开始寻找规律 ,绳子长度为 n(2 <=n<=58), 剪成m 段(2 <= m), 所以说
    以下是动态规划的解法: n = 1,2,3,4 是 base case
    转移方程式: res[i] = math.max(res[j] + res[ i - j] ) -> j from 1 to i / 2;
public static int maxProduceAfterCutting(int length) {
    if(length == 2)
        return 1;
    if(length == 3)
      return 2;
    if(length == 4)
      return 4;
    int [] res = new int[length + 1]; 
    res[0] = 1;
    res[1] = 1;
    res[2] = 2;
    res [3] = 3; 
    int max = 1; 
    for(int i = 4; i<=length; i++){
        for(int j = 1; j <= i/2; j++){
              int tmp = res[j] * res[ i - j];
              if(tmp > res[i])
                      res[i] = tmp ;
         }
    }
return res[length];
}
  • 以下是贪婪算法 的做法, 但是有3个数学的基本证明必须记住
  • 假设 ni >= 5 , 3 * ( ni - 3) > ni ? => 2ni > 9 ? 所以说 当 ni >= 5时,把3 切出来 可以乘机最大化
  • 当 ni = 4 时, 2* 2 > 3 * 1 , 当 ni = 4 时,把2 切出来,可以乘机最大化
  • 当 2 * 2* 2 < 3 * 3, 当既可以切 2个以上的3 ,又可以切2个以上的 2 时,把3 切出来 可以乘机最大化
public static int maxProduceAfterCutting(int length) {
    if(length == 2)
        return 1;
    if(length == 3)
      return 2;
    if(length == 4)
      return 2;
    int timesOf3 = length/3;
    /* 说明可以划出一个 4 */
    if(length - timesOf3 * 3 == 1){
        timesOf3 = timesOf3 -1 ;
    }
  int timesOf2 = (length - 3 * timesOf3) /2;
  return (int) Math.pow(3, timesOf3) * (int)Math.pow(2, timesOf2);
}
2· 匹配2个字符串的模式(19 剑指offer )
  • match pattern 的题型
/*
状态表示: f[i][j]  表示 s[i, ...] 和 p[j, ...] 相匹配
状态转移:
1.  p[j] 是正常字符, f[ i ][ j ] = s[i] = p[j] && f[i+1][j+1]
2.  p[j] 是‘ . ’, f[ i ][ j ] = f[ i+1][ j+1]
3. p[ j + 1 ] 是 ‘ * ’ , f[ i ][ j ] = f[ i ][ j+2] || f [i+1][ j ]
*/
class Solution {
     int n,m;
      int[][] f ;
    public boolean isMatch(String s, String p) {
        n = s.size();
        m = p.size();
        f = new int[n+1][m+1];
        for(int i=0; i<n+1; i++)
            for( int j =0; j< m+1; j++)
                    f[i][j] = -1;
        return dp(0,0,s,p);
    }

  public dp(int x, int y, String s, String p) {
      if(f[x][y] != null) return f[x][y];
      if( y == m )
            return f [x][y] = x == n;
  }
}
3.Two City Scheduling(1029.leetcode)
  • 方一 :用到了 PriorityQueue 的数据结构
public int twoCitySchedCost(int[][] costs) {
    int countA = 0;
    int countB = 0;
    int res = 0;
    for( int[] city : costs){
        int diff = Math.abs(city[0], city[1]);
        if(city[0] < city[1]){
            res += city[0];
            countA ++;
            pqA.offer(city[0]);
        } else {
          res += city[1];
          countB ++;
          pqB.offer(city[ 1])
        }
    } // for
    while( countA > countB) {
        res += pqA.poll();
        countA --;
        countB++;
    }
    while( countA < countB ){
        res += pqB.poll();
        countB --;
        countA++;
    }
     return res;
}
  • 方二 :用到了 DP 的思想

4. Uncrossed Lines(1035.leetcode)
  • dp 思想
public int maxUncrossedLines(int[] A, int[] B) {
    int m = A.length , n = B.length , dp[][] = new int[m + 1][ n + 1];
    for(int i = 11; i<= m ; i++){
        for( int j = 1; j<= n; j++){
            if( A[i - 1][j - 1] == B[i - 1][j - 1])
                dp[i][j] = 1 + dp[i -1 ][j - 1];
            else
                dp = Math.max( dp[i - 1][ j], dp[ i ][j - 1]);
        }
    }
   return dp[m][n];
}
5.Paint House( 256. leetcode)
  • easy 类型
  • 转移方程式:
    • paintCurrentRed = min(paintpreviousGreen , paintPreviousBlue) + costs[ i + 1][ 0 ];
public int minCost(int[][] costs){
    if(cost == null || cost.length ==0) return 0;
    int lastR = costs[0][0];
    int lastG = costs[0][1];
    int lastB = costs[0][2];
    for(int i = 1; i < costs.length ; i++){
        int curR = Math.min(lastG, lastB) + costs[i][0];
        int curG = Math.min(lasrR, lastB) + costs[i][1];
        int curB = Math.min(lastR, lastG) + costs[i][2];
        lastR = curR;
        lastG = curG;
        lastB = curB;
    }
    return   Math.min(lastR, lastG< lastB ? lastG : lastB);
}
6. House Robber(198. leetcode)
  • step 1. find recursion relation
    • rob(i) = Math.max( rob( i -2 )+ currentHouseV , rob( i -1));
  • step 2. recursive( top - down)
    converting the recurrent relation form step1 , 这个算法 重复跑 同样的 i 值 多次, 需要改进
public int rob( int[ ] nums){
    return rob( nums, nums.length - 1);
}
private int rob( int[ ] nums, int i){
    if( i < 0) return 0;
    return Math.max( rob( nums, i -2 ) + nums[i] , rob( nums, i -1 ) );
}
  • Step 3. Recursive + memo (top-down). 这里使用一个 array memo 来记录 i 值, runO(n) time. Space complexity O(n)
int [] memo ;
public int rob( int [] nums){
    memo = new int[ nums.length + 1];
    Arrays.fill(memo , -1);
    return rob( nums, nums.length -1 );
}
private int rob( int[] nums, int i){
    if(i < 0) return 0;
    if( memo[i] >= 0) return memo[i];
    int result = Math.max( rob( i -2) + nums[ i]  , rob(i -1));
    memo[i] = result;
    return result;
}
  • Step 4. Iterative + memo (bottom-up)
    用for loop 而不用 recurrsion call
public int rob(int[] nums){
    if (nums.length == 0) reutrn 0;
    int[ ] memo = new int[ nums.length + 1];
    memo[0] = 0;
    memo[1] = nums[0];
    for(int i= 1; i < nums.length ; i ++){
        int value = nums[i];
        memo[ i+ 1] = Math.max( memo[i] , memo[ i -1]+ value );
    }
  return memo[nums.length];
}
  • Step 5. Iterative + 2 variables (bottom-up)
    因为前面只用了 memo[ i] and memo[ i -1] , so going just 2 steps back. We can hold them in 2 variables instead. This optimization is met in Fibonacci sequence creation and some other problems [to paste links]
/* the order is : prev2 , prev2 , num*/
public int rob(int[] nums){
    if(nums == null || nums.length == 0) return 0;
    int prev1 = 0; 
    int prev2 = 0; 
    for(int num : nums){
          int tmp = prev1;
          
     }
}
7.Paint Fence( 276.leetcode)

https://www.youtube.com/watch?time_continue=3&v=deh7UpSRaEY


相关文章

网友评论

    本文标题:动态规划 && 贪婪算法

    本文链接:https://www.haomeiwen.com/subject/qsrbdqtx.html