当前位置:网站首页>动态规划、背包问题 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;
}
}
边栏推荐
猜你喜欢
随机推荐
所有文章汇总目录
自定义View的流程总结学习
51单片机营养液自动配置搅拌系统TDS浓度采集自动加水加营养液
在Unity中让物体围绕自身的x、y、z轴进行旋转(亲测有效)
AR Foundation Editor Remote插件使用方法
STM32F407ZG GPIO输出相关实验
Gradle学习(二)Groovy
每日刷题(day01)——leetcode 53. 最大子数组和
Unity对象池实现
LeetCode 1351. Counting Negative Numbers in Ordered Matrices (Simple)
内核性能分析总结
新建STM32F407ZG Keil5项目
STM32单片机手机APP蓝牙高亮RGB彩灯控制板任意颜色亮度调光
二次元卡通渲染之描边
废水中氟离子去除方法
作为测试,常用的adb命令
过大数组导致爆栈的解决方法记录(堆栈)
剑指 Offer(第 2 版)7/7 14-17
Unity中实现Animation Clip动画片段的倒播(该案例可以防止动画延迟)
Pytorch - 07. Multidimensional characteristics of input processing