目录
一、最大子数组和
题目链接:53. 最大子数组和 - 力扣(LeetCode)
1、暴力求解(java会超时)
用两个for循环,枚举出每一种情况,找到和最大的那个--时间复杂度O(n2)
代码如下:
public int maxSubArray(int[] nums) {
int len=nums.length;
int ret=Integer.MIN_VALUE; //存放最终结果
int sum=0;
for(int i=0;i<len;i++){ //固定起始位置
sum=0;
for(int j=i;j<len;j++){
sum+=nums[j];
ret=ret>sum?ret:sum;
}
}
return ret;
}
2、贪心算法
当连续和为负数的时候,就抛弃这个连续和从下一个数开始加。
代码如下:
public int maxSubArray(int[] nums) {
int ret=-1000001; //保存最大值
int sum=0;
for(int i=0;i<nums.length;i++){
sum+=nums[i];
ret=ret>sum?ret:sum;
if(sum<0){
sum=0;
}
}
return ret;
}
3、动态规划
动规五部曲
1.dp数组定义及下标含义
dp[i]:以i为结尾的最大子序列和
2.递推公式
递推公式:dp[i]可以延续上一个状态+nums[i];第二个是可以从nums[i]开始计算
dp[i]=max(dp[i-1]+nums[i],nums[i])
3.数组初始化
dp[0]=nums[0]
4.遍历顺序
从前到后遍历
4.打印
代码如下:
public int maxSubArray(int[] nums) {
int[] dp=new int[nums.length];
dp[0]=nums[0];
int max=nums[0];
for(int i=1;i<nums.length;i++){
dp[i]=Math.max(dp[i-1]+nums[i],nums[i]);
max=Math.max(max,dp[i]); //找dp数组中的最大值
}
return max;
}
二、礼物的最大价值
题目链接:剑指 Offer 47. 礼物的最大价值 - 力扣(LeetCode)
这是一道很标准的动态规划
动规五部曲
1.dp数组定义
dp[i][j]:走到(i,j)能拿到的最大价值。
2.递推公式
只能向下或向右移动,所以,dp[i][j]可以由dp[i-1][j]或者dp[i][j-1]推出
dp[i][j]=max(dp[i-1][j],dp[i][j-1])+grid[i]
3.dp数组初始化
为了方便,直接初始化第0行和第0列
4、遍历顺序
从左到右,从上到下
5.打印
代码如下:
public int maxValue(int[][] grid) {
int m=grid.length;
int n=grid[0].length;
int[][] dp=new int[m][n];
dp[0][0]=grid[0][0];
for(int i=1;i<m;i++){
dp[i][0]=dp[i-1][0]+grid[i][0]; //初始化第0列
}
for(int i=1;i<n;i++){
dp[0][i]=dp[0][i-1]+grid[0][i]; //初始化第0行
}
for(int i=1;i<m;i++){
for(int j=1;j<n;j++){
dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1])+grid[i][j];
}
}
return dp[m-1][n-1];
}