最长半递减数组
难度:
标签:
题目描述
代码结果
运行时间: 61 ms, 内存: 29.6 MB
/*
* LeetCode 2863: Longest Semi-Decreasing Subarray using Java Streams
*
* Problem Statement:
* Given an array of integers, find the length of the longest semi-decreasing subarray.
* A semi-decreasing subarray is one where for any two consecutive elements a[i] and a[i+1], a[i] >= a[i+1].
*
* Approach:
* 1. Convert the array to a list of indexes.
* 2. Use stream operations to find the longest semi-decreasing subarray.
* 3. Iterate through the list with a reduction operation to keep track of the longest subarray length.
*/
import java.util.*;
import java.util.stream.*;
public class Solution {
public int longestSemiDecreasingSubarray(int[] nums) {
if (nums.length == 0) return 0;
return IntStream.range(0, nums.length - 1)
.mapToObj(i -> nums[i] >= nums[i + 1] ? 1 : 0)
.collect(ArrayList::new, (list, val) -> {
if (val == 1) {
if (!list.isEmpty() && list.get(list.size() - 1) > 0) {
list.set(list.size() - 1, list.get(list.size() - 1) + 1);
} else {
list.add(1);
}
} else {
list.add(0);
}
}, ArrayList::addAll)
.stream()
.max(Integer::compare)
.orElse(1);
}
}
解释
方法:
这个解法利用了栈结构来保存数组中的元素下标。首先,遍历数组元素从右到左,将那些满足当前元素值小于栈顶元素值对应的数组元素的下标压入栈中。这样可以保证栈中元素下标对应的数组值是递减的。接着,从左到右遍历数组,每遇到一个元素,都尝试将栈顶的下标弹出,直到栈顶元素对应的数组值小于等于当前元素。对于每一个弹出的下标,计算当前位置与该下标的差,加1得到一个潜在的最长半递减数组的长度,并更新最大长度。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
在题解中,你提到了从右到左遍历数组时仅当当前元素小于栈顶元素对应的数组值时才进行压栈,这样的设计目的是什么?
▷🦆
为什么在从左到右遍历数组时需要比较当前元素与栈顶元素对应的数组值,并在当前元素大于栈顶元素时弹出栈顶?这样的操作有什么算法上的意义?
▷🦆
题解中提到的`最长半递减数组`具体是如何定义的?解法中如何确保所找到的数组段确实满足半递减的条件?
▷🦆
在题解的实现中,计算最大长度使用了`popIdx - i + 1`,这里的加1是基于什么考虑?
▷