文章目录
前言
线性DP同样作为DP领域中非常重要的一部分,其指的是状态之间含有某种线性关系,大多求最大/最小值。最典型的题目为子序列,编辑距离,股票问题。
一、序列问题
1. 最长上升子序列
Acwing 897
给定一个长度为 N 的数列,求数值严格单调递增的子序列的长度最长是多少。
当N的数据量并不大时 (10^4) ,可以直接使用朴素解法,即 O(n^2) 的时间复杂度,否则需要优化解法,即 O(nlogn) 的时间复杂度。
1.1 朴素写法
- 设置状态数组f[i],表示以 nums[i] 结尾的数可以构成的最长上升子序列长度。
- 状态转移方程: 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[i−1])+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) 的时间复杂度来确定每一个数所能构成的最优最长上升子序列。
- 构造遍历到当前数的最长上升子序列数组 ans