请用java语言写出求解最长不下降子序列长度并用nlogn复杂度完成,并使用动态规划思想两种解答给我
时间: 2024-12-11 09:17:23 浏览: 15
在Java中,可以使用动态规划(Dynamic Programming)方法解决最长不下降子序列(Longest Increasing Subsequence, LIS)问题。这里提供两种常见算法的实现:
1. **迭代法(在线空间)**:
```java
public int lengthOfLIS(int[] nums) {
if (nums == null || nums.length == 0) return 0;
int[] dp = new int[nums.length];
dp[0] = 1;
for (int i = 1; i < nums.length; i++) {
int maxSoFar = 0;
for (int j = 0; j < i; j++) {
if (nums[i] > nums[j]) {
maxSoFar = Math.max(dp[j], maxSoFar);
}
}
dp[i] = maxSoFar + 1;
}
return Arrays.stream(dp).max().getAsInt();
}
```
在这个版本中,我们维护了一个数组`dp`,其中`dp[i]`表示以`nums[i]`结尾的最长不下降子序列的长度。遍历数组,对于每个元素,找到所有小于它的元素的最大值对应的子序列长度加上1。
2. **递归法(离线空间)**:
```java
public int lengthOfLIS(int[] nums) {
if (nums == null || nums.length == 0) return 0;
int[] tailTable = new int[nums.length];
Arrays.fill(tailTable, -1); // 初始化tailTable全为-1
return findLength(nums, 0, tailTable);
}
private int findLength(int[] nums, int index, int[] tailTable) {
if (index >= nums.length) return 0;
int maxLength = 1;
for (int i = tailTable[index]; i != -1; i--) { // 从上一个位置开始找
int currentLength = 1 + findLength(nums, i + 1, tailTable);
maxLength = Math.max(maxLength, currentLength);
}
tailTable[index] = maxLength != 1 ? tailTable[findIndex(nums, maxLength)] : -1; // 更新tailTable
return maxLength;
}
private int findIndex(int[] nums, int targetLength) {
for (int i = 0; i < nums.length; i++) {
if (tailTable[i] == targetLength - 1) return i;
}
return -1;
}
```
这个递归版本首先构建了一个尾表`taiTable`,用于存储以某个位置作为起点的最长上升子序列结束的位置。然后在`findLength`函数里通过回溯找到最长子序列。
阅读全文