leetcode
leetcode 1401 ~ 1450
查找大小为 M 的最新分组

查找大小为 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]时,为什么可以保证这样的更新不会影响到其他位置的正确性?
在更新cnt数组时,只有两个位置cnt[v-l]和cnt[v+r]被更改,这两个位置分别表示整个连续'1'序列的起始和结束位置。更新这两个边界的原因是,只有这两个位置的值会影响到新加入的'1'如何改变整个连续序列的计数。由于连续序列的内部元素的cnt值不会被直接查询(只查询边界),因此更新边界不会影响其他位置的正确性。同时,这种方式确保了只有边界的连续长度被更新,保持了算法的效率和准确性。
🦆
为什么在检查左侧或右侧长度恰好为m时,答案可以直接更新为当前步骤i而不需要进一步的验证或处理?
题目要求找到最后一次出现恰好长度为m的连续'1'的步骤。在算法中,每次操作都会检查插入点的左右连续'1'的长度是否为m。如果是,说明在这一步操作完成后,恰好有一个长度为m的连续'1'序列。因此,可以直接更新答案为当前步骤i。此外,如果后续的操作影响了这个连续序列,即使它再次变为m,也会在后面的步骤中被检测到并更新答案。
🦆
如果m等于n,按题解逻辑直接返回n,但如果arr数组的顺序不是升序,是否会影响答案的正确性?
如果m等于n,意味着只有在数组arr的所有元素都被填充为'1'且完全填满整个数组时,才符合条件。无论arr的顺序如何,只要最后一个操作将最后一个'0'变为'1',整个数组就全是'1'。因此,不论arr的顺序如何,最后一个操作总是第n步,所以返回n是正确的。
🦆
题解没有提及如何处理如果存在多个长度为m的连续1组时的情况,这是否会影响到实际的答案输出?
在算法中,每次插入都会检查并更新答案ans,如果存在多个长度为m的连续'1'组,算法会在发现第一个这样的组时更新答案。之后的操作可能会改变这些连续序列的长度,但每次操作都会重新评估并可能更新答案。因此,即使存在多个长度为m的连续序列,算法依然能够正确记录最后一次出现长度为m的步骤,不会影响最终答案的正确性。

相关问题