加载中...
1562-查找大小为 M 的最新分组(Find Latest Group of Size M)
发表于:2021-12-03 | 分类: 中等
字数统计: 1.6k | 阅读时长: 7分钟 | 阅读量:

原文链接: https://leetcode-cn.com/problems/find-latest-group-of-size-m

英文原文

Given an array arr that represents a permutation of numbers from 1 to n.

You have a binary string of size n that initially has all its bits set to zero. At each step i (assuming both the binary string and arr are 1-indexed) from 1 to n, the bit at position arr[i] is set to 1.

You are also given an integer m. Find the latest step at which there exists a group of ones of length m. A group of ones is a contiguous substring of 1's such that it cannot be extended in either direction.

Return the latest step at which there exists a group of ones of length exactly m. If no such group exists, return -1.

 

Example 1:

Input: arr = [3,5,1,2,4], m = 1
Output: 4
Explanation:
Step 1: "00100", groups: ["1"]
Step 2: "00101", groups: ["1", "1"]
Step 3: "10101", groups: ["1", "1", "1"]
Step 4: "11101", groups: ["111", "1"]
Step 5: "11111", groups: ["11111"]
The latest step at which there exists a group of size 1 is step 4.

Example 2:

Input: arr = [3,1,5,4,2], m = 2
Output: -1
Explanation:
Step 1: "00100", groups: ["1"]
Step 2: "10100", groups: ["1", "1"]
Step 3: "10101", groups: ["1", "1", "1"]
Step 4: "10111", groups: ["1", "111"]
Step 5: "11111", groups: ["11111"]
No group of size 2 exists during any step.

Example 3:

Input: arr = [1], m = 1
Output: 1

Example 4:

Input: arr = [2,1], m = 2
Output: 2

 

Constraints:

  • n == arr.length
  • 1 <= m <= n <= 105
  • 1 <= arr[i] <= n
  • All integers in arr are distinct.

中文题目

给你一个数组 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

通过代码

高赞题解

解题思路:

每操作一次,新增的 1 可能会有如下三种情况:

  • 左右都是 0。此时该位置作为 新增段独立存在
  • 仅有左边或者右边。此时该位置 会将某个旧段的长度加 1
  • 左右都是 1。此时 该位置会将两个旧段合并成一个新段

我们现在维护一个字典 M,M 的 key 表示段的长度,value 表示在字符串中,长度为 key 的段的数量。初始时,M 中无记录。接下来,让我们看下上述三种情况分别对 M 造成了哪些变化。

  • 情况一:新增了一个长度为 1 的段。M[1] += 1
  • 情况二:删除一个长度为 L 的段,增加一个长度为 L+1的段。M[L] -= 1;M[L+1] += 1
  • 情况三:删除两个长度分别为 X,Y 的段,增加一个长度为 X+Y+1 的段。
    M[X] -= 1;M[Y] -= 1;M[X+Y+1] += 1

然后记录一下 最后一次使 M[m] 不为零的操作 即可。

另外,还有一个重要问题,如何确定被删除段的长度呢

设有一个数组 link,当 arr[i] 为某个段的端点时,link[i] 才有意义,其值代表另一个端点的位置。

接下来,上述三种情况如何更新 link

  • 情况一:因为长度为 1,所以 link[i] = i

  • 情况二:加入新增点成为某个旧段的右端点;
    则被删段长度为 (i-1) - link[i-1] + 1link[link[i-1]] = ilink[i] = link[i-1]
    为左端点时同理,机智的老铁们可自行推导。
    image.png

  • 情况三:左删除段长度为:(i-1) - link[i-1] + 1
    有删除段长度为:link(i+1) - (i+1) + 1
    更新:link[link[i-1]], link[link[i+1]] = link[i+1], link[i-1]
    image.png

另外,实现时根本不需要 M,因为我们只关心长度为 m 的段的数量~。

[]
int link[100001] = {0}; class Solution { public: int findLatestStep(vector<int>& arr, int m) { int cnt = 0; memset(link, -1, sizeof(link)); int anw = -1; for(int i = 0; i < arr.size(); i++) { int pos = arr[i] - 1; link[pos] = pos; int L = pos, R = pos; if(0 < pos && link[pos-1] != -1) { if(pos-1 - link[pos-1] + 1 == m) { cnt--; } L = link[pos-1]; } if(pos+1 < arr.size() && link[pos+1] != -1) { if(link[pos+1] - (pos+1) + 1 == m) { cnt--; } R = link[pos+1]; } link[L] = R; link[R] = L; if(R-L+1 == m) { cnt++; } if(cnt > 0) { anw = i+1; } } return anw; } };

统计信息

通过次数 提交次数 AC比率
4323 13932 31.0%

提交历史

提交时间 提交结果 执行时间 内存消耗 语言
上一篇:
1560-圆形赛道上经过次数最多的扇区(Most Visited Sector in a Circular Track)
下一篇:
1563-石子游戏 V(Stone Game V)
本文目录
本文目录