package com.heu.wsq.leetcode.dp;
/**
* 397 · 最长上升连续子序列
* @author wsq
* @date 2021/4/25
* 描述
* 给定一个整数数组(下标从 0 到 n-1, n 表示整个数组的规模),请找出该数组中的最长上升连续子序列。(最长上升连续子序列可以定义为从右到左或从左到右的序列。)
*
* 样例
*
* 样例 1:
* 输入:[5, 4, 2, 1, 3]
* 输出:4
* 解释:
* 给定 [5, 4, 2, 1, 3],其最长上升连续子序列(LICS)为 [5, 4, 2, 1],返回 4。
* 样例 2:
* 输入:[5, 1, 2, 3, 4]
* 输出:4
* 解释:
* 给定 [5, 1, 2, 3, 4],其最长上升连续子序列(LICS)为 [1, 2, 3, 4],返回 4。
* 挑战
* 使用 O(n) 时间和 O(1) 额外空间来解决
*/
public class LongestIncreasingContinuousSubsequence {
private int ans = 0;
public int longestIncreasingContinuousSubsequence(int[] A) {
if(A == null || A.length == 0){
return 0;
}
int n = A.length;
calc(A, n);
// 反转数组
reverse(A);
// 反转后再次计算,因为文中说了可以从左到右和从右到左
calc(A, n);
return ans;
}
private void reverse(int[] A){
int left = 0;
int right = A.length - 1;
while (left < right){
int t = A[left];
A[left] = A[right];
A[right] = t;
left++;
right--;
}
}
private void calc(int[] nums, int n){
// 由于每一步计算只需要i-1的最长上升子序列的长度,因此可以尝试用O(1)的时间复杂度去做。
// int[] f = new int[n];
// 采用滚动数组压缩空间消耗
// f[i] 表示以元素i结尾的最长上升子序列的长度
int[] f = new int[2];
// int old = 0;
// int curr = 0;
int old = 0, now = 1;
for(int i = 0; i < n; i++){
old = now;
now = 1 - now;
f[now] = 1;
if(i > 0 && nums[i] > nums[i-1]){
f[now] = f[old] + 1;
}
if(f[now] > ans){
ans = f[now];
}
}
}
}
397 · 最长上升连续子序列(动态规划)
最新推荐文章于 2022-03-29 23:03:39 发布