题目描述
给定一个无序的整数数组,找到其中最长上升子序列的长度
样例
输入:[10,9,2,5,3,7,101,18]
输出:[2,5,7,101],最长上升子序列的长度是4,其中,最长上升子序列可能存在多个
1.暴力枚举
private static int max;
public static void main(String[] args) {
int[] a = {10,9,2,5,3,7,101,18};
System.out.println(lengthOfLIS(a));
}
private static int lengthOfLIS(int[] nums) {
// 暴力搜索
dfs(0, nums,0, -1); // p表示从下标p的位置开始枚举,cur表示当前上升子序列的长度,pre表示上一个元素的下标
return max;
}
public static void dfs(int p, int[] a, int cur, int pre) {
max = Math.max(max, cur);
for (int i = p; i < a.length; i++) {
if (pre == -1 || a[i] > a[pre]) {
dfs(i+1, a, cur + 1, i);
}
}
}
2.DP
dp[i]:表示以下标i结尾的上升子序列的长度
初始化:dp[i]=1 每一个元素本身就是一个上升子序列
状态转移:dp[i]=max(dp[j], j <i && nums[j] < nums[i])
返回值:ans=max(dp[i])
public int lengthOfLIS(int[] nums) {
// 动态规划
int len = nums.length;
int[] dp = new int[len];
// 初始化
Arrays.fill(dp, 1);
// 状态转移
for (int i = 1; i < len; i++) {
int max = 0;
for (int j = 0; j < i; j++) {
if (nums[j] < nums[i]) {
max = Math.max(max, dp[j]);
}
}
dp[i] = max + 1;
}
// 返回值
int ans = 0;
for (int i = 0; i < len; i++) {
ans = Math.max(ans, dp[i]);
}
return ans;
}