Skip to content

Commit 91da053

Browse files
Merge pull request SharingSource#703 from SharingSource/ac_oier
✨feat: add 927
2 parents c5c1fc2 + f1acc88 commit 91da053

File tree

3 files changed

+131
-1
lines changed

3 files changed

+131
-1
lines changed

Index/模拟.md

+1
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@
122122
| [905. 按奇偶排序数组](https://leetcode-cn.com/problems/sort-array-by-parity/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/sort-array-by-parity/solution/by-ac_oier-nuz7/) | 简单 | 🤩🤩🤩 |
123123
| [919. 完全二叉树插入器](https://leetcode.cn/problems/complete-binary-tree-inserter/) | [LeetCode 题解链接](https://leetcode.cn/problems/complete-binary-tree-inserter/solution/by-ac_oier-t9dh/) | 中等 | 🤩🤩🤩🤩 |
124124
| [921. 使括号有效的最少添加](https://leetcode.cn/problems/minimum-add-to-make-parentheses-valid/) | [LeetCode 题解链接](https://leetcode.cn/problems/minimum-add-to-make-parentheses-valid/solution/by-ac_oier-9tn1/) | 中等 | 🤩🤩🤩🤩 |
125+
| [927. 三等分](https://leetcode.cn/problems/three-equal-parts/) | [LeetCode 题解链接](https://leetcode.cn/problems/three-equal-parts/solution/by-ac_oier-9i2s/) | 困难 | 🤩🤩🤩🤩 |
125126
| [929. 独特的电子邮件地址](https://leetcode.cn/problems/unique-email-addresses/) | [LeetCode 题解链接](https://leetcode.cn/problems/unique-email-addresses/solution/by-ac_oier-d3zu/) | 简单 | 🤩🤩🤩 |
126127
| [944. 删列造序](https://leetcode.cn/problems/delete-columns-to-make-sorted/) | [LeetCode 题解链接](https://leetcode.cn/problems/delete-columns-to-make-sorted/solution/by-ac_oier-smoz/) | 简单 | 🤩🤩🤩 |
127128
| [946. 验证栈序列](https://leetcode.cn/problems/validate-stack-sequences/) | [LeetCode 题解链接](https://leetcode.cn/problems/validate-stack-sequences/solution/by-ac_oier-84qd/) | 中等 | 🤩🤩🤩🤩 |

LeetCode/281-290/287. 寻找重复数(中等).md

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
这是 LeetCode 上的 **[287. 寻找重复数](https://leetcode.cn/problems/find-the-duplicate-number/solution/by-ac_oier-az8v/)** ,难度为 **中等**
44

5-
Tag : 「原地哈希」
5+
Tag : 「桶排序」、「原地哈希」
66

77

88

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
### 题目描述
2+
3+
这是 LeetCode 上的 **[927. 三等分](https://leetcode.cn/problems/three-equal-parts/solution/by-ac_oier-9i2s/)** ,难度为 **困难**
4+
5+
Tag : 「模拟」
6+
7+
8+
9+
给定一个由 `0``1` 组成的数组 `arr`,将数组分成  `3` 个非空的部分 ,使得所有这些部分表示相同的二进制值。
10+
11+
如果可以做到,请返回任何 `[i, j]`,其中 `i+1 < j`,这样一来:
12+
13+
* `arr[0], arr[1], ..., arr[i]` 为第一部分;
14+
* `arr[i + 1], arr[i + 2], ..., arr[j - 1]` 为第二部分;
15+
* `arr[j], arr[j + 1], ..., arr[arr.length - 1]` 为第三部分。
16+
* 这三个部分所表示的二进制值相等。
17+
18+
如果无法做到,就返回 `[-1, -1]`
19+
20+
注意,在考虑每个部分所表示的二进制时,应当将其看作一个整体。例如,`[1,1,0]` 表示十进制中的 `6`,而不会是 `3`。此外,前导零也是被允许的,所以 `[0,1,1]` 和 `[1,1]` 表示相同的值。
21+
22+
示例 1:
23+
```
24+
输入:arr = [1,0,1,0,1]
25+
26+
输出:[0,3]
27+
```
28+
示例 2:
29+
```
30+
输入:arr = [1,1,0,1,1]
31+
32+
输出:[-1,-1]
33+
```
34+
示例 3:
35+
```
36+
输入:arr = [1,1,0,0,1]
37+
38+
输出:[0,2]
39+
```
40+
41+
提示:
42+
* $3 <= arr.length <= 3 \times 10^4$
43+
* `arr[i]` 是 `0` 或 `1`
44+
45+
---
46+
47+
### 模拟
48+
49+
心情不好,写的代码也不好。
50+
51+
就大概讲讲啥意思吧:
52+
53+
1. 先统计 `1` 的个数 `cnt`,若 `cnt = 0` 代表能够任意划分,直接返回 `[0, 2]`
54+
2.`cnt` 不为 $3$ 的倍数,必然不能正常划分,返回无解 `[-1, -1]`,否则可知三段中必然每一段 `1` 的数量均为 $t = \frac{cnt}{3}$ 个;
55+
3. 最后检查「三段中 `1` 的间隔位是否相同,后缀 `0` 个数是否相同」即可:
56+
1. 创建二维数组 `ins` 记录三段中,相邻 `1` 之间的间隔情况,若存在间隔 `1` 不同,返回无解 `[-1, -1]`
57+
2. 预处理四个变量 `l1``l2``r1``r2`,分别代表能够划分出最左边 `t``1` 的左右端点,以及能够划分出最右边 `t``1` 的左右端点,同时统计最后一段的后缀 `0` 的数量 `d`,配合四个变量来检查能否划分出具有 `d` 个后缀 `0` 的前两段。
58+
59+
代码:
60+
```Java
61+
class Solution {
62+
public int[] threeEqualParts(int[] arr) {
63+
int[] fail = new int[]{-1, -1};
64+
// 检查总数
65+
int n = arr.length, cnt = 0;
66+
for (int i = 0; i < n; i++) cnt += arr[i];
67+
if (cnt == 0) return new int[]{0, 2};
68+
if (cnt % 3 != 0) return fail;
69+
// 检查间隔相对位
70+
int t = cnt / 3;
71+
int[][] ins = new int[3][t];
72+
for (int i = 0, j = -1, k = 0, p = 0, idx = 0; i < n; i++) {
73+
if (arr[i] == 0) continue;
74+
if (j != -1) ins[p][idx++] = i - j;
75+
if (++k == t) {
76+
j = -1; k = 0; p++; idx = 0;
77+
} else {
78+
j = i;
79+
}
80+
}
81+
for (int i = 0; i < t; i++) {
82+
if (ins[0][i] == ins[1][i] && ins[0][i] == ins[2][i] && ins[1][i] == ins[2][i]) continue;
83+
return fail;
84+
}
85+
// 构造答案(l1 和 l2 分别为能够划分出最左边 t 个 1 的 左右端点;r1 和 r2 分别为能够划分出最右边 t 个 1 的左右端点)
86+
int l1 = -1, l2 = -1, r1 = -1, r2 = -1;
87+
for (int i = 0, k = 0; i < n; i++) {
88+
k += arr[i];
89+
if (k == t) {
90+
if (l1 == -1) l1 = i;
91+
} else if (k == t + 1) {
92+
l2 = i - 1;
93+
break;
94+
}
95+
}
96+
for (int i = n - 1, k = 0; i >= 0; i--) {
97+
k += arr[i];
98+
if (k == t) {
99+
if (r2 == -1) r2 = i;
100+
} else if (k == t + 1) {
101+
r1 = i + 1;
102+
break;
103+
}
104+
}
105+
int d = 0; // d 为最右边一段的后缀 0 的数量
106+
for (int i = n - 1; i >= 0; i--) {
107+
if (arr[i] == 1) break;
108+
d++;
109+
}
110+
if (l1 + d > l2 || r1 + d > r2) return fail;
111+
return new int[]{l1 + d, r1 + d};
112+
}
113+
}
114+
```
115+
* 时间复杂度:$O(n)$
116+
* 空间复杂度:$O(n)$
117+
118+
---
119+
120+
### 最后
121+
122+
这是我们「刷穿 LeetCode」系列文章的第 `No.927` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
123+
124+
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
125+
126+
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode
127+
128+
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。
129+

0 commit comments

Comments
 (0)