方法一:动态规划
class Solution {
public int lengthOfLIS(int[] nums) {
// dp[i] 即以 nums[i] 这个数结尾的最长递增子序列的长度
int dp[] = new int[nums.length];
// base case
// 以 nums[i] 这个数结尾的最长递增子序列至少包含自己本身 初始化为 1
Arrays.fill(dp, 1);
for (int i = 0; i < nums.length; i++) {
for (int j = 0; j < i; j++) {
// 状态转移 当前下标 i 对应数值大于下标 j 对应数值才会得到更长的子序列 即 + 1 操作
if (nums[j] < nums[i]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
}
int ans = 0;
for (int i = 0; i < dp.length; i++) {
ans = Math.max(ans, dp[i]);
}
return ans;
}
}
进阶:方法二 二分查找 patience game 纸牌游戏的规律得出
class Solution {
public 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;
int right = piles;
while (left <= right) {
int mid = (left + right) / 2;
if (top[mid] > poker) {
right = mid - 1;
} else if (top[mid] < poker) {
left = mid + 1;
} else {
right = mid;
}
}
// 没找到合适的牌堆,新建一堆
if (left > piles) {
piles++;
}
// 把这张牌放到牌堆顶
top[left] = poker;
}
// 牌堆数就是最长子序列的长度
return piles;
}
}