这题是dp经典问题 最长上升子序列
在10-08写过本题的题解,但是有点遗忘,再补一次,并且基础打卡是按照章节来的,也方便今后查找。
这是10-08的题解:最长上升子序列
主要是两次遍历,f[i] = Math.max(f[i], f[j] + 1);
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
class Main {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static PrintWriter pw = new PrintWriter(System.out);
static int N = 1010, n;
static int f[] = new int[N], nums[] = new int[N];
public static void main(String[] args) throws Exception {
String[] s = br.readLine().split(" ");
n = Integer.parseInt(s[0]);
s = br.readLine().split(" ");
for (int i = 0; i < n; i++) nums[i] = Integer.parseInt(s[i]);
Arrays.fill(f, 1);
for (int i = 0; i < n; i++)
for (int j = 0; j < i; j++)
if (nums[i] > nums[j])
f[i] = Math.max(f[i], f[j] + 1);
int res = 0;
for (int i = 0; i < n; i++) res = Math.max(res, f[i]);
pw.println(res);
pw.flush();
pw.close();
br.close();
}
}
还有一个优化了一个N到logN的做法,不属于动态规划。用二分优化第二个N。
重新定义dp,设计一个排序列表,通过二分查找。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
class Main {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static PrintWriter pw = new PrintWriter(System.out);
static int N = 1010, n, res;
static int f[] = new int[N], nums[] = new int[N];
public static void main(String[] args) throws Exception {
String[] s = br.readLine().split(" ");
n = Integer.parseInt(s[0]);
s = br.readLine().split(" ");
for (int i = 0; i < n; i++) nums[i] = Integer.parseInt(s[i]);
for (int num : nums) {
int i = 0, j = res;
while (i < j) {
int m = i + j >> 1;
if (f[m] < num) i = m + 1;
else j = m;
}
f[i] = num;
if (res == j) res++;
}
pw.println(res);
pw.flush();
pw.close();
br.close();
}
}