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

动态规划 && 贪婪算法

作者: 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