请用java语言写出求解最长不下降子序列长度并用nlogn复杂度完成,并用两种解答给我
时间: 2024-12-11 16:17:55 浏览: 9
在 Java 中,我们可以使用动态规划结合二分查找来解决这个问题,这是一种时间复杂度为 O(n log n) 的解决方案。以下是两种不同的实现方法:
**方法一:哈希表辅助 + 二分查找**
```java
import java.util.HashMap;
import java.util.Map;
public class LongestIncreasingSubsequence {
public static int lengthOfLIS(int[] nums) {
if (nums == null || nums.length == 0) return 0;
Map<Integer, Integer> tailMap = new HashMap<>();
tailMap.put(nums[0], 0);
for (int i = 1; i < nums.length; i++) {
int prevTailIndex = -1;
for (int j = 0; j <= tailMap.size(); j++) {
if (tailMap.containsKey(nums[i] - j)) {
prevTailIndex = tailMap.get(nums[i] - j);
break;
}
}
tailMap.put(nums[i], i);
if (prevTailIndex != -1) {
tailMap.putAtLeast(prevTailIndex + 1, i);
}
}
// 使用二分查找获取最长子序列长度
int maxLength = 0;
for (int value : tailMap.values()) {
maxLength = Math.max(maxLength, value + 1);
}
return maxLength;
}
}
```
**方法二:使用单调栈**
```java
import java.util.Stack;
public class LongestIncreasingSubsequence {
public static int lengthOfLIS(int[] nums) {
if (nums == null || nums.length == 0) return 0;
Stack<Integer> stack = new Stack<>();
int[] tails = new int[nums.length];
tails[0] = nums[0];
for (int i = 1; i < nums.length; i++) {
while (!stack.isEmpty() && nums[i] > nums[stack.peek()]) {
tails[stack.pop()] = i;
}
stack.push(i);
}
int maxLength = 0;
for (int tail : tails) {
maxLength = Math.max(maxLength, tail + 1);
}
return maxLength;
}
}
```
在这两个方法中,第一个是借助哈希表记录每个元素最后能构成最长上升子序列的最后一个位置,然后通过二分查找找到最长的子序列长度。第二个方法则使用了单调栈,遍历过程中每次遇到新的更大元素,就将栈顶的元素出栈,更新其尾巴索引。
阅读全文