得到山形数组的最少删除次数
难度:
标签:
题目描述
代码结果
运行时间: 62 ms, 内存: 16.3 MB
/*
* Solution in Java using Java Stream
* The approach remains the same: find LIS and LDS for each index.
* Java Stream is used to manage collections and operations more succinctly.
*/
import java.util.*;
import java.util.stream.IntStream;
public class StreamSolution {
public int minimumMountainRemovals(int[] nums) {
int n = nums.length;
int[] lis = new int[n];
int[] lds = new int[n];
Arrays.fill(lis, 1);
Arrays.fill(lds, 1);
// Calculate LIS using streams
IntStream.range(1, n).forEach(i -> {
IntStream.range(0, i).forEach(j -> {
if (nums[i] > nums[j]) {
lis[i] = Math.max(lis[i], lis[j] + 1);
}
});
});
// Calculate LDS using streams
IntStream.range(0, n - 1).map(i -> n - 2 - i).forEach(i -> {
IntStream.range(i + 1, n).forEach(j -> {
if (nums[i] > nums[j]) {
lds[i] = Math.max(lds[i], lds[j] + 1);
}
});
});
int maxMountainLength = IntStream.range(1, n - 1).filter(i -> lis[i] > 1 && lds[i] > 1)
.map(i -> lis[i] + lds[i] - 1).max().orElse(0);
return n - maxMountainLength;
}
}
解释
方法:
题解的思路是首先用动态规划的方法分别计算数组中每个元素作为山顶的左侧的最长递增子序列长度和右侧的最长递减子序列长度。使用二分搜索优化的方法,通过两个辅助数组(或列表)来存储左侧和右侧的最长递增子序列的长度。对于右侧,从右向左遍历数组,并利用二分搜索在维护的递增序列中找到合适的位置更新或添加元素,并记录每个位置的最长递增子序列长度。对于左侧,从左向右同样操作,并同时检查如果当前元素既有左侧也有右侧子序列,则尝试更新最大的山顶长度。最后,数组的长度减去最大的山顶长度即为需要删除的元素个数,从而得到最少的删除次数。
时间复杂度:
O(n log n)
空间复杂度:
O(n)
代码细节讲解
🦆
在题解中,你提到了使用动态规划和二分搜索,能否详细解释如何结合这两种方法来优化解题过程?
▷🦆
题解中提到使用两个辅助数组来分别存储左侧和右侧的最长递增子序列长度,为什么选择这种数据结构而不是其他的?
▷🦆
在维护左侧和右侧递增序列时,你选择了二分搜索来插入或更新元素。这种方法在什么情况下可能会导致不准确或效率低下?
▷🦆
你如何确保每个元素作为山顶时的左侧最长递增序列和右侧最长递减序列长度正确无误地被计算和记录?
▷