查找大小为 M 的最新分组
难度:
标签:
题目描述
代码结果
运行时间: 129 ms, 内存: 27.3 MB
/*
* 使用Java Stream的解法
* 1. 使用IntStream遍历 arr 数组。
* 2. 对于每个 arr[i],更新 steps 数组和哈希表。
* 3. 每次更新后,检查是否有长度为 m 的区间。
* 4. 如果存在,记录当前步骤。如果没有,则返回 -1。
*/
import java.util.stream.IntStream;
import java.util.HashMap;
public int findLatestStep(int[] arr, int m) {
if (arr.length == m) return m;
int n = arr.length;
int[] length = new int[n + 2];
HashMap<Integer, Integer> left = new HashMap<>();
HashMap<Integer, Integer> right = new HashMap<>();
int[] result = {-1};
IntStream.range(0, n).forEach(i -> {
int pos = arr[i];
int leftLen = length[pos - 1];
int rightLen = length[pos + 1];
int currLen = leftLen + rightLen + 1;
length[pos] = currLen;
length[pos - leftLen] = currLen;
length[pos + rightLen] = currLen;
left.put(pos - leftLen, pos + rightLen);
right.put(pos + rightLen, pos - leftLen);
if (leftLen == m || rightLen == m) {
result[0] = i;
}
});
return result[0];
}
解释
方法:
本题的核心思路是使用一个额外的数组 `cnt` 来记录每个位置的连续 '1' 的长度。数组 `cnt` 的长度为 `n + 2`,其中 `n` 是输入数组 `arr` 的长度。这样设置可以避免处理边界情况。\n\n过程如下:\n1. 遍历数组 `arr`,每个元素 `v` 对应的是将二进制字符串的第 `v-1` 位置设为 '1'。\n2. 对于每个 `v`,检查其左侧和右侧的连续 '1' 的长度,存储在变量 `l` 和 `r` 中。这些长度可以从 `cnt` 数组获得。\n3. 如果左侧或右侧的长度恰好为 `m`,则更新答案 `ans` 为当前步骤编号 `i`(从0开始计数)。\n4. 更新 `cnt` 数组,将新形成的连续 '1' 的长度记录在 `cnt[v-l]` 和 `cnt[v+r]` 中。\n5. 特殊情况是当 `m` 等于 `n` 时,按照题目的逻辑,只有当所有位都是 '1' 时,才返回 `n`。\n\n该方法避免了直接检查整个字符串的高开销,而是通过局部更新和记录来保持整体的连续区间长度信息。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
当更新cnt数组的左右边界值cnt[v-l]和cnt[v+r]时,为什么可以保证这样的更新不会影响到其他位置的正确性?
▷🦆
为什么在检查左侧或右侧长度恰好为m时,答案可以直接更新为当前步骤i而不需要进一步的验证或处理?
▷🦆
如果m等于n,按题解逻辑直接返回n,但如果arr数组的顺序不是升序,是否会影响答案的正确性?
▷🦆
题解没有提及如何处理如果存在多个长度为m的连续1组时的情况,这是否会影响到实际的答案输出?
▷