当前位置:网站首页>动态规划、背包问题 6/26 116-120
动态规划、背包问题 6/26 116-120
2022-08-10 05:36:00 【吉良吉影__.】
1.最长递增子序列( LeetCode 300 )
方法一:动态规划
此题解还有二分 + 贪心,目前难度较大,暂时放一放
class Solution {
public int lengthOfLIS(int[] nums) {
int n = nums.length;
int ans = 1;
//dp[i] = 已i下标处结尾的最长递增子序列长度
int[] dp = new int[n];
dp[0] = 1;
for (int i = 1; i < n; i++) {
int max = 0;
//寻找以本节点结尾可以获得的最大长度
for (int j = 0; j < i; j++) {
if (nums[j] < nums[i])
max = Math.max(max,dp[j]);
}
dp[i] = max + 1;//求得了以本节点结尾的最长子序列长度
ans = Math.max(ans,dp[i]);
}
return ans;
}
}
2.最长连续递增序列( LeetCode 674 )
class Solution {
public int findLengthOfLCIS(int[] nums) {
int n = nums.length;
//dp[i] = 以第i个元素结尾的最长连续子序列长度
int[] dp = new int[n];
dp[0] = 1;
int ans = 1;
for (int i = 1; i < n; i++) {
dp[i] = nums[i] > nums[i - 1] ? dp[i - 1] + 1 : 1;
ans = Math.max(ans,dp[i]);
}
return ans;
}
}
3.分割等和子集( LeetCode 416 )01背包
方法一:动态规划
时间复杂度O(NM)
空间复杂度O(NM)
//分割等和子集
class Solution {
public boolean canPartition(int[] nums) {
int sum = 0;
for (int x:nums) sum += x;
int target = sum / 2;
if (target * 2 != sum)return false;//如果sum为奇数则不能拆分为等和子集
//问题转化为能不能从nums中选出一些元素和为target
//dp[i][j] = 从前i个元素中进行选取,总和不超过j的最大值
int[][] dp = new int[nums.length][target + 1];
//初始化第一行,只有nums[0] <= i才能装进背包
for (int i = 0; i <= target; i++) {
dp[0][i] = nums[0] <= i ? nums[0] : 0;
}
for (int i = 1; i < nums.length; i++) {
for (int j = 0; j <= target; j++) {
//不选第i个元素的最大价值
int no = dp[i - 1][j];
//选第i个元素的最大价值
int yes = nums[i] <= j ? dp[i - 1][j - nums[i]] + nums[i] : 0;
dp[i][j] = Math.max(no,yes);
}
}
return dp[nums.length - 1][target] == target;
}
}
方法二:动态规划 优化
滚动数组优化
时间复杂度O(NM)
空间复杂度O(M)
//分割等和子集
class Solution {
public boolean canPartition(int[] nums) {
int sum = 0;
for (int x:nums) sum += x;
int target = sum / 2;
if (target * 2 != sum)return false;//如果sum为奇数则不能拆分为等和子集
//问题转化为能不能从nums中选出一些元素和为target
//dp[i][j] = 从前i个元素中进行选取,总和不超过j的最大值
int[][] dp = new int[2][target + 1];
//初始化第一行,只有nums[0] <= i才能装进背包
for (int i = 0; i <= target; i++) {
dp[0][i] = nums[0] <= i ? nums[0] : 0;
}
for (int i = 1; i < nums.length; i++) {
for (int j = 0; j <= target; j++) {
//不选第i个元素的最大价值
//(i - 1) & 1 上一行对应的行下标
int no = dp[(i - 1) & 1][j];
//选第i个元素的最大价值
int yes = nums[i] <= j ? dp[(i - 1) & 1][j - nums[i]] + nums[i] : 0;
//i & 1本行对应的行下标
dp[i & 1][j] = Math.max(no,yes);
}
}
return dp[(nums.length - 1) & 1][target] == target;
}
}
方法三:动态规划 优化
一维数组优化
时间复杂度O(NM)
空间复杂度O(M)
//分割等和子集
class Solution {
public boolean canPartition(int[] nums) {
int sum = 0;
for (int x:nums) sum += x;
int target = sum / 2;
if (target * 2 != sum)return false;//如果sum为奇数则不能拆分为等和子集
//问题转化为能不能从nums中选出一些元素和为target
//dp[j] = 总和不超过j的最大值
int[] dp = new int[target + 1];
for (int num: nums) {
//前i个元素中选取
//逆序填充dp数组
for (int i = target; i >= num ; i--) {
//选与不选第i个元素的最大值
dp[i] = Math.max(dp[i],dp[i - num] + num);
}
}
return dp[target] == target;
}
}
4.最长重复子数组( LeetCode 718 )
动态规划
class Solution {
public int findLength(int[] nums1, int[] nums2) {
int n = nums1.length;
int m = nums2.length;
int ans = 0;
//dp[i][j] = 以nums1中下标i结尾,nums2中下标j结尾的最长公共子数组
int[][] dp = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (nums1[i] == nums2[j]){
//相等查看前一个元素的最长子数组
dp[i][j] = (i - 1 >= 0 && j - 1 >= 0) ? dp[i - 1][j - 1] + 1 : 1;
}else {
//不相等,公共子数组长度为0
dp[i][j] = 0;
}
ans = Math.max(ans,dp[i][j]);
}
}
return ans;
}
}
5.最长公共子序列( LeetCode 1143 )
动态规划
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int m = text1.length();
int n = text2.length();
/* dp[i][j] = text1下标i及i之前,text2下标j及j之前的最长公共子序列 在i,j处有两种情况 情况一:text1[i] = text2[j] dp[i][j] = dp[i - 1][j - 1] + 1; 情况二:text1[i] != text2[j] dp[i][j] = Math.max(dp[i - 1][j],dp[j - 1][i]); */
int[][] dp = new int[m][n];
int ans = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
int x = j - 1 >= 0 ? dp[i][j - 1] : 0;//dp[i,j - 1]
int y = i - 1 >= 0 ? dp[i - 1][j] : 0;//dp[i - 1 ,j]
int z = (j - 1 >= 0 && i - 1 >= 0) ? dp[i - 1][j - 1] : 0;//dp[i - 1][j - 1]
if (text1.charAt(i) == text2.charAt(j)){
dp[i][j] = 1 + z;
}else {
dp[i][j] = Math.max(x,y);
}
ans = Math.max(ans,dp[i][j]);
}
}
return ans;
}
}
边栏推荐
猜你喜欢
随机推荐
C#对MySQL数据库进行增删改查操作(该操作还有防止MySQL注入功能)
Gradle学习 (一) 入门
每日刷题(day02)——leetcode 622. 设计循环队列
观察者模式-数据池
LeetCode refers to the offer 21. Adjust the order of the array so that the odd numbers are in front of the even numbers (simple)
51单片机ST188手持人体温度脉搏心率测量仪锂电池充电
动态规划、背包问题 6/28 121-124
hanLP探索-语义距离计算的实现
VTK 初步 (1) ----- 可视化管线
2021-04-15 jacoco代码覆盖率统计和白盒测试
酸阻滞树脂
Multisim软件的基本使用
为什么游戏需要热更新?
氨氮的有效吸附材料
【fiddler2】使用fiddler mock response 数据
详解样条曲线(上)(包含贝塞尔曲线)
I don't like my code
ASP.NET连接SQL Server的步骤
Deep learning TensorFlow entry environment configuration
二维卷积定理的验证(下,cv2.filter2D())









