返回介绍

solution / 1500-1599 / 1562.Find Latest Group of Size M / README

发布于 2024-06-17 01:03:18 字数 8393 浏览 0 评论 0 收藏 0

1562. 查找大小为 M 的最新分组

English Version

题目描述

给你一个数组 arr ,该数组表示一个从 1n 的数字排列。有一个长度为 n 的二进制字符串,该字符串上的所有位最初都设置为 0

在从 1n 的每个步骤 i 中(假设二进制字符串和 arr 都是从 1 开始索引的情况下),二进制字符串上位于位置 arr[i] 的位将会设为 1

给你一个整数 m ,请你找出二进制字符串上存在长度为 m 的一组 1 的最后步骤。一组 1 是一个连续的、由 1 组成的子串,且左右两边不再有可以延伸的 1

返回存在长度 恰好m一组 1  的最后步骤。如果不存在这样的步骤,请返回 -1

 

示例 1:

输入:arr = [3,5,1,2,4], m = 1
输出:4
解释:
步骤 1:"00100",由 1 构成的组:["1"]
步骤 2:"00101",由 1 构成的组:["1", "1"]
步骤 3:"10101",由 1 构成的组:["1", "1", "1"]
步骤 4:"11101",由 1 构成的组:["111", "1"]
步骤 5:"11111",由 1 构成的组:["11111"]
存在长度为 1 的一组 1 的最后步骤是步骤 4 。

示例 2:

输入:arr = [3,1,5,4,2], m = 2
输出:-1
解释:
步骤 1:"00100",由 1 构成的组:["1"]
步骤 2:"10100",由 1 构成的组:["1", "1"]
步骤 3:"10101",由 1 构成的组:["1", "1", "1"]
步骤 4:"10111",由 1 构成的组:["1", "111"]
步骤 5:"11111",由 1 构成的组:["11111"]
不管是哪一步骤都无法形成长度为 2 的一组 1 。

示例 3:

输入:arr = [1], m = 1
输出:1

示例 4:

输入:arr = [2,1], m = 2
输出:2

 

提示:

  • n == arr.length
  • 1 <= n <= 10^5
  • 1 <= arr[i] <= n
  • arr 中的所有整数 互不相同
  • 1 <= m <= arr.length

解法

方法一:并查集

正向遍历 $arr$,利用并查集动态维护每组 $1$ 的长度。

时间复杂度 $O(n \times \log n)$。

相似题目:

class Solution:
  def findLatestStep(self, arr: List[int], m: int) -> int:
    def find(x):
      if p[x] != x:
        p[x] = find(p[x])
      return p[x]

    def union(a, b):
      pa, pb = find(a), find(b)
      if pa == pb:
        return
      p[pa] = pb
      size[pb] += size[pa]

    n = len(arr)
    if m == n:
      return n
    vis = [False] * n
    p = list(range(n))
    size = [1] * n
    ans = -1
    for i, v in enumerate(arr):
      v -= 1
      if v and vis[v - 1]:
        if size[find(v - 1)] == m:
          ans = i
        union(v, v - 1)
      if v < n - 1 and vis[v + 1]:
        if size[find(v + 1)] == m:
          ans = i
        union(v, v + 1)
      vis[v] = True
    return ans
class Solution {
  private int[] p;
  private int[] size;

  public int findLatestStep(int[] arr, int m) {
    int n = arr.length;
    if (m == n) {
      return n;
    }
    boolean[] vis = new boolean[n];
    p = new int[n];
    size = new int[n];
    for (int i = 0; i < n; ++i) {
      p[i] = i;
      size[i] = 1;
    }
    int ans = -1;
    for (int i = 0; i < n; ++i) {
      int v = arr[i] - 1;
      if (v > 0 && vis[v - 1]) {
        if (size[find(v - 1)] == m) {
          ans = i;
        }
        union(v, v - 1);
      }
      if (v < n - 1 && vis[v + 1]) {
        if (size[find(v + 1)] == m) {
          ans = i;
        }
        union(v, v + 1);
      }
      vis[v] = true;
    }
    return ans;
  }

  private int find(int x) {
    if (p[x] != x) {
      p[x] = find(p[x]);
    }
    return p[x];
  }

