基础算法 --- 线性DP

本文详细介绍了线性动态规划(DP)在解决序列问题中的应用,包括最长上升子序列和最短编辑距离。讨论了如何优化最长上升子序列的解法,通过二分查找和TreeSet实现。同时阐述了最长公共子序列的朴素写法。编辑距离部分解释了如何通过状态转移方程找到从一个字符串转换到另一个的最小操作次数。
摘要由CSDN通过智能技术生成


前言

线性DP同样作为DP领域中非常重要的一部分,其指的是状态之间含有某种线性关系,大多求最大/最小值。最典型的题目为子序列编辑距离股票问题


一、序列问题

1. 最长上升子序列

Acwing 897
给定一个长度为 N 的数列,求数值严格单调递增的子序列的长度最长是多少。
当N的数据量并不大时 (10^4) ,可以直接使用朴素解法,即 O(n^2) 的时间复杂度,否则需要优化解法,即 O(nlogn) 的时间复杂度。

1.1 朴素写法

  1. 设置状态数组f[i],表示以 nums[i] 结尾的数可以构成的最长上升子序列长度。
  2. 状态转移方程: f [ i ] = M a x ( f [ 0 ] , f [ 1 ] , . . . , f [ i − 1 ] ) + 1 f[i] = Max(f[0], f[1], ..., f[i-1]) + 1 f[i]=Max(f[0],f[1],...,f[i1])+1当然括号内的 f[j] 应该满足 n u m s [ i ] > n u m s [ j ] nums[i] > nums[j] nums[i]>nums[j]
import java.util.*;

public class Main {
   
    public static void main(String[] args) {
   
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[] nums = new int[n];
        for (int i = 0; i < n; i ++) {
   
            nums[i] = in.nextInt();
        }
        int[] f = new int[n];
        
        Arrays.fill(f, 1);
        
        for (int i = 1; i < n; i ++) {
   
            for (int j = 0; j < i; j ++) {
   
                if (nums[i] > nums[j]) {
   
                    f[i] = Math.max(f[i], f[j] + 1);
                }
            }
        }
        
        System.out.println(Arrays.stream(f).max().getAsInt());
    }
}

1.2 优化写法

时间复杂度 O(nlogn),可以理解为以 O(n) 的时间复杂度来遍历整个数组,再用 O(logn) 的时间复杂度来确定每一个数所能构成的最优最长上升子序列。

  1. 构造遍历到当前数的最长上升子序列数组 ans
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值