不间断子数组
难度:
标签:
题目描述
You are given a 0-indexed integer array nums
. A subarray of nums
is called continuous if:
- Let
i
,i + 1
, ...,j
be the indices in the subarray. Then, for each pair of indicesi <= i1, i2 <= j
,0 <= |nums[i1] - nums[i2]| <= 2
.
Return the total number of continuous subarrays.
A subarray is a contiguous non-empty sequence of elements within an array.
Example 1:
Input: nums = [5,4,2,4] Output: 8 Explanation: Continuous subarray of size 1: [5], [4], [2], [4]. Continuous subarray of size 2: [5,4], [4,2], [2,4]. Continuous subarray of size 3: [4,2,4]. Thereare no subarrys of size 4. Total continuous subarrays = 4 + 3 + 1 = 8. It can be shown that there are no more continuous subarrays.
Example 2:
Input: nums = [1,2,3] Output: 6 Explanation: Continuous subarray of size 1: [1], [2], [3]. Continuous subarray of size 2: [1,2], [2,3]. Continuous subarray of size 3: [1,2,3]. Total continuous subarrays = 3 + 2 + 1 = 6.
Constraints:
1 <= nums.length <= 105
1 <= nums[i] <= 109
代码结果
运行时间: 133 ms, 内存: 24.5 MB
/*
* 思路:
* 使用Java Stream API实现相同的逻辑
*/
import java.util.stream.IntStream;
public class ContinuousSubarraysStream {
public static int countContinuousSubarrays(int[] nums) {
return IntStream.range(0, nums.length)
.mapToObj(i -> new int[]{i, i})
.mapToInt(p -> {
int start = p[0];
int end = p[1];
while (end < nums.length && (end == start || Math.abs(nums[end] - nums[end - 1]) <= 2)) {
end++;
}
return end - start;
})
.sum();
}
}
解释
方法:
该题解采用了一个双指针技术来确定符合条件的不间断子数组。指针i作为子数组的起始点,而指针j从i开始向后遍历,检查每个新元素是否能扩展当前的不间断子数组。为了判断是否满足不间断条件,算法维护了当前子数组中的最大值maxV和最小值minV,并更新这两个值随着j的增加。如果这两个值的差大于2,表明当前子数组已不再满足条件,因此计算到目前为止的所有可能子数组数目,并调整i的位置来尝试新的子数组。如果j到达数组末尾而没有超过范围,那么将当前子数组的计数加入最终结果中。此外,对于单个元素的子数组,最后结果需再加上n。
时间复杂度:
O(n^2)
空间复杂度:
O(1)
代码细节讲解
🦆
在算法中,如何精确地维护并更新maxV和minV的值?是否在每次循环中都重新计算,还是有其他优化方法?
▷🦆
为什么在maxV和minV的差大于2时,内部while循环要检查`abs(nums[j] - nums[j - k]) <= 2`?这个条件是如何与题目要求关联的?
▷🦆
题解中提到,当maxV和minV的差大于2时会重新调整i的位置。具体是如何决定新的i的位置?这种调整是否可能导致遗漏某些有效的子数组?
▷🦆
算法在最后使用了复杂的数学公式来计算子数组的数量,这个计算过程是否正确?具体的公式逻辑是什么?
▷