LeetCode122
题目:
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
思路:
只要后一天大于前一天,便可以卖出买入。
第一天买入第三天卖出,相当于第一天买入第二天卖出第二天买入第三天再卖出
代码:
public int maxProfit(int[] prices) {
if(prices.length<=0)
return 0;
int sum =0;
for(int i=1;i<prices.length;++i){
if(prices[i]>prices[i-1])
sum+=prices[i]-prices[i-1];
}
return sum;
}
ode123
题目:
给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。注意: 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
思路1:
构建两个数组,分别表示从第一天开始卖,只卖一次可以取得的最大值;从最后第i天开始第二次卖可能达到的最大值;两者之和最大即为最多两笔交易可达最值(需要单独考虑只卖一次的情况)
代码1:
思路2:
动态规划。
动态规划的一般步骤:
- 将原问题转化为子问题
- 确定状态
- 确定一些初始状态(边界状态)
- 确定状态方程
代码2:
/**
* @param prices
* @return
* 最多完成两次买卖,所以最多有4种状态
* 第一次买:buy1=max(buy1,-prices[i])
* 第一次卖:sell1 = max(sell1,prices[i]+buy1);
* 第二次买:buy2 = max(buy2,sell1-prives[i]);
* 第二次卖:sell2=max(sell2,buy2+prices[i]);
*最后返回结果应该是sell1或者sell2中的最大值。
*/
public int maxProfit(int[] prices) {
//如果buy1 = Integer.MIN_VALUE可以不需要考虑length<0的情况,
//但是如果用了prices[0]需要单独考虑length<=0的情况,即数组为空
if(prices.length<=0)
return 0;
int buy1 = -prices[0],sell1=0;//sell1=0相当于第一天买入然后立刻卖出
int buy2 = -prices[0],sell2=0;
for(int p :prices) {
buy1 = Math.max(buy1, -p);
sell1 = Math.max(sell1, buy1+p);
buy2 = Math.max(buy2, sell1-p);
sell2 = Math.max(sell2, buy2+p);
}
return Math.max(sell1,sell2);
}
思路3:
从第几次交易考虑,同样使用动态规划方法:
状态转移方程:第i天的收益为result[k,i]=max(result[k,i−1],prices[i]−prices[j]+result[k−1,j−1])
k表示第k次交易,j<=i-1
LeetCode120 三角形最小路径和
题目:
给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
例如,给定三角形:
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。
思路1:
自底向上的动态规划。
通过构建二维数组,上一层节点[i][j]可以选择的下一层结点为[i+1][j]和[i+1][j+1]
所以dp[i][j]=min(dp[i+1][j+1],dp[i+1][j])+dp[i][j];//这里使用的是ArrayList数组,获取方式与数组直接获取略有不同
dp[i][j] 相当于 triangle.get(i).get(j)
代码1:
public int minimumTotal(ArrayList<ArrayList<Integer>> triangle) {
if(triangle==null || triangle.size()==0)
return 0;
// 加1可以不用初始化最后一层
int[][] dp = new int[triangle.size()+1][triangle.size()+1];
for(int i=triangle.size()-1;i>=0;--i) {
ArrayList<Integer> cur = triangle.get(i);
for(int j=0;j<cur.size();++j)
dp[i][j] = Math.min(dp[i+1][j], dp[i+1][j+1])+cur.get(j);
}
return dp[0][0];
}
<br><br>
思路2:
自顶向下的动态规划
minPath[i] = min(minPath[i]+minPath[i+1])+triangle[k][i]
代码2:
public int minimumTotal(ArrayList<ArrayList<Integer>> triangle) {
if (triangle == null || triangle.size() == 0){
return 0;
}
int[] dp = new int[triangle.size()+1];
for(int i=triangle.size()-1;i>=0;--i){
ArrayList<Integer> cur = triangle.get(i);
for(int j=0;j<cur.size();++j)
//这里的dp[j] 使用的时候默认是上一层的,赋值之后变成当前层
dp[j]=Math.min(dp[j],dp[j+1])+cur.get(j);
}
}
思路3:
自顶向上:https://blog.csdn.net/wys2011101169/article/details/73306882
LeetCode118杨辉三角
题目:
给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。
[
[1],
[1,1],
[1,2,1],
[1,3,3,1],
[1,4,6,4,1]
]
思路:
dp[i][j]=dp[i-1][j-1]+dp[i-1][j-1];
代码:
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
if(numRows<=0) return res;
res.add(Arrays.asList(1));//Arrays.asList(1)的返回类型是List不是ArrayList
for(int i=1;i<numRows;i++){
List<Integer> list = new ArrayList<Integer>();
for(int j=0;j<=i;j++){
if(j == 0 || j==i)
list.add(1);
else
list.add(res.get(i-1).get(j-1)+res.get(i-1).get(j));
}
res.add(list);
}
return res;
}