  private void union(int a, int b) {
    int pa = find(a), pb = find(b);
    if (pa == pb) {
      return;
    }
    p[pa] = pb;
    size[pb] += size[pa];
  }
}
class Solution {
public:
  vector<int> p;
  vector<int> size;

  int findLatestStep(vector<int>& arr, int m) {
    int n = arr.size();
    if (m == n) return n;
    p.resize(n);
    size.assign(n, 1);
    for (int i = 0; i < n; ++i) p[i] = i;
    int ans = -1;
    vector<int> vis(n);
    for (int i = 0; i < n; ++i) {
      int v = arr[i] - 1;
      if (v && vis[v - 1]) {
        if (size[find(v - 1)] == m) ans = i;
        unite(v, v - 1);
      }
      if (v < n - 1 && vis[v + 1]) {
        if (size[find(v + 1)] == m) ans = i;
        unite(v, v + 1);
      }
      vis[v] = true;
    }
    return ans;
  }

  int find(int x) {
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];
  }

  void unite(int a, int b) {
    int pa = find(a), pb = find(b);
    if (pa == pb) return;
    p[pa] = pb;
    size[pb] += size[pa];
  }
};
func findLatestStep(arr []int, m int) int {
  n := len(arr)
  if m == n {
    return n
  }
  p := make([]int, n)
  size := make([]int, n)
  vis := make([]bool, n)
  for i := range p {
    p[i] = i
    size[i] = 1
  }
  var find func(int) int
  find = func(x int) int {
    if p[x] != x {
      p[x] = find(p[x])
    }
    return p[x]
  }
  union := func(a, b int) {
    pa, pb := find(a), find(b)
    if pa == pb {
      return
    }
    p[pa] = pb
    size[pb] += size[pa]
  }

  ans := -1
  for i, v := range arr {
    v--
    if v > 0 && vis[v-1] {
      if size[find(v-1)] == m {
        ans = i
      }
      union(v, v-1)
    }
    if v < n-1 && vis[v+1] {
      if size[find(v+1)] == m {
        ans = i
      }
      union(v, v+1)
    }
    vis[v] = true
  }
  return ans
}

方法二:动态维护区间端点的长度

我们其实并不需要去通过查找并查集来获取每个区间长度,我们只需要在每个区间端点处记录每个区间长度,由于合并的时候只会访问区间端点,所以合并区间的时候修改端点区间长度即可。

时间复杂度 $O(n)$。

class Solution:
  def findLatestStep(self, arr: List[int], m: int) -> int:
    n = len(arr)
    if m == n:
      return n
    cnt = [0] * (n + 2)
    ans = -1
    for i, v in enumerate(arr):
      v -= 1
      l, r = cnt[v - 1], cnt[v + 1]
      if l == m or r == m:
        ans = i
      cnt[v - l] = cnt[v + r] = l + r + 1
    return ans
class Solution {
  public int findLatestStep(int[] arr, int m) {
    int n = arr.length;
    if (m == n) {
      return n;
    }
    int[] cnt = new int[n + 2];
    int ans = -1;
    for (int i = 0; i < n; ++i) {
      int v = arr[i];
      int l = cnt[v - 1], r = cnt[v + 1];
      if (l == m || r == m) {
        ans = i;
      }
      cnt[v - l] = l + r + 1;
      cnt[v + r] = l + r + 1;
    }
    return ans;
  }
}
class Solution {
public:
  int findLatestStep(vector<int>& arr, int m) {
    int n = arr.size();
    if (m == n) return n;
    vector<int> cnt(n + 2);
    int ans = -1;
    for (int i = 0; i < n; ++i) {
      int v = arr[i];
      int l = cnt[v - 1], r = cnt[v + 1];
      if (l == m || r == m) ans = i;
      cnt[v - l] = cnt[v + r] = l + r + 1;
    }
    return ans;
  }
};
func findLatestStep(arr []int, m int) int {
  n := len(arr)
  if m == n {
    return n
  }
  cnt := make([]int, n+2)
  ans := -1
  for i, v := range arr {
    l, r := cnt[v-1], cnt[v+1]
    if l == m || r == m {
      ans = i
    }
    cnt[v-l], cnt[v+r] = l+r+1, l+r+1
  }
  return ans
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文