动态规划强化

动态规划空间优化   滚动数组

1 House Robber

    public long houseRobber(int[] a) {
        if (a == null || a.length == 0) {
            return 0;
        }
        if (a.length == 1) {
            return a[0];
        }
        if (a.length == 2) {
            return Math.max(a[0], a[1]);
        }
        long[] res = new long[a.length];
        res[0] = a[0];
        res[1] = Math.max(a[0], a[1]);
        for (int i = 2; i < a.length; i++) {
            res[i] = Math.max(res[i - 1], res[i - 2] + a[i]);
        }
        return res[a.length - 1];
     }
View Code
    public long houseRobber(int[] a) {
        if (a == null || a.length == 0) {
            return 0;
        }
        if (a.length == 1) {
            return a[0];
        }
        if (a.length == 2) {
            return Math.max(a[0], a[1]);
        }
        long[] res = new long[2];
        res[0] = a[0];
        res[1] = Math.max(a[0], a[1]);
        for (int i = 2; i < a.length; i++) {
            res[i % 2] = Math.max(res[(i - 1) % 2], res[(i - 2) % 2] + a[i]);
        }
        return res[(a.length - 1) % 2];
     }
View Code

2 Maximal Square

   public int maxSquare(int[][] matrix) {
        int m = matrix.length;
        int n = matrix[0].length;
        int max = 0;
        int[][] dp = new int[m][n];
        for (int i = 0; i < m; i++) {
            dp[i][0] = matrix[i][0];
            max = Math.max(max, dp[i][0]);
            for (int j = 1; j < n; j++) {
                if (i == 0) {
                    dp[i][j] = matrix[i][j];
                } else {
                    if (matrix[i][j] == 1) {
                        dp[i][j] = Math.min(dp[i - 1][j - 1], Math.min(dp[i][j - 1], dp[i - 1][j])) + 1;
                    }
                }
                max = Math.max(max, dp[i][j]);
            }
        }
        return max * max;
    }
View Code
    public int maxSquare(int[][] matrix) {
        int m = matrix.length;
        int n = matrix[0].length;
        int max = 0;
        int[][] dp = new int[2][n];
        for (int i = 0; i < m; i++) {
            dp[i % 2][0] = matrix[i][0];
            max = Math.max(max, dp[i % 2][0]);
            for (int j = 1; j < n; j++) {
                if (i == 0) {
                    dp[i % 2][j] = matrix[i][j];
                } else {
                    if (matrix[i][j] == 1) {
                        dp[i % 2][j] = Math.min(dp[(i - 1) % 2][j - 1], Math.min(dp[i % 2][j - 1], dp[(i - 1) % 2][j])) + 1;
                    } else {
                        dp[i % 2][j] = 0;
                    }
                }
                max = Math.max(max, dp[i % 2][j]);
            }
        }
        return max * max;
View Code

局部最 优 和全局最 优实现时间优

1 Maximum Subarray

    public int maxSubArray(int[] nums) {
        // write your code here
        if (nums == null || nums.length == 0) {
            return 0;
        }
        int[] local = new int[nums.length];
        int global = nums[0];
        local[0] = nums[0];
        
        for (int i = 1; i < nums.length; i++) {
            local[i] = Math.max(local[i - 1] + nums[i], nums[i]);
            global = Math.max(global, local[i]);
        }
        
        return global;
    }
View Code

2 Maximum Product Subarray

    public int maxProduct(int[] nums) {
        // write your code here
        if (nums == null || nums.length == 0) {
            return 0;
        }
        if (nums.length == 1) {
            return nums[0];
        }
        int max_local = nums[0];
        int min_local = nums[0];
        int global = nums[0];
        for (int i = 1; i < nums.length; i++) {
            int max_copy = max_local;
            max_local = Math.max(Math.max(nums[i] * max_local, nums[i]), nums[i] * min_local);
            min_local = Math.min(Math.min(nums[i] * max_copy, nums[i]), nums[i] * min_local);
            global = Math.max(global, max_local);
        }
        return global;
    }
View Code

3 Best Time to Buy and Sell Stock

    public int maxProfit(int k, int[] prices) {
        // write your code here
        if (k >= prices.length) {
            int profit = 0;
            for (int i = 1; i < prices.length; i++) {
                if (prices[i] > prices[i - 1]) {
                    profit += prices[i] - prices[i - 1];
                }
            }
            return profit;
        }
        int[] local = new int[k + 1];
        int[] global = new int[k + 1];
        for (int i = 0; i < prices.length - 1; i++) {
            int diff = prices[i + 1] - prices[i];
            for (int j = k; j > 0; j--) {
                local[j] = Math.max(global[j - 1] + Math.max(diff, 0), local[j] + diff);
                global[j] = Math.max(global[j], local[j]);
            }
        }
        return global[k];
    }
View Code

 记忆化搜索

本质上:动态规划
动态规划就是解决了重复计算的搜索
动态规划的实现方式:
1. 循环(从小到大递推)
2. 记忆化搜索(从大到小搜索) -> 万金油

什么 时 候用 记忆 化搜索?
1. 状态转移特别麻烦,不是顺序性。
2. 初始化状态不是很容易找到

For I = 1 ->n
dp[i] = search (i)
// 搜索
int search(int i)
{
if(visit[i] == 1)
return dp[i];
if(smallest state)
{
set smallest state
} else {
// to update (i,) , we might need other state
// such as (i-1), (i+1)
for other state
update dp[i] = max(search(i-1) , search(i+1))
}
visit[i] = 1;
return dp[i];
}
View Code

1 Longest Increasing continuous Subsequence 2D

class Solution {

    static int n = 0;
    static int m = 0;
    public int longestIncreasingContinuousSubsequenceII(int[][] a) {
        
        if (a == null || a.length == 0) {
            return 0;
        }
        m = a.length;
        n = a[0].length;
        int[][] dp = new int[m][n];
        boolean[][] flag = new boolean[m][n];
        int max = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                dp[i][j] = search(i, j, a, dp, flag);
                max = Math.max(max, dp[i][j]);
            }
        }
        return max;
    }
    int[] dx = {-1, 1, 0, 0};
    int[] dy = {0, 0, 1, -1};
    private int search(int i, int j, int[][] a, int[][] dp, boolean[][] flag) {
        // TODO Auto-generated method stub
        if (flag[i][j]) {
            return dp[i][j];
        }
        int res = 1;
        for (int k = 0; k < 4; k++) {
            int x = i + dx[k];
            int y = j + dy[k];
            if (x >= 0 && x < m && y >= 0 && y < n) {
                if (a[x][y] > a[i][j]) {
                    res = Math.max(res, search(x, y, a, dp, flag) + 1);
                }
            }
        }
        flag[i][j] = true;
        dp[i][j] = res;
        return res;
    }
}
View Code

