题目来自《代码随想录》
https://leetcode-cn.com/problems/longest-increasing-subsequence/
注意,本题未要求连续
/*
* 定义 dp[i] 为考虑前 i个元素,以第 i个数字结尾的最长上升子序列的长度,
* 注意 nums[i] 必须被选取。
*/
public int lengthOfLIS(int[] nums) {
int len = nums.length;
if(len <= 1) return len;
int[] dp = new int[len];
for(int i=0; i<len; i++) dp[i] = 1;//初始化
int maxans = 1;
for(int i=1; i<len; i++){
for(int j=0; j<i; j++){
if(nums[i] > nums[j]) {
dp[i] = Math.max(dp[i], dp[j]+1);
}
}
maxans = Math.max(maxans, dp[i]);
show(dp);
}
return maxans;
}
public void show(int[] num){
for(int i:num) System.out.print(i + " ");
System.out.print("\n");
}
//注意不是连续!!错误!!
public int lengthOfLIS2(int[] nums) {
int len = nums.length;
if(len <= 1) return len;
int l = 0;
int r = 1;
int cur = 1;
int res = 0;
while(r<len){
if(nums[r]>nums[r-1]){//严格递增
System.out.println(nums[r] + ">" + nums[r-1] + ", 当前递增");
System.out.println("l=" + l + ", r=" + r);
cur++;
r++;
res = Math.max(cur, res);
}else{
System.out.println("l=" + l + ", r=" + r);
l = r;
r++;
cur = 0;
}
}
return res;
}
https://leetcode-cn.com/problems/longest-continuous-increasing-subsequence/
/*
* 2. 动态规划
* 执行用时:1 ms, 在所有 Java 提交中击败了99.77%的用户
* 内存消耗:42.2 MB, 在所有 Java 提交中击败了6.06%的用户
*/
public int findLengthOfLCIS2(int[] nums) {
int len = nums.length;
if(len <= 1) return len;
int[] dp = new int[len];
dp[0] = 1;
int res = 1;
for(int i=1; i<len; i++){
if(nums[i] > nums[i-1]){
dp[i] = dp[i-1]+1;
res = Math.max(res, dp[i]);
}else{
dp[i] = 1;
}
}
return res;
}
/*
* 1. 双指针
* 执行用时:1 ms, 在所有 Java 提交中击败了99.77%的用户
* 内存消耗:42.1 MB, 在所有 Java 提交中击败了12.63%的用户
*
* 注意:
* 1. 一开始res要赋值为0
* 2. 一旦不递增,cur不归零,归1
*/
public int findLengthOfLCIS(int[] nums) {
int len = nums.length;
if(len <= 1) return len;
int l = 0;
int r = 1;
int cur = 1;
int res = 1;
while(r<len){
if(nums[r]>nums[r-1]){//严格递增
System.out.print(nums[r] + ">" + nums[r-1] + ", 当前递增");
//System.out.println("l=" + l + ", r=" + r);
cur++;
r++;
res = Math.max(cur, res);
System.out.println(",当前cur:" + cur);
}else{
System.out.print(nums[r] + "<=" + nums[r-1] + ", 当前非递增");
//System.out.println("l=" + l + ", r=" + r);
l = r;
r++;
cur = 1;
System.out.println(",当前cur:" + cur);
}
}
return res;
}
https://leetcode-cn.com/problems/maximum-length-of-repeated-subarray/
/*
* dp[i][j]:以下标i结尾的nums1和以下标j结尾的nums2的最长公共子序列为dp[i][j]
*/
public int findLength(int[] nums1, int[] nums2) {
int len1 = nums1.length;
int len2 = nums2.length;
if(len1 == 0 || len2 == 0) return 0;
int[][] dp = new int[len1+1][len2+1];
int res = 0;
for(int i=0; i<len1+1; i++){
for(int j=0; j<len2+1; j++){
if(i==0 || j==0) {//左边上边都是0
dp[i][j] = 0;continue;
}
if(nums2[j-1] == nums1[i-1]){
dp[i][j] = dp[i-1][j-1] + 1;
res = Math.max(res, dp[i][j]);
}
show(dp);
}
}
return res;
}
public void show(int[][] num){
for(int i=0; i<num.length; i++){
for(int j=0; j<num[0].length; j++){
System.out.print(num[i][j] + " ");
}
System.out.print("\n");
}
System.out.println("*************");
}
https://leetcode-cn.com/problems/longest-common-subsequence/
/*
* dp[i][j]:长度为[0, i-1]的字符串text1与长度为[0, j-1]的字符串text2
* 的最长公共子序列为dp[i][j]
*/
public int longestCommonSubsequence(String text1, String text2) {
int len1 = text1.length();
int len2 = text2.length();
if(len1 == 0 || len2 == 0) return 0;
int[][] dp = new int[len1+1][len2+1];
int res = 0;
for(int i=0; i<=len1; i++) {
for(int j=0; j<=len2; j++) {
if(i==0 || j==0) {//左边上边都是0
dp[i][j] = 0;continue;
}
/*
* dp[i][j]来自三个方向:左上,左,上
*/
if(text1.charAt(i+1) == text2.charAt(j+1)){
dp[i][j] = dp[i-1][j-1] + 1;
}else{
dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
}
res = Math.max(dp[i][j], res);
}
}
return res;
}
https://leetcode-cn.com/problems/uncrossed-lines/
其实就是最长公共子序列。
/*
* 直线不能相交,这就是说明在字符串A中 找到一个与字符串B相同的子序列,
* 且这个子序列不能改变相对顺序,只要相对顺序不改变,链接相同数字的直线就不会相交。
*/
public int maxUncrossedLines(int[] nums1, int[] nums2) {
int len1 = nums1.length;
int len2 = nums2.length;
if(len1 == 0 || len2 == 0) return 0;
int[][] dp = new int[len1+1][len2+1];
int res = 0;
for(int i=0; i<=len1; i++) {
for(int j=0; j<=len2; j++) {
if(i==0 || j==0) {//左边上边都是0
dp[i][j] = 0;continue;
}
/*
* dp[i][j]来自三个方向:左上,左,上
*/
if(nums1[i-1] == nums2[j-1]){
dp[i][j] = dp[i-1][j-1] + 1;
}else{
dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
}
res = Math.max(dp[i][j], res);
}
}
return res;
}
/*
* 贪心
*/
public int maxSubArray(int[] nums) {
int len = nums.length;
if(len == 0) return 0;
int cur = 0;
int res = Integer.MIN_VALUE;
for(int i=0; i<len; i++){
cur += nums[i];
if(cur > res) res = cur;
if(cur < 0) cur = 0;
}
return res;
}
/*
* 动规
*/
public int maxSubArray1(int[] nums) {
int len = nums.length;
if(len == 0) return 0;
int[] dp = new int[len];
dp[0] = nums[0];
int res = nums[0];
for(int i=1; i<len; i++){
/*
* 两个来源,两个求max
* 1. 从自己这重新开始
* 2. 加入前一个
*/
dp[i] = Math.max(nums[i], dp[i-1]+nums[i]);
res = Math.max(res, dp[i]);
show(dp);
}
return res;
}
https://leetcode-cn.com/problems/is-subsequence/submissions/
这个题要好好再和别的对比一下
public boolean isSubsequence(String s, String t) {
int len1 = s.length();
int len2 = t.length();
if(len1 == 0) return true;
if(len2 == 0 || len1>len2) return false;
int[][] dp = new int[len1+1][len2+1];
for(int i=1; i<=len1; i++){
for(int j=1; j<=len2; j++){
if(s.charAt(i-1) == t.charAt(j-1)){
dp[i][j] = dp[i-1][j-1]+1;
}else{
dp[i][j] = dp[i][j-1];
}
// show(dp);
}
}
return dp[len1][len2] == len1;
}
https://leetcode-cn.com/problems/distinct-subsequences/
/*
* 输入:s = "rabbbit", t = "rabbit"
* 输出:3
* dp[i][j]:以i-1为结尾的s子序列中出现以j-1为结尾的t的个数为dp[i][j]。
*/
public int numDistinct(String s, String t) {
int len1 = s.length(); int len2 = t.length();
if(len2 == 0) return 0;
int[][] dp = new int[len1+1][len2+1];
dp[0][0] = 1;
for(int i=1; i<=len1; i++){
for(int j=0; j<=len2; j++){
if(j == 0){
dp[i][j] = 1;continue;//初始化
}
if(s.charAt(i-1) == t.charAt(j-1)){//相等由两部分构成
dp[i][j] = dp[i-1][j-1] + dp[i-1][j];
}else{
dp[i][j] = dp[i-1][j];
}
}
}
return dp[len1][len2];
/*
* 1. s[i - 1] 与 t[j - 1]相等
* 一部分是用s[i - 1]来匹配,那么个数为dp[i - 1][j - 1]。
* 一部分是不用s[i - 1]来匹配,个数为dp[i - 1][j]。
* 2. s[i - 1] 与 t[j - 1] 不相等
* dp[i][j]只有一部分组成,不用s[i - 1]来匹配,即:dp[i - 1][j]
*/
}
https://leetcode-cn.com/problems/delete-operation-for-two-strings/
min的括号不要标错位置!
/*
* word1 = "sea", word2 = "eat",输出:2
* word1 = "leetcode", word2 = "etco",输出:4
*/
public int minDistance(String word1, String word2) {
int len1 = word1.length();
int len2 = word2.length();
if(len1 == 0) return len2;
if(len2 == 0) return len1;
int[][] dp = new int[len1+1][len2+1];
for (int i=0; i<=len1; i++) dp[i][0] = i;
for (int j=0; j<=len2; j++) dp[0][j] = j;
for(int i=1; i<=len1; i++){
for(int j=1; j<=len2; j++){
if(word1.charAt(i-1) == word2.charAt(j-1)){
//相等的时候就是左上角
dp[i][j] = dp[i-1][j-1];
}else{
//不等的时候三种情况,1减一个,2减一个,一起减一个,三个求min
dp[i][j] = Math.min(dp[i-1][j-1]+2, Math.min(dp[i][j-1]+1, dp[i-1][j]+1));
// if(i == 2 && j == 2){
// System.out.println("i = " + i + ", j = " + j);
// System.out.println("dp[i-1][j-1]+2 = " + (dp[i-1][j-1]+2));
// System.out.println("dp[i][j-1]+1 = " + (dp[i][j-1]+1));
// System.out.println("dp[i-1][j]+1 = " + (dp[i-1][j]+1));
// System.out.println((dp[i-1][j]+1) + "和" + (dp[i][j-1]+1) +
// "的最小值为:" + Math.min(dp[i][j-1]+1, dp[i-1][j]+1));
// System.out.println("最后dp[i][j] = " + (dp[i][j]));
// }
}
}
show(dp);
}
return dp[len1][len2];
}
https://leetcode-cn.com/problems/edit-distance/
public int minDistance(String word1, String word2) {
int len1 = word1.length();
int len2 = word2.length();
if(len1 == 0) return len2;
if(len2 == 0) return len1;
int[][] dp = new int[len1+1][len2+1];
for (int i=0; i<=len1; i++) dp[i][0] = i;
for (int j=0; j<=len2; j++) dp[0][j] = j;
for(int i=1; i<=len1; i++){
for(int j=1; j<=len2; j++){
//1.当前比较字符相同,直接等于左上角
if(word1.charAt(i-1) == word2.charAt(j-1)){
dp[i][j] = dp[i-1][j-1];
}else{
/*
* 1. 增或删
* ①word1删,dp[i - 1][j] + 1
* ①word2删,dp[i][j - 1] + 1
* 2. 替换
* dp[i - 1][j - 1] + 1
*/
dp[i][j] = Math.min(dp[i-1][j-1],
Math.min(dp[i][j-1], dp[i-1][j])) + 1;
}
}
}
return dp[len1][len2];
}
public int countSubstrings(String s) {
int len = s.length();
if(len == 0) return 0;
boolean[][] dp = new boolean[len][len];
int res = 0;
for(int i=len-1; i>=0; i--){
for(int j=i; j<len; j++){
if(s.charAt(i) == s.charAt(j)){
if(i == j || j-i == 1 || dp[i+1][j-1] == true){
dp[i][j] = true;
res++;
}
}
}
show(dp);
}
return res;
}
https://leetcode-cn.com/problems/longest-palindromic-subsequence/
public int longestPalindromeSubseq(String s) {
int len = s.length();
if(len == 0) return 0;
int[][] dp = new int[len][len];
for(int i=len-1; i>=0; i--){
for(int j=i; j<len; j++){
if(i == j){//对角线都是1
dp[i][j] = 1; continue;
}
if(s.charAt(i) == s.charAt(j)){//相等时,左下角加2
dp[i][j] = dp[i+1][j-1] + 2;
}else{//不等时,左边或者下边的max
dp[i][j] = Math.max(dp[i+1][j], dp[i][j-1]);
}
}
}
return dp[0][len-1];
}