1、买卖股票的最佳时机
2、买卖股票的最佳时机 II
3、买卖股票的最佳时机 III
4、买卖股票的最佳时机 IV
5、最大子数组和
6、买卖股票的最佳时机含手续费
7、最佳买卖股票时机含冷冻期
8、检查相同字母间的距离
class Solution {
public int maxProfit(int[] prices) {
//只能买卖一次
int[] dp = new int[2];
//【0】买 【1】卖
dp[0] = -prices[0];
for(int i=1;i<prices.length;i++){
//第i天买入 有买和不买两种可能 不买:dp[i-1][0]前一天的买入的钱 买的话钱应该变为-prices[i]
dp[0] = Math.max(dp[0],-prices[i]);
//第i天卖出 有卖和不卖两种可能 不卖:dp[i-1][1]前一天的卖出的钱 卖的话钱应该变为
dp[1] = Math.max(dp[1],prices[i]+dp[0]);
}
return dp[1];
}
}
class Solution {
public int maxProfit(int[] prices) {
int[] dp = new int[2];
dp[0] = -prices[0];
for(int i=1;i<prices.length;i++){
dp[0] = Math.max(dp[0],dp[1]-prices[i]);
dp[1] = Math.max(dp[1],dp[0]+prices[i]);
}
return dp[1];
}
}
class Solution {
public int maxProfit(int[] prices) {
int[] dp = new int[4];
dp[0]=-prices[0]; //第一次买入
dp[1] = 0;//第一次卖出
dp[2] = -prices[0]; //第二次买入
dp[3] = 0;//第二次卖出
for(int i=1;i<prices.length;i++){
//第一次买入 不买还是买
dp[0] = Math.max(dp[0],-prices[i]);
//第一次卖出 不卖还是卖
dp[1] = Math.max(dp[1],dp[0]+prices[i]);
//第二次买入 不买还是买 第一次卖出之后赚的钱继续买
dp[2] = Math.max(dp[2],dp[1]-prices[i]);
//第二次卖出
dp[3] = Math.max(dp[3],dp[2]+prices[i]);
}
return dp[3];
}
}
分析:
III的进阶版 从特殊到一般 奇数表示买入,偶数表示卖出,其余操作类似
class Solution {
public int maxProfit(int k, int[] prices) {
int[][] dp = new int[prices.length][2*k+1];
// 1:买入
// 2:卖出
// 3:买入
// 4:卖出
//…… ……
for(int i=1;i<2*k+1;i+=2){
dp[0][i] = -prices[0];
}
for(int i=1;i<prices.length;i++){
for(int j = 1;j<=2*k-1;j+=2){
//奇数 j买入 第i天的股票 买还是不买两种状态 买今天的:前一天卖出的钱-当前的股票钱 dp[i-1][j-1]-prices[i]
//不买今天的 dp[i-1][j] 前一天买入的钱
dp[i][j] = Math.max(dp[i-1][j-1]-prices[i],dp[i-1][j]);
//偶数 j+1卖出 第i天的股票 卖还是不卖两种状态 卖今天的:前一天买入的钱+当前的股票钱 dp[i-1][j]+prices[i]
//不卖今天的 dp[i-1][j+1] 前一天买入的钱
dp[i][j+1] = Math.max(dp[i-1][j]+prices[i],dp[i-1][j+1]);
}
}
return dp[prices.length-1][2*k];
}
}
class Solution {
public int maxSubArray(int[] nums) {
int[] dp = new int[nums.length];
dp[0] = nums[0];
int res = nums[0];
for( int i=1;i<nums.length;i++){
dp[i] = Math.max(dp[i-1]+nums[i],nums[i]);
res = Math.max(dp[i],res);
}
return res;
}
}
class Solution {
public int maxProfit(int[] prices, int fee) {
int[] dp = new int[2];
dp[0] = -prices[0]-fee;
for(int i=1;i<prices.length;i++){
dp[0] = Math.max(dp[0],dp[1]-prices[i]-fee);
dp[1] = Math.max(dp[1],dp[0]+prices[i]);
}
return dp[1];
}
}
分析:
根据状态去计算每天对应的值
class Solution {
public int maxProfit(int[] prices) {
int[][] dp = new int[prices.length][3];
dp[0][0] = -prices[0];//0表示买入
dp[0][1] = 0;//1表示卖出
dp[0][2] = 0;//2表示冷冻期
for(int i=1;i<prices.length;i++){
//买入:第i天不买 第i天买
//dp[i-1][2] 前一天是冷冻期
//dp[i-1][0] 前一天以内买入股票
//dp[i-1][1] 前一天售出股票
dp[i][0] = Math.max(dp[i-1][0],dp[i-1][2]-prices[i]);
dp[i][1] = Math.max(dp[i-1][1],dp[i-1][0]+prices[i]);
dp[i][2] = dp[i-1][1];
}
return dp[prices.length-1][1];
}
}
分析:
在比较两个数组时,因为0比较特殊,可能表示两个字符间的间隔为0,也可能表示distance数组中的0,因此我们自己计算的这个临时数组,给他都初始化为1 以作区分
class Solution {
public boolean checkDistances(String s, int[] distance) {
//Map放字符 以及对应出现的下标
Map<Character,Integer> map = new HashMap<>();
int[] temp = new int[26];
Arrays.fill(temp, -1);
map.put(s.charAt(0),0);
//1、先求距离
for(int i=1;i<s.length();i++){
char c = s.charAt(i);
if(map.get(c)==null){
map.put(c,i);
}else{
temp[c-'a']=i-map.get(c)-1;
}
}
//2、得到temp数组之后和distance数组进行比较 是不是子集 temp是不是distance的子集
//temp在distance中都能找到
for(int i=0;i<26;i++){
if(temp[i]!=-1){
if(temp[i]!=distance[i])
return false;
}
}
return true;
}
}