最长递增子序列 II
难度:
标签:
题目描述
代码结果
运行时间: 809 ms, 内存: 48.5 MB
/*
* 思路:
* 使用Java Stream进行处理,我们需要先对数组进行预处理,以便使用动态规划来求解。
* 我们可以使用一个数组dp来存储以每个元素结尾的最长递增子序列长度。
* 由于Stream不适合直接进行动态规划,我们可以将其用作辅助工具来处理部分逻辑。
*/
import java.util.Arrays;
public class Solution {
public int longestSubsequence(int[] nums, int k) {
int n = nums.length;
int[] dp = new int[n];
Arrays.fill(dp, 1);
for (int i = 1; i < n; i++) {
int finalI = i;
dp[i] = Arrays.stream(dp, 0, i)
.filter(j -> nums[finalI] > nums[j] && nums[finalI] - nums[j] <= k)
.map(j -> dp[j] + 1)
.max()
.orElse(1);
}
return Arrays.stream(dp).max().orElse(1);
}
}
解释
方法:
本题解采用的是基于归并排序的分治策略来处理问题,并结合动态规划(DP)和双端队列(deque)优化查找过程。首先,使用一个DP数组dp来保存以每个元素结尾的最长子序列的长度。同时,数组p用于存储nums中元素的索引,按照元素值进行排序,对于相同值的情况按照索引逆序排序。通过分治方法,对索引数组p进行递归划分,对每个子数组,利用双端队列dq维护可能的子序列候选。在处理过程中,如果当前元素索引小于等于中点,更新队列;如果大于中点,通过队列来更新dp数组。整体算法通过不断的分治和合并来构建可能的最长递增子序列。最终返回dp数组中的最大值,即为所求的最长子序列长度。
时间复杂度:
O(n log n)
空间复杂度:
O(n)
代码细节讲解
🦆
在使用归并排序的分治策略时,您是如何确保在子数组中维持元素的原始顺序?
▷🦆
您提到使用了一个双端队列来优化查找过程,请问这样做主要解决了什么问题?
▷🦆
在分治法中,对于元素索引的排序和逆序排序有何作用,它们是如何影响算法性能的?
▷🦆
您如何处理元素值相同但索引不同的情况?排序时对这种情况有什么特别的考虑吗?
▷