和等于 k 的最长子数组长度
难度:
标签:
题目描述
代码结果
运行时间: 99 ms, 内存: 57.9 MB
/*
* 题目思路:
* 1. 我们需要找到和等于 k 的最长子数组长度。
* 2. 使用一个哈希图来存储当前前缀和和它对应的索引。
* 3. 使用流处理数组,计算当前的前缀和。
* 4. 使用Optional和map处理逻辑。
*/
import java.util.HashMap;
import java.util.Optional;
import java.util.stream.IntStream;
public class Solution {
public int maxSubArrayLen(int[] nums, int k) {
HashMap<Integer, Integer> prefixSumMap = new HashMap<>();
final int[] maxLen = {0};
final int[] prefixSum = {0};
IntStream.range(0, nums.length).forEach(i -> {
prefixSum[0] += nums[i];
if (prefixSum[0] == k) {
maxLen[0] = i + 1;
}
Optional.ofNullable(prefixSumMap.get(prefixSum[0] - k)).ifPresent(index -> {
maxLen[0] = Math.max(maxLen[0], i - index);
});
prefixSumMap.putIfAbsent(prefixSum[0], i);
});
return maxLen[0];
}
}
解释
方法:
这个题解使用前缀和和哈希表的方法来解决问题。通过维护一个哈希表,记录每个前缀和出现的最早下标,然后在遍历数组的过程中,检查当前前缀和减去目标值 k 是否在哈希表中出现过。如果出现过,则更新最长子数组的长度。这样可以在遍历一次数组的过程中,找到和等于 k 的最长子数组的长度。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
为什么在哈希表中初始存入累积和0对应的下标-1?这样的初始化有什么特殊意义吗?
▷🦆
在更新最长子数组长度时,为什么只考虑累积和等于`current_sum - k`的情况?这种方法是否覆盖了所有可能的和为k的子数组?
▷🦆
如果当前累积和已经在哈希表中存在,为什么不更新其对应的下标?保持最早出现的下标有什么优势?
▷相关问题
长度最小的子数组
给定一个含有 n
个正整数的数组和一个正整数 target
。
找出该数组中满足其总和大于等于 target
的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度。如果不存在符合条件的子数组,返回 0
。
示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3]
是该条件下的长度最小的子数组。
示例 2:
输入:target = 4, nums = [1,4,4] 输出:1
示例 3:
输入:target = 11, nums = [1,1,1,1,1,1,1,1] 输出:0
提示:
1 <= target <= 109
1 <= nums.length <= 105
1 <= nums[i] <= 105
进阶:
- 如果你已经实现
O(n)
时间复杂度的解法, 请尝试设计一个O(n log(n))
时间复杂度的解法。
区域和检索 - 数组不可变
给定一个整数数组 nums
,处理以下类型的多个查询:
- 计算索引
left
和right
(包含left
和right
)之间的nums
元素的 和 ,其中left <= right
实现 NumArray
类:
NumArray(int[] nums)
使用数组nums
初始化对象int sumRange(int i, int j)
返回数组nums
中索引left
和right
之间的元素的 总和 ,包含left
和right
两点(也就是nums[left] + nums[left + 1] + ... + nums[right]
)
示例 1:
输入: ["NumArray", "sumRange", "sumRange", "sumRange"] [[[-2, 0, 3, -5, 2, -1]], [0, 2], [2, 5], [0, 5]] 输出: [null, 1, -1, -3] 解释: NumArray numArray = new NumArray([-2, 0, 3, -5, 2, -1]); numArray.sumRange(0, 2); // return 1 ((-2) + 0 + 3) numArray.sumRange(2, 5); // return -1 (3 + (-5) + 2 + (-1)) numArray.sumRange(0, 5); // return -3 ((-2) + 0 + 3 + (-5) + 2 + (-1))
提示:
1 <= nums.length <= 104
-105 <= nums[i] <= 105
0 <= i <= j < nums.length
- 最多调用
104
次sumRange
方法
连续数组
给定一个二进制数组 nums
, 找到含有相同数量的 0
和 1
的最长连续子数组,并返回该子数组的长度。
示例 1:
输入: nums = [0,1] 输出: 2 说明: [0, 1] 是具有相同数量 0 和 1 的最长连续子数组。
示例 2:
输入: nums = [0,1,0] 输出: 2 说明: [0, 1] (或 [1, 0]) 是具有相同数量0和1的最长连续子数组。
提示:
1 <= nums.length <= 105
nums[i]
不是0
就是1
乘积小于 K 的子数组
给你一个整数数组
nums
和一个整数 k
,请你返回子数组内所有元素的乘积严格小于 k
的连续子数组的数目。
示例 1:
输入:nums = [10,5,2,6], k = 100 输出:8 解释:8 个乘积小于 100 的子数组分别为:[10]、[5]、[2],、[6]、[10,5]、[5,2]、[2,6]、[5,2,6]。 需要注意的是 [10,5,2] 并不是乘积小于 100 的子数组。
示例 2:
输入:nums = [1,2,3], k = 0 输出:0
提示:
1 <= nums.length <= 3 * 104
1 <= nums[i] <= 1000
0 <= k <= 106