博弈 类

1 Coins in a line

    public boolean firstWillWin(int n) {
        // write your code here
        int[] dp = new int[n + 1];
        return search(n, dp);
    }
    public boolean search(int n, int[] dp) {
        if (dp[n] != 0) {
            if (dp[n] == 1) {
                return false;
            } else {
                return true;
            }
        }
        if (n <= 0) {
            dp[n] = 1;
        } else if (n == 1) {
            dp[n] = 2;
        } else if (n == 2) {
            dp[n] = 2;
        } else if (n == 3) {
            dp[n] = 1;
        } else {
            if (search(n - 2, dp) && search(n - 3, dp) ||
                search(n - 3, dp) && search(n - 4, dp)) {
                    dp[n] = 2;
                } else {
                    dp[n] = 1;
                }
        }
        return dp[n] == 2;
    }
View Code

2 Coins in a line 2

    public boolean firstWillWin(int[] values) {
        // write your code here
        int[] dp = new int[values.length + 1];
        boolean[] flag = new boolean[values.length + 1];
        int sum = 0;
        for (int i : values) {
            sum += i;
        }
        search(values.length, values, dp, flag);
        return dp[values.length] * 2 > sum;
    }
    public int search(int n, int[] values, int[] dp, boolean[] flag) {
        if (flag[n]) {
            return dp[n];
        } 
        flag[n] = true;
        int len = values.length;
        if (n == 0) {
            dp[n] = 0;
        } else if (n == 1) {
            dp[n] = values[len - 1];
        } else if (n == 2) {
            dp[n] = values[len - 1] + values[len - 2]; 
        } else if (n == 3) {
            dp[n] = values[len - 2] + values[len - 3];
        } else {
            dp[n] = Math.max(
                Math.min(search(n - 2, values, dp, flag), search(n - 3, values, dp, flag)) + values[len - n],
                Math.min(search(n - 3, values, dp, flag), search(n - 4, values, dp, flag)) + values[len - n] + values[len - n + 1]
                );
        }
        return dp[n];
    }
View Code

3 Coins in a line 2

public boolean firstWillWin(int[] values) {

    int n = values.length;
    int[][] dp = new int[n + 1][n + 1];
    boolean[][] flag = new boolean[n + 1][n + 1];
    
    int sum = 0;
    for (int i : values) {
        sum += i;
    }
    return search(0, n - 1, values, dp, flag) * 2 > sum;
}

