public String minWindow(String s, String t) {
if (s.length() < t.length()) {
return "";
}
char[] sArr = s.toCharArray();
char[] tArr = t.toCharArray();
int[] hash = new int[256];
for (int i = 0; i < tArr.length; ++i) {
hash[tArr[i]]++;
}
int l = 0, count = tArr.length, max = s.length() + 1;
String result = "";
for (int r = 0; r < sArr.length; ++r) {
hash[sArr[r]]--;
if (hash[sArr[r]] >= 0) {
count--;
}
while (l < r && hash[sArr[l]] < 0) {
hash[sArr[l]]++;
l++;
}
if (count == 0 && max > r - l + 1) {
max = r - l + 1;
result = s.substring(l, r + 1);
}
}
return result;
}
159. Longest Substring with At Most Two Distinct Characters
public int lengthOfLongestSubstringTwoDistinct(String s) {
if (s == null || s.length() == 0) {
return 0;
}
char[] sArr = s.toCharArray();
int[] hash = new int[256];
int l = 0, count = 0, result = 1;
for (int r = 0; r < sArr.length; ++r) {
hash[sArr[r]]++;
if (hash[sArr[r]] == 1) {
count++;
}
while (count > 2) {
hash[sArr[l]]--;
if (hash[sArr[l]] == 0) {
count--;
}
l++;
}
result = Math.max(result, r - l + 1);
}
return result;
}
340. Longest Substring with At Most K Distinct Characters
和上题一样,把 2 变成 k 即可
public int lengthOfLongestSubstringKDistinct(String s, int k) {
if (s == null || s.length() == 0 || k == 0) {
return 0;
}
char[] sArr = s.toCharArray();
int[] hash = new int[256];
int l = 0, count = 0, result = 1;
for (int r = 0; r < sArr.length; ++r) {
hash[sArr[r]]++;
if (hash[sArr[r]] == 1) {
count++;
}
while (count > k) {
hash[sArr[l]]--;
if (hash[sArr[l]] == 0) {
count--;
}
l++;
}
result = Math.max(result, r - l + 1);
}
return result;
}
public int lengthOfLongestSubstring(String s) {
if (s == null || s.length() == 0) {
return 0;
}
char[] sArr = s.toCharArray();
int[] hash = new int[256];
int l = 0, result = 1;
for (int r = 0; r < sArr.length; ++r) {
hash[sArr[r]]++;
while (hash[sArr[r]] != 1) {
hash[sArr[l]]--;
l++;
}
result = Math.max(result, r - l + 1);
}
return result;
}
567. Permutation in String
public boolean checkInclusion(String s1, String s2) {
if (s1.length() > s2.length()) {
return false;
}
char[] s1Arr = s1.toCharArray();
char[] s2Arr = s2.toCharArray();
int[] hash = new int[26];
for (int i = 0; i < s1Arr.length; ++i) {
hash[s1Arr[i] - 'a']++;
}
int l = 0, count = 0;
for (int r = 0; r < s2Arr.length; ++r) {
hash[s2Arr[r] - 'a']--;
if (hash[s2Arr[r] - 'a'] >= 0) {
count++;
}
if (r >= s1Arr.length) {
hash[s2Arr[l] - 'a']++;
if (hash[s2Arr[l] - 'a'] >= 1) {
count--;
}
l++;
}
if (count == s1Arr.length) {
return true;
}
}
return false;
}
992. Subarrays with K Different Integers
看完了字符串类型的题目,这次来看看数组类型的,题目中的 subarray 已经明确了这个题可以考虑用滑动窗口,这题比较 trick 的一个地方在于,这里不是求最小值最大值,而是要你计数,但是如果每次仅仅加 1 的话又不太对,例如 A = [1,2,1,2,3], K = 2 这个例子,假如右指针移到 index 为 3 的位置,如果按之前的思路左指针根据 count 来移动,当前窗口是 [1,2,1,2],但是怎么把 [2,1] 给考虑进去呢?可以从数组和子数组的关系来思考,假如 [1,2,1,2] 是符合条件的数组,如果要计数的话,[1,2,1,2] 要求的结果是否和 [1,2,1] 的结果存在联系?这两个数组的区别在于多了一个新进来的元素,之前子数组计数没考虑到这个元素,假如把这个元素放到之前符合条件的子数组中组成的新数组也是符合条件的,我们看看这个例子中所有满足条件的窗口以及对应的满足条件的子数组情况:
[1,2,1,2,3] // 窗口满足条件
l r // 满足条件的子数组 [1,2]
[1,2,1,2,3] // 窗口满足条件
l r // 满足条件的子数组 [1,2],[2,1],[1,2,1]
[1,2,1,2,3] // 窗口满足条件
l r // 满足条件的子数组 [1,2],[2,1],[1,2,1],[1,2],[2,1,2],[1,2,1,2]
[1,2,1,2,3] // 窗口不满足条件,移动左指针至满足条件
l r
[1,2,1,2,3] // 窗口满足条件
l r // 满足条件的子数组 [1,2],[2,1],[1,2,1],[1,2],[2,1,2],[1,2,1,2],[2,3]
public double[] medianSlidingWindow(int[] nums, int k) {
if (nums == null || nums.length < k ) {
return new double[0];
}
double[] results = new double[nums.length - k + 1];
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder());
for (int i = 0; i < nums.length; ++i) {
// add current element into queue
maxHeap.offer(nums[i]);
minHeap.offer(maxHeap.poll());
if (minHeap.size() > maxHeap.size()) {
maxHeap.offer(minHeap.poll());
}
// record answer
if (i >= k - 1) {
results[i - k + 1] = minHeap.size() < maxHeap.size()
? maxHeap.peek() : ((long)maxHeap.peek() + minHeap.peek()) * 0.5;
if (maxHeap.contains(nums[i - k + 1])) {
maxHeap.remove(nums[i - k + 1]);
} else {
minHeap.remove(nums[i - k + 1]);
}
}
}
return results;
}