-
Notifications
You must be signed in to change notification settings - Fork 83
/
LongestRepeatingCharacterReplacement424.java
130 lines (118 loc) · 3.78 KB
/
LongestRepeatingCharacterReplacement424.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
/**
* Given a string that consists of only uppercase English letters, you can
* replace any letter in the string with another letter at most k times. Find
* the length of a longest substring containing all repeating letters you can
* get after performing the above operations.
*
* Note:
* Both the string's length and k will not exceed 104.
*
* Example 1:
* Input:
* s = "ABAB", k = 2
* Output:
* 4
*
* Explanation:
* Replace the two 'A's with two 'B's or vice versa.
*
* Example 2:
* Input:
* s = "AABABBA", k = 1
* Output:
* 4
*
* Explanation:
* Replace the one 'A' in the middle with 'B' and form "AABBBBA".
* The substring "BBBB" has the longest repeating letters, which is 4.
*/
public class LongestRepeatingCharacterReplacement424 {
public int characterReplacement(String s, int k) {
if (s == null || s.length() == 0) return 0;
int N = s.length();
char[] chars = s.toCharArray();
int[] map = new int[26];
Comparator<Point> comp = (p1, p2) -> Integer.compare(p2.count, p1.count);
PriorityQueue<Point> pq = new PriorityQueue(26, comp);
int res = 0;
int left = 0;
int right = 0;
while (right < N) {
char c = chars[right++];
pq.remove(new Point(c, map[c-'A']));
pq.add(new Point(c, map[c-'A'] + 1));
map[c-'A']++;
while (right - left - pq.peek().count > k) {
char leftC = chars[left++];
pq.remove(new Point(leftC, map[leftC-'A']));
pq.add(new Point(leftC, map[leftC-'A'] - 1));
map[leftC-'A']--;
}
if (right - left > res) {
res = right - left;
}
}
return res;
}
class Point {
char ch;
int count;
Point(char c, int cnt) {
ch = c;
count = cnt;
}
}
public int characterReplacement2(String s, int k) {
if (s == null || s.length() == 0) return 0;
int N = s.length();
char[] chars = s.toCharArray();
int[] map = new int[26];
int res = 0;
int left = 0;
int right = 0;
while (right < N) {
char c = chars[right++];
map[c-'A']++;
while (right - left - getMax(map) > k) {
char leftC = chars[left++];
map[leftC-'A']--;
}
if (right - left > res) {
res = right - left;
}
}
return res;
}
private int getMax(int[] map) {
int res = 0;
for (int c: map) {
if (c > res) {
res = c;
}
}
return res;
}
/**
* https://leetcode.com/problems/longest-repeating-character-replacement/discuss/91271/Java-12-lines-O(n)-sliding-window-solution-with-explanation
*
* maxCount may be invalid at some points, but this doesn't matter, because
* it was valid earlier in the string, and all that matters is finding the
* max window that occurred anywhere in the string. Additionally, it will
* expand if and only if enough repeating characters appear in the window
* to make it expand. So whenever it expands, it's a valid expansion.
*/
public int characterReplacement3(String s, int k) {
int len = s.length();
int[] count = new int[26];
int start = 0, maxCount = 0, maxLength = 0;
for (int end = 0; end < len; end++) {
maxCount = Math.max(maxCount, ++count[s.charAt(end) - 'A']);
while (end - start + 1 - maxCount > k) {
count[s.charAt(start) - 'A']--;
start++;
}
maxLength = Math.max(maxLength, end - start + 1);
}
return maxLength;
}
}