Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit bb69d6e

Browse files
Merge pull request #791 from SharingSource/ac_oier
🌟 feat: add 10、1004、1006、1038、1052、115、119、1190、1206、1208、1233、1282、1...
2 parents a4120c8 + c1a446b commit bb69d6e

File tree

117 files changed

+7969
-1361
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

117 files changed

+7969
-1361
lines changed

‎LeetCode/1-10/10. 正则表达式匹配(困难).md‎

Lines changed: 71 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -74,41 +74,28 @@ Tag : 「动态规划」、「序列 DP」
7474
本题可以使用动态规划进行求解:
7575

7676
* 状态定义:`f(i,j)` 代表考虑 `s` 中以 `i` 为结尾的子串和 `p` 中的 `j` 为结尾的子串是否匹配。最终我们要求的结果为 `f[n][m]`
77-
7877
* 状态转移:也就是我们要考虑 `f(i,j)` 如何求得,前面说到了 `p` 有三种字符,所以这里的状态转移也要分三种情况讨论:
79-
80-
1. `p[j]` 为普通字符:匹配的条件是前面的字符匹配,同时 `s` 中的第 `i` 个字符和 `p` 中的第 `j` 位相同。
81-
82-
`f(i,j) = f(i - 1, j - 1) && s[i] == p[j]`
83-
84-
2. `p[j]` 为 `'.'`:匹配的条件是前面的字符匹配, `s` 中的第 `i` 个字符可以是任意字符。
85-
86-
`f(i,j) = f(i - 1, j - 1) && p[j] == '.'`。
87-
88-
3. `p[j]``'*'`:读得 `p[j - 1]` 的字符,例如为字符 `a`。 然后根据 `a*` 实际匹配 `s``a` 的个数是 0ドル$ 个、1ドル$ 个、2ドル$ 个 ...
89-
90-
3.1. 当匹配为 0ドル$ 个:`f(i,j) = f(i, j - 2)`
91-
92-
3.2. 当匹配为 1ドル$ 个:`f(i,j) = f(i - 1, j - 2) && (s[i] == p[j - 1] || p[j - 1] == '.')`
93-
94-
3.3. 当匹配为 2ドル$ 个:`f(i,j) = f(i - 2, j - 2) && ((s[i] == p[j - 1] && s[i - 1] == p[j - 1]) || p[j] == '.')`
78+
1. `p[j]` 为普通字符:匹配的条件是前面的字符匹配,同时 `s` 中的第 `i` 个字符和 `p` 中的第 `j` 位相同。 即 `f(i,j) = f(i-1, j-1) && s[i] == p[j]`
79+
2. `p[j]``'.'`:匹配的条件是前面的字符匹配, `s` 中的第 `i` 个字符可以是任意字符。即 `f(i,j) = f(i-1, j-1) && p[j] == '.'`
80+
3. `p[j]``'*'`:读得 `p[j-1]` 的字符,例如为字符 `a`。 然后根据 `a*` 实际匹配 `s``a` 的个数是 0ドル$ 个、1ドル$ 个、2ドル$ 个 ...
81+
* 当匹配为 0ドル$ 个:`f(i,j) = f(i,j-2)`
82+
* 当匹配为 1ドル$ 个:`f(i,j) = f(i-1,j-2) && (s[i] == p[j-1] || p[j-1] == '.')`
83+
* 当匹配为 2ドル$ 个:`f(i,j) = f(i-2, j-2) && ((s[i] == p[j-1] && s[i-1] == p[j-1]) || p[j] == '.')`
9584

9685
**我们知道,通过「枚举」来确定 `*` 到底匹配多少个 `a` 这样的做法,算法复杂度是很高的。**
9786

9887
**我们需要挖掘一些「性质」来简化这个过程。**
9988

