题解 | #最长上升子序列(一)# 【动态规划】/【贪心+二分】
最长上升子序列(一)
http://www.nowcoder.com/practice/5f65ccbb025240bd8458eb6479c2612e
方法一:动态规划
- 时间复杂度:
- 空间复杂度:
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
PrintWriter pw = new PrintWriter(System.out);
st.nextToken();
int n = (int) st.nval;
int[] nums = new int[n];
for (int i = 0; i < n; i++) {
st.nextToken();
nums[i] = (int) st.nval;
}
// f[i] 表示以下标为i的数字结尾的最长上升子序列的长度
int[] f = new int[n];
for (int i = 0; i < n; i++) {
f[i] = 1;
for (int j = 0; j < i; j++) {
if (nums[j] < nums[i]) {
f[i] = Math.max(f[i], f[j] + 1);
}
}
}
int ans = 1;
for (int i = 0; i < n; i++) {
ans = Math.max(ans, f[i]);
}
pw.println(ans);
pw.flush();
pw.close();
}
}
贪心 + 二分
- 时间复杂度:
- 空间复杂度:
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
PrintWriter pw = new PrintWriter(System.out);
st.nextToken();
int n = (int) st.nval;
int[] nums = new int[n];
for (int i = 0; i < n; i++) {
st.nextToken();
nums[i] = (int) st.nval;
}
// q[i] 表示长度为i的上升子序列的结尾数字
int[] q = new int[n + 1];
int ans = 0;
for (int i = 0; i < n; i++) {
// 二分找到小于nums[i]的最大的那个
int l = 0, r = ans;
while (l < r) {
int mid = l + r + 1 >> 1;
if (q[mid] < nums[i]) {
l = mid;
} else {
r = mid - 1;
}
}
q[r + 1] = nums[i];
ans = Math.max(ans, r + 1);
}
pw.println(ans);
pw.flush();
pw.close();
}
}