动态规划(刷题)

定义:动态规划是分治思想的延伸,通俗一点来说就是大事化小,小事化无的艺术。在将大问题化解为小问题的分治过程中,保存对这些小问题已经处理好的结果,并供后面处理更大规模的问题时直接使用这些结果。

动态规划具备了以下三个特点

  • 把原来的问题分解成了几个相似的子问题。
  • 所有的子问题都只需要解决一次。
  • 储存子问题的解。
     

动态规划的本质,是对问题状态的定义和状态转移方程的定义(状态以及状态之间的递推关系)

动态规划问题一般从以下四个角度考虑:

  1. 状态定义
  2. 状态间的转移方程定义
  3. 状态的初始化
  4. 返回结果
     

适用场景:最大值/最小值, 可不可行, 是不是,方案个数

第1题 Fibonacci斐波那契
答案一:使用递归(通过不了,因为这道题考的就不是递归,递归复杂度高,所以要用动态规划思想来做)

class Solution {
    public int fib(int n) {
        if (n == 0) {
            return 0;
        }
        if (n == 1) {
            return 1;
        }
        return fib(n - 1) + fib(n - 2);
    }
}

 答案二:

class Solution {
    public final int MOD = 1000000007;

    public int fib(int n) {
        int[] arr = new int[n + 1];
        if (n < 2) {
            arr[n] = n;
        } else {
            arr[0] = 0;
            arr[1] = 1;
        }
        for (int i = 2; i <= n; i++) {
            arr[i] = (arr[i - 1] + arr[i - 2]) % MOD;
        }
        return arr[n];
    }
}

答案三:对答案二做空间上的优化

class Solution {
    public final int MOD = 1000000007;

    public int fib(int n) {
        if (n < 2) {
            return n;
        }
        int f = 0;
        int f1 = 0;
        int f2 = 1;
        for (int i = 2; i <= n; i++) {
            f = (f1 + f2) % MOD;
            f1 = f2;
            f2 = f;
        }
        return f;
    }
}

第2题 字符串分割(Word Break)字符串分割

class Solution {
    public boolean wordBreak(String s, Set<String> dict) {
        boolean[] canBreak = new boolean[s.length() + 1];

        canBreak[0] = true;

        for (int i = 1; i <= s.length(); i++) {
            for (int j = 0; j < i; j++) {
                if (canBreak[j] && dict.contains(s.substring(j, i))) {
                    canBreak[i] = true;
                    break;
                }
            }
        }
        return canBreak[s.length()];
    }
}

第3题 三角矩阵(Triangle)三角矩阵

答案一:自顶向下

class Solution {
    public int minimumTotal(ArrayList<ArrayList<Integer>> triangle) {
        if (triangle.isEmpty()) {
            return 0;
        }

        List<List<Integer>> minPathSum = new ArrayList<>();

        for (int i = 0; i < triangle.size(); i++) {
            minPathSum.add(new ArrayList<>());
        }

        minPathSum.get(0).add(triangle.get(0).get(0));

        for (int i = 1; i < triangle.size(); i++) {
            int curSum = 0;
            for (int j = 0; j <= i; j++) {
                if (j == 0) {
                    curSum = minPathSum.get(i - 1).get(0);
                } else if (j == i) {
                    curSum = minPathSum.get(i - 1).get(j - 1);
                } else {
                    curSum = Math.min(minPathSum.get(i - 1).get(j), minPathSum.get(i - 1).get(j - 1));
                }
                minPathSum.get(i).add(triangle.get(i).get(j) + curSum);
            }
        }

        int size = triangle.size();

        int allMin = minPathSum.get(size - 1).get(0);

        for (int i = 1; i < size; i++) {
            allMin = Math.min(allMin, minPathSum.get(size - 1).get(i));
        }

        return allMin;
    }
}

答案二:自底向上

