>1.最大子序和问题
//找到整数数组nums的具有最大和的连续子数组(子数组最少包含一个元素)并返回其最大和
public int maxSubArray(int[] nums) {
//动态规划思路:
//dp[i]代表从数组的开始位置到下标为i的和的最大值
//dp[i] = Math.max(dp[i - 1], dp[i - 1] + nums[i])
//上一行即判断:每一次dp[i]的时候要不要加上前面的i-1个(即dp[i-1]有没有可能是负的)
//针对nums = {-2,1,-3,4,-1,2,1,-5,4}来说
//nums[i] -2 1 -3 4 -1 2 1 -5 4
//dp[i] -2 1 -2 4 3 5 6 1 5
//res MIN 1 1 4 4 5 6 6 6
int[] dp = new int[nums.length];
dp[0] = nums[0];
int res = Integer.MIN_VALUE;
for(int i = 1; i < nums.length; i++) {
dp[i] = Math.max(nums[i], dp[i - 1] + nums[i]);
res = Math.max(res, dp[i]);
}
return Math.max(res,dp[0]);
}
>2.爬楼梯问题
//共n阶台阶,每次可走1阶或2阶,问有多少种走法
public int climbStairs(int n) {
//定义dp[i]为走到第i阶的路径数,由于每一步可走1阶或2阶
//显然dp[i]与dp[i - 1]、dp[i - 2]有关,转移方程如下:
//dp[i] = dp[i - 1] + dp[i - 2]
if (n == 1) return 1;
if (n == 2) return 2;
int[] dp = new int[n + 1];//dp[0] = 0可省略不写
dp[1] = 1;
dp[2] = 2;
for(int i = 3; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
// return n == 1 ? 1 : (n == 2 ? 2 : (climbStairs(n - 1) + climbStairs(n - 2)));
//上面一行的递归方法时间复杂度比动态规划高!!超时!!!!
}
//思考:如果每一步可走1阶、2阶或3阶,又将会有多少种走法呢?
public int climbStairs(int n) {
if (n == 1) return 1;
if (n == 2) return 2;
if (n == 3) return 4;
int[] dp = new int[n + 1];
dp[0] = 0;
dp[1] = 1;
dp[2] = 2;
dp[3] = 4;
for (int i = 4; i <= n; i++) {
dp[i] = dp[i- 1] + dp[i - 2] + dp[i - 3];
}
return dp[n];
}
>2.1类似问题还有:leetcode.62 不同路径问题:
leetcode.62:从一个m*n的网格的左上角走到右下角,一共有多少种走法(规定每次只能向下或向右走)
class Solution {
public int uniquePaths(int m, int n) {
if (m == 1 || n == 1) return 1;
//return uniquePaths(m, n - 1) + uniquePaths(m - 1, n);//直接递归,运行超时!!!
int[][] dp = new int[m + 1][n + 1];
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
dp[i][0] = dp[0][j] = 0;
dp[i][1] = dp[i][j] = 1;
dp[i][j] = dp[i][j - 1] + dp[i - 1][j];
}
}
return dp[m][n];
}
}