private int search(int i, int j, int[] val, int[][] dp, boolean[][] flag) {
    // TODO Auto-generated method stub
    if (flag[i][j]) {
        return dp[i][j];
    }
    flag[i][j] = true;
    if (i > j) {
        dp[i][j] = 0;
    } else if (i == j) {
        dp[i][j] = val[i];
    } else if (i + 1 == j) {
        dp[i][j] = Math.max(val[i], val[j]);
    } else {
        int pick_left = Math.min(dp[i + 2][j], dp[i + 1][j - 1]) + val[i];
        int pick_right = Math.min(dp[i + 1][j - 1], dp[i][j - 2]) + val[j];
        dp[i][j] = Math.max(pick_left, pick_right);
    }
    return dp[i][j];
}
View Code

区 间类Dp

1 Stone-Game

有一个石子归并的游戏。最开始的时候,有n堆石子排成一列,目标是要将所有的石子合并成一堆。合并规则如下:

每一次可以合并相邻位置的两堆石子
每次合并的代价为所合并的两堆石子的重量之和
求出最小的合并代价。

您在真实的面试中是否遇到过这个题? Yes
样例
对于石子序列:[4, 1, 1, 4](每个数代表这堆石子的重量),最优合并方案下,合并代价为 181. 合并第2堆和第3堆 => [4, 2, 4], 代价 +2
2. 合并前两堆 => [6, 4],代价 +6
3. 合并剩下的两堆 => [10],代价 +10
其他例子:
[1, 1, 1, 1] 代价为 8
[4, 4, 5, 9] 代价为 43
View Code
    public int stoneGame(int[] a) {
        if (a == null || a.length == 0) {
            return 0;
        }
        int n = a.length;
        int[][] sum = new int[n][n];
        int[][] dp = new int[n][n];
        boolean[][] flag = new boolean[n][n];
        for (int i = 0; i < n; i++) {
            sum[i][i] = a[i];
            for (int j = i + 1; j < n; j++) {
                sum[i][j] = sum[i][j + 1] + a[j];
            }
        }
        return search(0, n - 1, sum, dp, flag);
    }

    private int search(int i, int j, int[][] sum, int[][] dp, boolean[][] flag) {
        // TODO Auto-generated method stub
        if (flag[i][j]) {
            return dp[i][j];
        }
        if (i == j) {
            flag[i][j] = true;
            return dp[i][j];
        }
        flag[i][j] = true;
        for (int k = i; k < j; k++) {
            dp[i][j] = Math.min(dp[i][j], search(i, k, sum, dp, flag) + search(k + 1, j, sum, dp, flag) + sum[i][j]);
        }
        return dp[i][j];
    }
View Code

2  312. Burst Balloons

public int maxCoins(int[] nums) {
        int n = nums.length;
        int[] newnum = new int[n + 2];
        newnum[0] = 1;
        for (int i = 0; i < n; i++) {
            newnum[i + 1] = nums[i];
        }
        newnum[n + 1] = 1;
        int[][] dp = new int[n + 2][n + 2];
        return search(newnum, 0, n + 1, dp);
    }
    int search(int[] nums, int l, int r, int[][] dp) {
        if (dp[l][r] != 0) {
            return dp[l][r];
        }
        if (l + 2 == r) {
            dp[l][r] = nums[l] * nums[l + 1] * nums[r];
            return dp[l][r];
        }
        for (int i = l + 1; i < r; i++) {
            dp[l][r] = Math.max(dp[l][r], search(nums, l, i, dp) + search(nums, i, r, dp) + nums[l] * nums[r] * nums[i]);
        }
        return dp[l][r];
    }
View Code

 背包问题

1 Backpack

    public int backPack(int n, int[] a) {
        // write your code here
        int m = a.length;
        boolean[][] dp = new boolean[m + 1][n + 1];
        for (int i = 0; i <= m; i++) {
            dp[i][0] = true;
        }
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                dp[i][j] = dp[i - 1][j] || j >= a[i - 1] && dp[i - 1][j - a[i - 1]];
            }
        }
        for (int i = n; i >= 1; i--) {
            if (dp[m][i]) {
                return i;
            }
        }
        return 0;
    }
View Code

2 Backpack II

    public int backPackII(int n, int[] a, int[] v) {
        // write your code here
        int m = a.length;
        int[][] dp = new int[m + 1][n + 1];
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                dp[i][j] = Math.max(dp[i - 1][j], j >= a[i - 1] ? dp[i - 1][j - a[i - 1]] + v[i - 1]: 0); 
            }
        }
        int max = 0;
        for (int i = n; i >= 1; i--) {
            max = Math.max(dp[m][i], max);
        }
        return max;
    }
View Code
原文地址:https://www.cnblogs.com/whesuanfa/p/7448839.html