简介
最长递增子序列:输入一个无序的整数数组,请你找到其中最长递增子序列的长度。例如,输入nums=[10, 9, 2, 5, 3, 7, 101, 18],其中最长的递增子序列是[2, 3, 7, 101],算法输出4。
该题有两种主流的解法,一种是使用动态规划法,另一种为二分搜索解法。
动态规划解法代码
package com.company;
import static java.lang.System.out;
import java.util.*;
public class Main {
public static int lengthOfLIS(int[] nums){
int[] dp = new int[nums.length];
Arrays.fill(dp, 1);
for (int i = 0; i < nums.length; i++) {
for (int j = 0; j < i; j++) {
if (nums[j] < nums[i]){
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
}
int res = 0;
for (int i = 0; i < dp.length; i++) {
res = Math.max(res, dp[i]);
}
return res;
}
public static void main(String[] args) {
int[] nums = {10, 9, 2, 5, 3, 7, 101, 18};
int res = lengthOfLIS(nums);
out.println(res); // 4
}
}
二分搜索解法
package com.company;
import static java.lang.System.out;
public class Main {
public static int lengthOfLIS(int[] nums){
int[] top = new int[nums.length];
// 牌堆数初始化为0
int piles = 0;
for (int i = 0; i < nums.length; i++) {
// 要处理的扑克牌
int poker = nums[i];
/***** 搜索左边界的二分搜索 *****/
int left = 0, right = piles - 1;
while (left <= right){
int mid = left + (right - left) / 2;
if (top[mid] == poker)
right = mid -1;
else if (top[mid] < poker)
left = mid + 1;
else if (top[mid] > poker)
right = mid - 1;
}
/*****************************/
// 没找到合适的牌堆,新建一堆
if (left == piles) piles++;
// 把这张牌放到堆顶
top[left] = poker;
}
// 牌堆数就是LIS的长度
return piles;
}
public static void main(String[] args) {
int[] nums = {10, 9, 2, 5, 3, 7, 101, 18};
int res = lengthOfLIS(nums);
out.println(res); // 4
}
}