Skip to content

Commit 99cf8af

Browse files
committed
904-1031-1156-1208-1223-1233-1234-1343-1546 (9)
1 parent efbfada commit 99cf8af

File tree

22 files changed

+743
-51
lines changed

22 files changed

+743
-51
lines changed

leetcode-01/src/main/java/Solution3.java

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,26 @@
33

44
public class Solution3 {
55
public int lengthOfLongestSubstring(String s) {
6-
Map<Character, Integer> sCntMap = new HashMap<>();
7-
int ans = 0;
8-
// 双指针-滑动窗口
9-
int left = 0;
10-
int right = 0;
11-
while (right < s.length()) {
12-
// 右指针右移
13-
char addCh = s.charAt(right);
14-
sCntMap.put(addCh, sCntMap.getOrDefault(addCh, 0) + 1);
15-
right++;
16-
// 左指针右移
17-
while (sCntMap.getOrDefault(addCh, 0) > 1) {
18-
char rmCh = s.charAt(left);
19-
sCntMap.put(rmCh, sCntMap.getOrDefault(rmCh, 0) - 1);
20-
left++;
6+
int n = s.length();
7+
char[] chars = s.toCharArray();
8+
Map<Character, Integer> cntMap = new HashMap<>();
9+
int l = 0, r = 0;
10+
int max = 0;
11+
while (r < n) {
12+
cntMap.put(chars[r], cntMap.getOrDefault(chars[r], 0) + 1);
13+
while (cntMap.get(chars[r]) > 1) {
14+
int cnt = cntMap.get(chars[l]);
15+
if (cnt == 1) {
16+
cntMap.remove(chars[l]);
17+
} else {
18+
cntMap.put(chars[l], cnt - 1);
19+
}
20+
l++;
2121
}
22-
ans = Math.max(ans, right - left);
22+
max = Math.max(max, r - l + 1);
23+
r++;
2324
}
24-
return ans;
25+
return max;
2526
}
2627
}
2728
/*

leetcode-01/src/main/java/Solution76.java

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,26 @@ public String minWindow(String s, String t) {
1616
}
1717

1818
Map<Character, Integer> sMap = new HashMap<>();
19-
int left = 0, right = 0;
19+
int l = 0, r = 0;
2020
int ansLen = n + 1;
2121
int ansL = 0;
22-
while (right < n) {
23-
char ch = s.charAt(right);
22+
while (r < n) {
23+
char ch = s.charAt(r);
2424
sMap.put(ch, sMap.getOrDefault(ch, 0) + 1);
2525
while (check(sMap)) {
26-
if (ansLen > right - left + 1) {
27-
ansLen = right - left + 1;
28-
ansL = left;
26+
if (ansLen > r - l + 1) {
27+
ansLen = r - l + 1;
28+
ansL = l;
2929
}
30-
char rm = s.charAt(left);
30+
char rm = s.charAt(l);
3131
sMap.put(rm, sMap.get(rm) - 1);
32-
left++;
32+
l++;
3333
}
34-
right++;
34+
r++;
3535
}
3636
return (ansLen == n + 1) ? "" : s.substring(ansL, ansL + ansLen);
3737
}
3838

39-
// sMap 是否完全覆盖 tMap
4039
private boolean check(Map<Character, Integer> sMap) {
4140
for (Map.Entry<Character, Integer> entry : tMap.entrySet()) {
4241
char ch = entry.getKey();
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import java.util.HashMap;
2+
import java.util.Map;
3+
4+
public class Solution904 {
5+
public int totalFruit(int[] fruits) {
6+
int n = fruits.length;
7+
Map<Integer, Integer> cntMap = new HashMap<>();
8+
int l = 0, r = 0;
9+
int max = 0;
10+
while (r < n) {
11+
cntMap.put(fruits[r], cntMap.getOrDefault(fruits[r], 0) + 1);
12+
while (cntMap.size() > 2) {
13+
int cnt = cntMap.get(fruits[l]);
14+
if (cnt == 1) {
15+
cntMap.remove(fruits[l]);
16+
} else {
17+
cntMap.put(fruits[l], cnt - 1);
18+
}
19+
l++;
20+
}
21+
max = Math.max(max, r - l + 1);
22+
r++;
23+
}
24+
return max;
25+
}
26+
}
27+
/*
28+
904. 水果成篮
29+
https://leetcode.cn/problems/fruit-into-baskets/
30+
31+
你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。
32+
你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:
33+
- 你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。
34+
- 你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。
35+
- 一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。
36+
给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。
37+
提示:
38+
1 <= fruits.length <= 10^5
39+
0 <= fruits[i] < fruits.length
40+
41+
双指针 滑动窗口
42+
*/
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import org.junit.jupiter.api.Assertions;
2+
import org.junit.jupiter.api.Test;
3+
4+
public class Solution904Tests {
5+
private final Solution904 solution904 = new Solution904();
6+
7+
@Test
8+
public void example1() {
9+
int[] fruits = {1, 2, 1};
10+
int expected = 3;
11+
Assertions.assertEquals(expected, solution904.totalFruit(fruits));
12+
}
13+
14+
@Test
15+
public void example2() {
16+
int[] fruits = {0, 1, 2, 2};
17+
int expected = 3;
18+
Assertions.assertEquals(expected, solution904.totalFruit(fruits));
19+
}
20+
21+
@Test
22+
public void example3() {
23+
int[] fruits = {1, 2, 3, 2, 2};
24+
int expected = 4;
25+
Assertions.assertEquals(expected, solution904.totalFruit(fruits));
26+
}
27+
28+
@Test
29+
public void example4() {
30+
int[] fruits = {3, 3, 3, 1, 2, 1, 1, 2, 3, 3, 4};
31+
int expected = 5;
32+
Assertions.assertEquals(expected, solution904.totalFruit(fruits));
33+
}
34+
}

leetcode-11/src/main/java/Solution1014.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
public class Solution1014 {
22
public int maxScoreSightseeingPair(int[] values) {
3-
int maxI = 0;
4-
int maxIj = 0;
5-
for (int j = 1; j < values.length; j++) {
6-
maxI = Math.max(maxI, values[j - 1] + j - 1);
7-
maxIj = Math.max(maxIj, maxI + values[j] - j);
3+
int n = values.length;
4+
// f[i] 表示 [0, i) 的 (values[i] + i) 最大值
5+
int[] f = new int[n + 1];
6+
int max = 0;
7+
for (int i = 0; i < n; i++) {
8+
max = Math.max(max, f[i] + values[i] - i);
9+
f[i + 1] = Math.max(f[i], values[i] + i);
810
}
9-
return maxIj;
11+
return max;
1012
}
1113
}
1214
/*
@@ -22,6 +24,7 @@ public int maxScoreSightseeingPair(int[] values) {
2224
2 <= values.length <= 5 * 10^4
2325
1 <= values[i] <= 1000
2426
27+
双指针 动态规划
2528
由于 用例 数值较大,需要将时间复杂度由 O(n^2) 优化到 O(n)
2629
当 i < j 时:
2730
f(i,j) = values[i] + values[j] + i - j == (values[i] + i) + (values[j] - j)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
public class Solution1031 {
2+
public int maxSumTwoNoOverlap(int[] nums, int firstLen, int secondLen) {
3+
return Math.max(dp(nums, firstLen, secondLen), dp(nums, secondLen, firstLen));
4+
}
5+
6+
private int dp(int[] nums, int firstLen, int secondLen) {
7+
int n = nums.length;
8+
// f[i] 表示 [0, i) 之间长为 firstLen 的最大和
9+
int[] f = new int[n + 1];
10+
int l = 0, r = 0, sum = 0, max = 0;
11+
while (r < n) {
12+
sum += nums[r];
13+
while (r - l + 1 > firstLen) sum -= nums[l++];
14+
max = Math.max(max, sum);
15+
f[r + 1] = Math.max(f[r], max);
16+
r++;
17+
}
18+
r = l = sum = max = 0;
19+
while (r < n) {
20+
sum += nums[r];
21+
while (r - l + 1 > secondLen) sum -= nums[l++];
22+
max = Math.max(max, sum + f[l]);
23+
r++;
24+
}
25+
return max;
26+
}
27+
}
28+
/*
29+
1031. 两个非重叠子数组的最大和
30+
https://leetcode.cn/problems/maximum-sum-of-two-non-overlapping-subarrays/
31+
32+
给出非负整数数组 A ,返回两个非重叠(连续)子数组中元素的最大和,子数组的长度分别为 L 和 M。(这里需要澄清的是,长为 L 的子数组可以出现在长为 M 的子数组之前或之后。)
33+
从形式上看,返回最大的 V,而 V = (A[i] + A[i+1] + ... + A[i+L-1]) + (A[j] + A[j+1] + ... + A[j+M-1]) 并满足下列条件之一:
34+
0 <= i < i + L - 1 < j < j + M - 1 < A.length, 或
35+
0 <= j < j + M - 1 < i < i + L - 1 < A.length.
36+
提示:
37+
L >= 1
38+
M >= 1
39+
L + M <= A.length <= 1000
40+
0 <= A[i] <= 1000
41+
42+
双指针 滑动窗口 动态规划
43+
L + M
44+
M + L
45+
各判断一次
46+
*/
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import org.junit.jupiter.api.Assertions;
2+
import org.junit.jupiter.api.Test;
3+
4+
public class Solution1031Tests {
5+
private final Solution1031 solution1031 = new Solution1031();
6+
7+
@Test
8+
public void example1() {
9+
int[] nums = {0, 6, 5, 2, 2, 5, 1, 9, 4};
10+
int firstLen = 1;
11+
int secondLen = 2;
12+
int expected = 20;
13+
Assertions.assertEquals(expected, solution1031.maxSumTwoNoOverlap(nums, firstLen, secondLen));
14+
}
15+
16+
@Test
17+
public void example2() {
18+
int[] nums = {3, 8, 1, 3, 2, 1, 8, 9, 0};
19+
int firstLen = 3;
20+
int secondLen = 2;
21+
int expected = 29;
22+
Assertions.assertEquals(expected, solution1031.maxSumTwoNoOverlap(nums, firstLen, secondLen));
23+
}
24+
25+
@Test
26+
public void example3() {
27+
int[] nums = {2, 1, 5, 6, 0, 9, 5, 0, 3, 8};
28+
int firstLen = 4;
29+
int secondLen = 3;
30+
int expected = 31;
31+
Assertions.assertEquals(expected, solution1031.maxSumTwoNoOverlap(nums, firstLen, secondLen));
32+
}
33+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
public class Solution1156 {
2+
public int maxRepOpt1(String text) {
3+
int n = text.length();
4+
char[] s = text.toCharArray();
5+
6+
int[] cntArr = new int[26];
7+
for (char ch : s) {
8+
cntArr[ch - 'a']++;
9+
}
10+
11+
int ans = 0;
12+
for (char ch = 'a'; ch <= 'z'; ch++) {
13+
// 双指针,交换次数
14+
int l = 0, r = 0, time = 0;
15+
while (r < n) {
16+
if (s[r] != ch) time++;
17+
while (time > 1) {
18+
if (s[l] != ch) time--;
19+
l++;
20+
}
21+
if (cntArr[ch - 'a'] >= r - l + 1) {
22+
ans = Math.max(ans, r - l + 1);
23+
}
24+
r++;
25+
}
26+
}
27+
return ans;
28+
}
29+
}
30+
/*
31+
1156. 单字符重复子串的最大长度
32+
https://leetcode.cn/problems/swap-for-longest-repeated-character-substring/
33+
34+
如果字符串中的所有字符都相同,那么这个字符串是单字符重复的字符串。
35+
给你一个字符串 text,你只能交换其中两个字符一次或者什么都不做,然后得到一些单字符重复的子串。返回其中最长的子串的长度。
36+
提示:
37+
1 <= text.length <= 20000
38+
text 仅由小写英文字母组成。
39+
40+
双指针 滑动窗口
41+
*/
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import org.junit.jupiter.api.Assertions;
2+
import org.junit.jupiter.api.Test;
3+
4+
public class Solution1156Tests {
5+
private final Solution1156 solution1156 = new Solution1156();
6+
7+
@Test
8+
public void example1() {
9+
String text = "ababa";
10+
int expected = 3;
11+
Assertions.assertEquals(expected, solution1156.maxRepOpt1(text));
12+
}
13+
14+
@Test
15+
public void example2() {
16+
String text = "aaabaaa";
17+
int expected = 6;
18+
Assertions.assertEquals(expected, solution1156.maxRepOpt1(text));
19+
}
20+
21+
@Test
22+
public void example3() {
23+
String text = "aaabbaaa";
24+
int expected = 4;
25+
Assertions.assertEquals(expected, solution1156.maxRepOpt1(text));
26+
}
27+
28+
@Test
29+
public void example4() {
30+
String text = "aaaaa";
31+
int expected = 5;
32+
Assertions.assertEquals(expected, solution1156.maxRepOpt1(text));
33+
}
34+
35+
@Test
36+
public void example5() {
37+
String text = "abcdef";
38+
int expected = 1;
39+
Assertions.assertEquals(expected, solution1156.maxRepOpt1(text));
40+
}
41+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
public class Solution1208 {
2+
public int equalSubstring(String s, String t, int maxCost) {
3+
int n = s.length();
4+
int l = 0, r = 0;
5+
int sum = 0;
6+
int max = 0;
7+
while (r < n) {
8+
sum += f(s, t, r);
9+
while (sum > maxCost) {
10+
sum -= f(s, t, l);
11+
l++;
12+
}
13+
max = Math.max(max, r - l + 1);
14+
r++;
15+
}
16+
return max;
17+
}
18+
19+
private int f(String s, String t, int i) {
20+
return Math.abs(s.charAt(i) - t.charAt(i));
21+
}
22+
}
23+
/*
24+
1208. 尽可能使字符串相等
25+
https://leetcode.cn/problems/get-equal-substrings-within-budget/
26+
27+
给你两个长度相同的字符串,s 和 t。
28+
将 s 中的第 i 个字符变到 t 中的第 i 个字符需要 |s[i] - t[i]| 的开销(开销可能为 0),也就是两个字符的 ASCII 码值的差的绝对值。
29+
用于变更字符串的最大预算是 maxCost。在转化字符串时,总开销应当小于等于该预算,这也意味着字符串的转化可能是不完全的。
30+
如果你可以将 s 的子字符串转化为它在 t 中对应的子字符串,则返回可以转化的最大长度。
31+
如果 s 中没有子字符串可以转化成 t 中对应的子字符串,则返回 0。
32+
提示:
33+
1 <= s.length, t.length <= 10^5
34+
0 <= maxCost <= 10^6
35+
s 和 t 都只含小写英文字母。
36+
37+
双指针 滑动窗口
38+
*/

0 commit comments

Comments
 (0)