class Solution {
    public int minimumTotal(ArrayList<ArrayList<Integer>> triangle) {
        if (triangle.isEmpty()) {
            return 0;
        }

        ArrayList<ArrayList<Integer>> minPathSum = new ArrayList<>(triangle);

        int row = minPathSum.size();

        for (int i = row - 2; i >= 0; i--) {
            for (int j = 0; j <= i; j++) {
                int curSum = Math.min(triangle.get(i+1).get(j),triangle.get(i+1).get(j+1)) + triangle.get(i).get(j);
                minPathSum.get(i).set(j,curSum);
            }
        }
        return minPathSum.get(0).get(0);
    }
}

第4题 路径总数(Unique Paths)路径总数

答案:

class Solution {
    public int uniquePaths(int m, int n) {
        List<List<Integer>> pathNum = new ArrayList<>();

        for (int i = 0; i < m; i++) {
            pathNum.add(new ArrayList<>());
            pathNum.get(i).add(1);
        }

        for (int i = 1; i < n; i++) {
            pathNum.get(0).add(1);
        }

        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                pathNum.get(i).add(pathNum.get(i).get(j - 1) + pathNum.get(i - 1).get(j));
            }
        }

        return pathNum.get(m - 1).get(n - 1);
    }
}

第5题 最小路径和(Minimum Path Sum)最小路径和
 

class Solution {
    public int minPathSum(int[][] grid) {
        int row = grid.length;
        int col = grid[0].length;

        if (grid == null) {
            return 0;
        }

        for (int i = 1; i < row; i++) {
            grid[i][0] = grid[i - 1][0] + grid[i][0];
        }

        for (int i = 1; i < col; i++) {
            grid[0][i] = grid[0][i - 1] + grid[0][i];
        }

        for (int i = 1; i < row; i++) {
            for (int j = 1; j < col; j++) {
                grid[i][j] = Math.min(grid[i - 1][j], grid[i][j - 1]) + grid[i][j];
            }
        }
        return grid[row - 1][col - 1];
    }
}

第6题 背包问题背包问题

答案一:

class Solution {
    public int backPackII(int m, int[] A, int[] V) {
        int num = A.length;
        if (m == 0 || num == 0) {
            return 0;
        }
        int[][] maxValue = new int[num + 1][m + 1];
        for (int i = 0; i <= num; i++) {
            maxValue[i][0] = 0;
        }
        for (int i = 1; i <= m; i++) {
            maxValue[0][i] = 0;
        }
        for (int i = 1; i <= num; i++) {
            for (int j = 1; j <= m; j++) {
                if (A[i - 1] > j) {
                    maxValue[i][j] = maxValue[i - 1][j];
                } else {
                    int newValue = maxValue[i - 1][j - A[i - 1]] + V[i - 1];
                    maxValue[i][j] = Math.max(newValue, maxValue[i - 1][j]);
                }
            }
        }

        return maxValue[num][m];
    }
}

答案二:(优化算法)

class Solution {

    public int backPackII(int m, int[] A, int[] V) {
        int num = A.length;

        if (m == 0 || num == 0) {
            return 0;
        }

        int[] maxValue = new int[m + 1];

        for (int i = 0; i <= m; i++) {
            maxValue[i] = 0;
        }

        for (int i = 1; i <= num; i++) {
            for (int j = m; j > 0; j--) {
                if (A[i - 1] <= j) {
                    int newValue = maxValue[j - A[i - 1]] + V[i - 1];
                    maxValue[j] = Math.max(newValue, maxValue[j]);
                }
            }
        }

        return maxValue[m];
    }
}

第7题 回文串分割(Palindrome Partitioning)回文串分割

答案:好难,没理解,痛苦

class Solution {
    public int minCut(String s) {
        int len = s.length();
        if (len == 0) {
            return 0;
        }
        int[] minCut = new int[len + 1];
        for (int i = 0; i <= len; i++) {
            minCut[i] = i - 1;
        }
        for (int i = 1; i <= len; i++) {
            for (int j = 0; j < i; j++) {
                if (isPal(s, j, i - 1)) {
                    minCut[i] = Math.min(minCut[i], minCut[j] + 1);
                }
            }
        }
        return minCut[len];
    }

    public boolean isPal(String s, int start, int end) {
        while (start < end) {
            if (s.charAt(start) != s.charAt(end)) {
                return false;
            }
            start++;
            end--;
        }
        return true;
    }
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿瞒有我良计15

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值