100-
![640.png](https://pic.leetcode-cn.com/1611397993-lmpHIZ-640.png)
89+
![](https://pic.leetcode-cn.com/1611397993-lmpHIZ-640.png)
10190

102-
代码:
91+
Java 代码:
10392
```Java
10493
class Solution {
10594
public boolean isMatch(String ss, String pp) {
10695
// 技巧:往原字符头部插入空格,这样得到 char 数组是从 1 开始,而且可以使得 f[0][0] = true,可以将 true 这个结果滚动下去
10796
int n = ss.length(), m = pp.length();
108-
ss = " " + ss;
109-
pp = " " + pp;
110-
char[] s = ss.toCharArray();
111-
char[] p = pp.toCharArray();
97+
ss = " " + ss; pp = " " + pp;
98+
char[] s = ss.toCharArray(), p = pp.toCharArray();
11299
// f(i,j) 代表考虑 s 中的 1~i 字符和 p 中的 1~j 字符 是否匹配
113100
boolean[][] f = new boolean[n + 1][m + 1];
114101
f[0][0] = true;
@@ -132,6 +119,67 @@ class Solution {
132119
}
133120
}
134121
```
122+
C++ 代码:
123+
```C++
124+
class Solution {
125+
public:
126+
bool isMatch(string s, string p) {
127+
int n = s.length(), m = p.length();
128+
s = " " + s; p = " " + p;
129+
vector<vector<bool>> f(n + 1, vector<bool>(m + 1, false));
130+
f[0][0] = true;
131+
for (int i = 0; i <= n; i++) {
132+
for (int j = 1; j <= m; j++) {
133+
if (j + 1 <= m && p[j + 1] == '*' && p[j] != '*') continue;
134+
if (i - 1 >= 0 && p[j] != '*') {
135+
f[i][j] = f[i - 1][j - 1] && (s[i] == p[j] || p[j] == '.');
136+
} else if (p[j] == '*') {
137+
f[i][j] = (j - 2 >= 0 && f[i][j - 2]) || (i - 1 >= 0 && f[i - 1][j] && (s[i] == p[j - 1] || p[j - 1] == '.'));
138+
}
139+
}
140+
}
141+
return f[n][m];
142+
}
143+
};
144+
```
145+
Python 代码:
146+
```Python
147+
class Solution:
148+
def isMatch(self, s: str, p: str) -> bool:
149+
n, m = len(s), len(p)
150+
s, p = " " + s, " " + p
151+
f = [[False] * (m + 1) for _ in range(n + 1)]
152+
f[0][0] = True
153+
for i in range(n + 1):
154+
for j in range(1, m + 1):
155+
if j + 1 <= m and p[j + 1] == '*' and p[j] != '*':
156+
continue
157+
if i - 1 >= 0 and p[j] != '*':
158+
f[i][j] = f[i - 1][j - 1] and (s[i] == p[j] or p[j] == '.')
159+
elif p[j] == '*':
160+
f[i][j] = (j - 2 >= 0 and f[i][j - 2]) or (i - 1 >= 0 and f[i - 1][j] and (s[i] == p[j - 1] or p[j - 1] == '.'))
161+
return f[n][m]
162+
```
163+
TypeScript 代码:
164+
```TypeScript
165+
function isMatch(s: string, p: string): boolean {
166+
let n: number = s.length, m: number = p.length
167+
s = " " + s; p = " " + p;
168+
let f: boolean[][] = new Array(n + 1).fill(false).map(() => new Array(m + 1).fill(false));
169+
f[0][0] = true;
170+
for (let i: number = 0; i <= n; i++) {
171+
for (let j: number = 1; j <= m; j++) {
172+
if (j + 1 <= m && p.charAt(j + 1) === '*' && p.charAt(j) !== '*') continue;
173+
if (i - 1 >= 0 && p.charAt(j) !== '*') {
174+
f[i][j] = f[i - 1][j - 1] && (s.charAt(i) === p.charAt(j) || p.charAt(j) === '.');
175+
} else if (p.charAt(j) === '*') {
176+
f[i][j] = (j - 2 >= 0 && f[i][j - 2]) || (i - 1 >= 0 && f[i - 1][j] && (s.charAt(i) === p.charAt(j - 1) || p.charAt(j - 1) === '.'));
177+
}
178+
}
179+
}
180+
return f[n][m];
181+
};
182+
```
135183
* 时间复杂度:$n$ 表示 `s` 的长度,$m$ 表示 `p` 的长度,总共 $n \times m$ 个状态。复杂度为 $O(n \times m)$
136184
* 空间复杂度:使用了二维数组记录结果。复杂度为 $O(n \times m)$
137185

‎LeetCode/1001-1010/1004. 最大连续1的个数 III(中等).md‎

Lines changed: 128 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,27 @@ Tag : 「双指针」、「滑动窗口」、「二分」、「前缀和」
66

77

88

9-
给定一个由若干 0ドル$1ドル$ 组成的数组 `A`,我们最多可以将 $K$ 个值从 0ドル$ 变成 1ドル$
9+
给定一个由若干 01 组成的数组 `A`,我们最多可以将 `K` 个值从 0 变成 1
1010

11-
返回仅包含 1ドル$ 的最长(连续)子数组的长度。
11+
返回仅包含 1 的最长(连续)子数组的长度。
1212

1313

1414
示例 1:
1515
```
1616
输入:A = [1,1,1,0,0,0,1,1,1,1,0], K = 2
17+
1718
输出:6
19+
1820
解释:
1921
[1,1,1,0,0,1,1,1,1,1,1]
2022
粗体数字从 0 翻转到 1,最长的子数组长度为 6。
2123
```
2224
示例 2:
2325
```
2426
输入:A = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], K = 3
27+
2528
输出:10
29+
2630
解释:
2731
[0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1]
2832
粗体数字从 0 翻转到 1,最长的子数组长度为 10。
@@ -50,7 +54,7 @@ Tag : 「双指针」、「滑动窗口」、「二分」、「前缀和」
5054
* 如果 $A[i]$ 本身就为 1 的话,无须消耗翻转次数,$f[i][j] = f[i - 1][j] + 1$。
5155
* 如果 $A[i]$ 本身不为 1 的话,由于定义是必须以 $A[i]$ 为结尾,因此必须要选择翻转该位置,$f[i][j] = f[i - 1][j - 1] + 1$。
5256

53-
代码:
57+
Java 代码:
5458
```Java
5559
class Solution {
5660
public int longestOnes(int[] nums, int k) {
@@ -96,23 +100,19 @@ class Solution {
96100

97101
**因此,对于某个确定的「左端点/右端点」而言,以「其最远右端点/最远左端点」为分割点的前缀和数轴,具有「二段性」。可以通过二分来找分割点。**
98102

99-
代码:
103+
Java 代码:
100104
```Java
101105
class Solution {
102106
public int longestOnes(int[] nums, int k) {
103-
int n = nums.length;
104-
int ans = 0;
107+
int n = nums.length, ans = 0;
105108
int[] sum = new int[n + 1];
106109
for (int i = 1; i <= n; i++) sum[i] = sum[i - 1] + nums[i - 1];
107110
for (int i = 0; i < n; i++) {
108111
int l = 0, r = i;
109112
while (l < r) {
110113
int mid = l + r >> 1;
111-
if (check(sum, mid, i, k)) {
112-
r = mid;
113-
} else {
114-
l = mid + 1;
115-
}
114+
if (check(sum, mid, i, k)) r = mid;
115+
else l = mid + 1;
116116
}
117117
if (check(sum, r, i, k)) ans = Math.max(ans, i - r + 1);
118118
}
@@ -124,6 +124,80 @@ class Solution {
124124
}
125125
}
126126
```
127+
C++ 代码:
128+
```C++
129+
class Solution {
130+
public:
131+
int longestOnes(vector<int>& nums, int k) {
132+
int n = nums.size(), ans = 0;
133+
vector<int> sum(n + 1, 0);
134+
for (int i = 1; i <= n; i++) sum[i] = sum[i - 1] + nums[i - 1];
135+
for (int i = 0; i < n; i++) {
136+
int l = 0, r = i;
137+
while (l < r) {
138+
int mid = l + r >> 1;
139+
if (check(sum, mid, i, k)) r = mid;
140+
else l = mid + 1;
141+
}
142+
if (check(sum, r, i, k)) ans = max(ans, i - r + 1);
143+
}
144+
return ans;
145+
}
146+
bool check(const vector<int>& sum, int l, int r, int k) {
147+
int tol = sum[r + 1] - sum[l];
148+
int len = r - l + 1;
149+
return len - tol <= k;
150+
}
151+
};
152+
```
153+
Python 代码:
154+
```Python
155+
class Solution:
156+
def longestOnes(self, nums: List[int], k: int) -> int:
157+
n, ans = len(nums), 0
158+
sumv = [0] * (n + 1)
159+
for i in range(1, n + 1):
160+
sumv[i] = sumv[i - 1] + nums[i - 1]
161+
for i in range(n):
162+
l, r = 0, i
163+
while l < r:
164+
mid = l + r >> 1
165+
if self.check(sumv, mid, i, k):
166+
r = mid
167+
else:
168+
l = mid + 1
169+
if self.check(sumv, l, i, k):
170+
ans = max(ans, i - l + 1)
171+
return ans
172+
173+
def check(self, sumv, l, r, k):
174+
tol = sumv[r + 1] - sumv[l]
175+
lenv = r - l + 1
176+
return lenv - tol <= k
177+
```
178+
TypeScript 代码:
179+
```TypeScript
180+
function check(sum: number[], l: number, r: number, k: number): boolean {
181+
const tol = sum[r + 1] - sum[l];
182+
const len = r - l + 1;
183+
return len - tol <= k;
184+
}
185+
function longestOnes(nums: number[], k: number): number {
186+
let n = nums.length, ans = 0;
187+
const sum = new Array(n + 1).fill(0);
188+
for (let i = 1; i <= n; i++) sum[i] = sum[i - 1] + nums[i - 1];
189+
for (let i = 0; i < n; i++) {
190+
let l = 0, r = i;
191+
while (l < r) {
192+
let mid = l + r >> 1;
193+
if (check(sum, mid, i, k)) r = mid;
194+
else l = mid + 1;
195+
}
196+
if (check(sum, l, i, k)) ans = Math.max(ans, i - l + 1);
197+
}
198+
return ans;
199+
};
200+
```
127201
* 时间复杂度:$O(n\log{n})$
128202
* 空间复杂度:$O(n)$
129203

@@ -143,12 +217,11 @@ class Solution {
143217

144218
右端点一直右移,左端点在窗口不满足「`len - tol <= k`」的时候进行右移,即可做到线程扫描的复杂度。
145219

146-
代码:
220+
Java 代码:
147221
```Java
148222
class Solution {
149223
public int longestOnes(int[] nums, int k) {
150-
int n = nums.length;
151-
int ans = 0;
224+
int n = nums.length, ans = 0;
152225
for (int i = 0, j = 0, tot = 0; i < n; i++) {
153226
tot += nums[i];
154227
while ((i - j + 1) - tot > k) tot -= nums[j++];
@@ -158,6 +231,47 @@ class Solution {
158231
}
159232
}
160233
```
234+
C++ 代码:
235+
```C++
236+
class Solution {
237+
public:
238+
int longestOnes(vector<int>& nums, int k) {
239+
int n = nums.size(), ans = 0;
240+
for (int i = 0, j = 0, tot = 0; i < n; i++) {
241+
tot += nums[i];
242+
while ((i - j + 1) - tot > k) tot -= nums[j++];
243+
ans = max(ans, i - j + 1);
244+
}
245+
return ans;
246+
}
247+
};
248+
```
249+
Python 代码:
250+
```Python
251+
class Solution:
252+
def longestOnes(self, nums: List[int], k: int) -> int:
253+
n, ans = len(nums), 0
254+
j, tot = 0, 0
255+
for i in range(n):
256+
tot += nums[i]
257+
while (i - j + 1) - tot > k:
258+
tot -= nums[j]
259+
j += 1
260+
ans = max(ans, i - j + 1)
261+
return ans
262+
```
263+
TypeScript 代码:
264+
```TypeScript
265+
function longestOnes(nums: number[], k: number): number {
266+
let n = nums.length, ans = 0;
267+
for (let i = 0, j = 0, tot = 0; i < n; i++) {
268+
tot += nums[i];
269+
while ((i - j + 1) - tot > k) tot -= nums[j++];
270+
ans = Math.max(ans, i - j + 1);
271+
}
272+
return ans;
273+
};
274+
```
161275
* 时间复杂度:$O(n)$
162276
* 空间复杂度:$O(1)$
163277

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /