-
Notifications
You must be signed in to change notification settings - Fork 0
/
wkb78.java
161 lines (144 loc) · 5.39 KB
/
wkb78.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package weekly;
import java.util.Arrays;
public class wkb78 {
//ranking: 688 / 4347
//简单题,直接截取字符串判断是不是符合条件
public int divisorSubstrings(int num, int k) {
String n = num + "";
int ans = 0;
for (int i = k - 1; i < n.length(); i++) {
String sub = n.substring(i - k + 1, i + 1);
if (Integer.parseInt(sub) == 0) continue;
if (num % Integer.parseInt(sub) == 0) ans++;
}
return ans;
}
//中等题,前缀和算就好了,注意int数组会溢出,改成long
public int waysToSplitArray(int[] nums) {
long[] sum = new long[nums.length + 1];
for (int i = 0; i < nums.length; i++) {
sum[i + 1] = sum[i] + nums[i];
}
int ans = 0;
for (int i = 0; i < nums.length; i++) {
long pre = sum[i + 1];
long last = sum[nums.length] - sum[i + 1];
if (pre >= last && i != nums.length - 1) ans++;
}
return ans;
}
//中等题,排序后双指针做
/* public int maximumWhiteTiles(int[][] tiles, int carpetLen) {
Arrays.sort(tiles, (a, b) -> a[1] - b[1]);
int max = 0;
int left = 0;
int count = 0;
int sub = 0;
for (int i = 0; i < tiles.length; i++) {
//每次都与这块砖的右侧对其
int[] block = tiles[i];
//求左侧位置
int pre = block[1] - carpetLen + 1;
count += block[1] - block[0] + 1;
//去掉没有覆盖到的
while (left < i && tiles[left][1] < pre) {
count -= (tiles[left][1] - tiles[left][0] + 1);
//再减去这块砖的时候,要看下之前有没有减去
count += sub;
sub = 0;
left++;
}
//判断下left有没有没被覆盖的
if (tiles[left][0] < pre) {
int all = (pre - tiles[left][0]);
//这里也需要加上之前的sub
count -= (all - sub);
//表示这块砖已经减去了这些
sub = all;
}
max = Math.max(max, count);
}
return max;
}*/
//优化代码逻辑,去掉了sub变量
public int maximumWhiteTiles(int[][] tiles, int carpetLen) {
Arrays.sort(tiles, (a, b) -> a[1] - b[1]);
int max = 0;
int left = 0;
int count = 0;
for (int i = 0; i < tiles.length; i++) {
//每次都与这块砖的右侧对其
int[] block = tiles[i];
//求左侧位置
int pre = block[1] - carpetLen + 1;
count += block[1] - block[0] + 1;
//去掉没有覆盖到的
while (left < i && tiles[left][1] < pre) {
count -= (tiles[left][1] - tiles[left][0] + 1);
left++;
}
//判断下left有没有没被覆盖的
if (tiles[left][0] < pre) {
int all = (pre - tiles[left][0]);
//更新左侧端点,防止重复计算
tiles[left][0]=pre;
count -= all;
}
max = Math.max(max, count);
}
return max;
}
/* public int largestVariance(String s) {
int[][] dp = new int[26][26];
int[][] min = new int[26][26];
boolean[] can = new boolean[26];
int max = 0;
for (int i = 0; i < s.length(); i++) {
int c = s.charAt(i) - 'a';
can[c] = true;
for (int j = 0; j < dp.length; j++) {
if (!can[j]) continue;
dp[c][j]++;
min[c][j] = Math.min(min[c][j], dp[c][j]);
}
for (int j = 0; j < dp[0].length; j++) {
if (!can[j]) continue;
dp[j][c]--;
min[j][c] = Math.min(min[j][c], dp[j][c]);
}
for (int j = 0; j < dp.length; j++) {
for (int k = 0; k < dp.length; k++) {
if(!can[j]||!can[k]) continue;
max = Math.max(max, dp[j][k] - min[j][k]);
}
}
}
return max;
}*/
//困难题,真的没想到,二重循环枚举所有字母的,依次求这两个字母的波动值
//比如 a b a看成+1 ,b看成-1,模型就成了最大子数组和,但是限制b必须出现至少一次
//diff表示ab的差,最小是0,diffB表示带有b的ab的差,diffB可以初始成负无穷,表示答案不存在
//遇到a diff++,diffB++,遇到b diff--,diffB=diff,然后每次求max(diffB)
public int largestVariance(String s) {
int n = s.length();
int ans = 0;
for (int a = 'a'; a <= 'z'; a++) {
for (int b = 'a'; b <= 'z'; b++) {
if (a == b) continue;
int diff = 0;
int diffB = -n;
for (int i = 0; i < n; i++) {
if (s.charAt(i) == a) {
diff++;
diffB++;
} else if (s.charAt(i) == b) {
diffB = --diff;
diff = Math.max(0, diff);
}
ans = Math.max(ans, diffB);
}
}
}
return ans;
}
}