leecode更新

This commit is contained in:
markilue 2023-02-22 14:54:05 +08:00
parent 607b5f6af2
commit 933ab91051
5 changed files with 294 additions and 1 deletions

View File

@ -96,7 +96,7 @@ public class T27_LengthOfLIS {
r = mid - 1; r = mid - 1;
} }
} }
d[pos + 1] = nums[i]; d[pos + 1] = nums[i];//把第一个小于的位置替换成这个数//并不影响原本的长度,只有后续比他更长了才会影响他的长度
} }
} }
return len; return len;

View File

@ -0,0 +1,96 @@
package com.markilue.leecode.dynamic.second;
import org.junit.Test;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.dynamic.second
*@Author: markilue
*@CreateTime: 2023-02-22 10:35
*@Description:
* TODO 力扣714题 买卖股票的最佳时机含手续费:
* 给定一个整数数组 prices其中 prices[i]表示第 i 天的股票价格 整数 fee 代表了交易股票的手续费用
* 你可以无限次地完成交易但是你每笔交易都需要付手续费如果你已经购买了一个股票在卖出它之前你就不能再继续购买股票了
* 返回获得利润的最大值
* 注意这里的一笔交易指买入持有并卖出股票的整个过程每笔交易你只需要为支付一次手续费
*@Version: 1.0
*/
public class T26_MaxProfit {
@Test
public void test(){
int[] prices = {1, 3, 2, 8, 4, 9};
int fee = 2;
System.out.println(maxProfit(prices,fee));
}
/**
* 思路:仅是每笔交易的时候包含了手续费;在每次买的时候加上手续费即可
* 速度击败50.42% 内存击败89.43%
* @param prices
* @param fee
* @return
*/
public int maxProfit(int[] prices, int fee) {
int[][] dp = new int[prices.length][2];
dp[0][0] = 0;
dp[0][1] = -prices[0] - fee;
for (int i = 1; i < prices.length; i++) {
dp[i][0]=Math.max(dp[i-1][0],dp[i-1][1]+prices[i]);
dp[i][1]=Math.max(dp[i-1][1],dp[i-1][0]-prices[i]-fee);
}
return dp[dp.length-1][0];
}
/**
* 一维dp优化
* 速度击败99.96% 内存击败36.47% 3ms
* @param prices
* @param fee
* @return
*/
public int maxProfit1(int[] prices, int fee) {
int dp0 = 0;
int dp1 = -prices[0] - fee;
int temp;
for (int i = 1; i < prices.length; i++) {
temp=dp0;
dp0=Math.max(dp0,dp1+prices[i]);
dp1=Math.max(dp1,temp-prices[i]-fee);
}
return dp0;
}
/**
* 贪心算法: 核心在于 何时才真正卖出
* @param prices
* @param fee
* @return
*/
public int maxProfit2(int[] prices, int fee) {
int buy=prices[0]+fee;
int sum=0;
for (int price : prices) {
if(price+fee<buy){//后续如果比8大的数如果在之前遇到了p + fee<buy的情况,那么后续就一定有正收益了所以之前的可以放心卖
buy=price+fee;//寻找最小价格
}else if(price>buy){
sum += price - buy;//假装排除计算收益
buy = price;//后期如果有数比他大那么就是计算加上的p-buy增值收益
}
}
return sum;
}
}

View File

@ -0,0 +1,44 @@
package com.markilue.leecode.dynamic.second;
import java.util.Arrays;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.dynamic.second
*@Author: markilue
*@CreateTime: 2023-02-22 10:58
*@Description:
* TODO leecode300 最长递增子序列:
* 给你一个整数数组 nums 找到其中最长严格递增子序列的长度
* 子序列 是由数组派生而来的序列删除或不删除数组中的元素而不改变其余元素的顺序例如[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列
*@Version: 1.0
*/
public class T27_LengthOfLIS {
/**
* 思路:注意是子序列,可以删除前后元素,找最长 因为可以删除 所以可以将状态分为两种 要当前的词 不要当前的词 TODO 不知道如何保存状态未能做出
* TODO dp五部曲:
* 1.dp定义: dp[i][0]表示不要当前当前的词的最长序列长度 dp[i][1]表示要当前的词的最长序列长度
* 2.dp状态转移方程: //因为没法保存状态,所以只能暴力依次比较 时间复杂度O(n^2)
* 3.dp初始化:
* 4.dp遍历顺序:
* 5.dp举例推导:
* @param nums
* @return
*/
public int lengthOfLIS(int[] nums) {
int[] dp = new int[nums.length];
Arrays.fill(dp, 1);
int result = 0;
for (int i = 0; i < dp.length; i++) {
for (int j = 0; j < i; j++) {//本质上还是依次比较寻找最大的
if (nums[i] > nums[j]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
if (dp[i] > result) result = dp[i]; // 取长的子序列
}
return result;
}
}

View File

@ -0,0 +1,67 @@
package com.markilue.leecode.dynamic.second;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.dynamic.second
*@Author: markilue
*@CreateTime: 2023-02-22 11:47
*@Description:
* TODO 力扣674题 最长连续递增序列:
* 给定一个未经排序的整数数组找到最长且 连续递增的子序列并返回该序列的长度
* 连续递增的子序列 可以由两个下标 l rl < r确定如果对于每个 l <= i < r都有 nums[i] < nums[i + 1]
* 那么子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]] 就是连续递增子序列
*@Version: 1.0
*/
public class T28_FindLengthOfLCIS {
/**
* 思路:不同之处在于 要连续递增 所以要维护的是一个子数组由于是连续的,所以比较
* TODO DP五部曲
* 1.dp定义:
* 2.dp状态转移方程:
* 3.dp初始化:
* 4.dp遍历顺序:
* 5.dp举例推导:
* @param nums
* @return
*/
public int findLengthOfLCIS(int[] nums) {
int maxLength = 1;
int curLength = 1;
for (int i = 1; i < nums.length; i++) {
if (nums[i] > nums[i - 1]) {
curLength++;
} else {
curLength = 1;//小于就重置
}
if (curLength > maxLength) maxLength = curLength;
}
return maxLength;
}
/**
* 动态规划法
* @param nums
* @return
*/
public int findLengthOfLCIS1(int[] nums) {
int nowLength=1;
int[] dp = new int[nums.length];
dp[0]=1;
for (int i = 1; i < nums.length; i++) {
if (nums[i] > nums[i-1]) {
nowLength+=1;//状态递推
}else {
nowLength=1;
}
dp[i]=Math.max(dp[i-1],nowLength);
}
return dp[nums.length-1];
}
}

View File

@ -0,0 +1,86 @@
package com.markilue.leecode.dynamic.second;
import org.junit.Test;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.dynamic.second
*@Author: markilue
*@CreateTime: 2023-02-22 11:56
*@Description:
* TODO 力扣718题 最长重复子数组:
* 给两个整数数组 nums1 nums2 返回 两个数组中 公共的 长度最长的子数组的长度
*@Version: 1.0
*/
public class T29_FindLength {
@Test
public void test() {
int[] nums1 = {0, 1, 1, 1, 1};
int[] nums2 = {1, 0, 1, 0, 1};
System.out.println(findLength(nums1, nums2));
}
/**
* 思路:
* TODO DP五部曲:
* 1.dp定义:dp[i][j]表示 使用nums1[0-i]和nums2[0-j]所返回的最长长度
* 2.dp状态转移方程:
* dp[i][j] 可以是 不要nums2[j] 不要nums1[i] 或者nums[i]==nums[j]
* dp[i][j] if(nums[i-1]!=nums[j-1]) max(dp[i-1][j],dp[i][j-1])
* else dp[i-1][j-1]+1
* 3.dp初始化:为了初始化方便取nums[i-1]!=nums[j-1]的关系 dp[i][0]=0; dp[0][j]=0;
* 4.dp遍历顺序:
* 5.dp举例推导:
* @param nums1
* @param nums2
* @return
*/
public int findLength(int[] nums1, int[] nums2) {
int[][] dp = new int[nums1.length + 1][nums2.length + 1];
int result = 0;
for (int i = 1; i < dp.length; i++) {
for (int j = 1; j < dp[0].length; j++) {
if (nums1[i - 1] == nums2[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1;
//因为是子数组不是子序列所以一不想等就直接等于0了不做处理
if (result < dp[i][j]) result = dp[i][j];
// else dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
return result;
}
/**
* 一维dp优化
* @param nums1
* @param nums2
* @return
*/
public int findLength1(int[] nums1, int[] nums2) {
int[] dp = new int[nums2.length + 1];
int result = 0;
for (int i = 1; i < nums1.length + 1; i++) {
for (int j = dp.length - 1; j >= 1; j--) {
//返许遍历因为dp[j]要用到dp[i-1]
if (nums1[i - 1] == nums2[j - 1]) {
dp[j] = dp[j - 1] + 1;
}else {
dp[j]=0; //TODO 特别需要注意: 如果不等需要重新赋值避免不覆盖的情况而二维的时候不用因为不用重复利用
}
//因为是子数组不是子序列所以一不想等就直接等于0了不做处理
if (result < dp[j]) result = dp[j];
}
}
return result;
}
}