算法训练(leetcode)二刷第三十七天 | *300. 最长递增子序列、674. 最长连续递增序列、*718. 最长重复子数组

刷题记录

*300. 最长递增子序列

leetcode题目地址

dp数组含义:

dpi表示以numsi结尾的最长递增子序列长度,即以numsi结尾的子序列的长度。

j从0向i遍历,遇到numi > numj, dpi = max(dpj+1, dpi);

时间复杂度: O ( n 2 ) O(n^2) O(n2)
空间复杂度: O ( n ) O(n) O(n)

java 复制代码
// java
class Solution {
    public int lengthOfLIS(int[] nums) {
        int len = nums.length; 
        int[] dp = new int[len];
        int result = 1;
        // for(int i=0; i<len; i++) dp[i] = 1;
        Arrays.fill(dp, 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);
            }
            if(result < dp[i]) result = dp[i];
        }
        return result;
    }
}

674. 最长连续递增序列

leetcode题目地址

基础解法(非动规)

求最长连续递增子序列,统计子序列记录最长即可。在递增中断时,计数器要置为1而非0,因为下一个子序列从当前元素开始。

时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( n ) O(n) O(n)

java 复制代码
// java
class Solution {
    public int findLengthOfLCIS(int[] nums) {
        int result = 1;
        int cnt = 1;
        int len = nums.length;
        for(int i=1; i<len; i++){
            if(nums[i]>nums[i-1]) {
                cnt++;
                if(cnt > result) result = cnt;
            }
            else cnt = 1; // 计数器置为1
            
        }
        return result;
    }
}

动态规划

dp数组含义:

dpi表示以numsi结尾的最长连续递增子序列的长度。

初始化:

每个元素本身就是一个连续递增子序列,因此初始化为1,即dp数组均初始化为1。

java 复制代码
// java
class Solution {
    public int findLengthOfLCIS(int[] nums) {

        int len = nums.length;
        int[] dp = new int[len];
        Arrays.fill(dp, 1);
        int result = 1;
        for(int i=1; i<len; i++){
            if(nums[i] > nums[i-1]) dp[i] = dp[i-1]+1;
            result = Math.max(result, dp[i]);
        }
        return result;
        
    }
}

718. 最长重复子数组

leetcode题目地址

dp数组含义:

dpij表示 以nums1i-1结尾的子数组A 和以 以nums2j-1结尾的子数组B 的最长重复子数组长度。

这里为什么要用i-1和j-1?

因为dpij的更新依赖于dpi-1j-1的值。也就是说,在nums1i-1和nums2j-1相等时,更新对应位置长度需要依赖nums1i-2和nums2j-2的最长重复子数组长度。

以题目示例1举例:nums1 = 1,2,3,2,1, nums2 = 3,2,1,4,7

  • 当nums12 == nums20时,当前位置的最长重复子数组长度依赖于前面的匹配情况,前面相等的串长度为0,因此这里dp31是1。
  • 当nums13 == nums21时,逻辑同上,dp42的更新依赖于前面的匹配情况,前面有一个元素匹配到,因此这里dp42 = dp31+1 = 2
  • 当nums14 == nums22时,逻辑同上,dp53的更新依赖于前面的匹配情况,前面有两个元素匹配到,因此这里dp53 = dp42+1 = 3

到这里就可以总结出状态转移方程,dpij = dpi-1j-1 + 1

由于这里使用了i-1和j-1,在i和j为0时会越界。 因此整体将dp数组下标后移一位,来解决这一问题。(也可单独处理i和j为0的情况,较复杂)

时间复杂度: O ( n 2 ) O(n^2) O(n2)
空间复杂度: O ( n ) O(n) O(n)

java 复制代码
// java
class Solution {
    public int findLength(int[] nums1, int[] nums2) {
        int len1 = nums1.length;
        int len2 = nums2.length;
        
        int[][] dp = new int[len1+1][len2+1];

        int result  = 0;
        if(nums1[0] == nums2[0]) dp[1][1] = 1;
        for (int i=1; i<=len1; i++){
            for(int j=1; j<=len2; j++){
                if(nums1[i-1] == nums2[j-1]){
                    dp[i][j] = dp[i-1][j-1]+1;
                }
                result = Math.max(result, dp[i][j]);
                // System.out.print(dp[i][j] + " ");
            }
            // System.out.println();
        }
        return result;
    }
}

滚动数组

注意:

1、思路同上,只是每一层的状态是从上一层拷贝下来的,因此在遍历nums2时要从后向前,防止将前面元素在上一层的状态覆盖

2、当遇到元素不相同是要将对应位置赋值0.

java 复制代码
// java
class Solution {
    public int findLength(int[] nums1, int[] nums2) {
        int len1 = nums1.length;
        int len2 = nums2.length;
        
        int[] dp = new int[len2+1];

        int result  = 0;
        for (int i=1; i<=len1; i++){
            for(int j=len2; j>=1; j--){
                if(nums1[i-1] == nums2[j-1]){
                    dp[j] = dp[j-1]+1;
                } else dp[j] = 0; // 注意这里不相等的时候要有赋0的操作
                result = Math.max(result, dp[j]);
                
            }
            
        }
        return result;
    }
}
相关推荐
倒头就睡的小比特3 天前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!3 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼3 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
旖旎夜光3 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark3 天前
大规模并行计算中的负载均衡算法研究4
算法
Because_of_Her13 天前
并查集-听课笔记
笔记·算法·并查集
码流子3 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
another heaven3 天前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
wzdark3 天前
从算法设计模式看编程思维的抽象能力4
算法
2601_962218613 天前
万象生鲜系统称重自动多退少补算法解决生鲜非标品痛点
大数据·数据库·人工智能·python·算法