(1) Mostly used in sorted array, typical example is K Sum problem
2. Two Pointers start at the same end
(1) Cycle Detection algorithm (pointers move at different paces)
Idea: Define two pointers: fast pointer and slow pointer. if the cycle exists, find the place they meet in the first time. Then move slow pointer to the place it was in the beginning, and both pointer move at the same pace. The cycle starts at the place where these two pointers meet again(How to prove it?). Example: Find the Duplicate Number
public int findDuplicate(int[] nums) {
int fast = 0, slow = 0;
do {
fast = nums[nums[fast]];
slow = nums[slow];
}
while (fast != slow);
// Move slow pointer to the beginning
slow = 0;
while (fast != slow) {
fast = nums[fast];
slow = nums[slow];
}
// Cycle starts at the place where two pointers meet
return slow;
}
(2) Sliding Window (update start pointer when constraints is violated)
// Find All Anagrams in a String
public List<Integer> findAnagrams(String s, String p) {
List<Integer> res = new ArrayList<>();
if (s == null || s.length() == 0 || p == null || p.length() == 0) {
return res;
}
int start = 0, end = 0;
int count = p.length();
int[] map = new int[256];
// Put all characters in p into map
for (char c : p.toCharArray()) {
map[c]++;
}
while (end < s.length()) {
// When current character is in the map, decrease the count by 1
if (map[s.charAt(end)] > 0) {
--count;
}
--map[s.charAt(end)];
++end;
// When the size of window is equal to p.length(), update the start pointer
if (end - start - 1 == p.length()) {
// if current character pointed by start pointer is in p, increase count by 1
if (map[s.charAt(start)] >= 0) {
++count;
}
++map[s.charAt(start)];
++start;
}
// When count is 0, we find an answer
if (count == 0) {
res.add(start);
}
}
return res;
}
// Minimum Window Substring
public String minWindow(String s, String t) {
int[] map = new int[256];
int start = 0, end = 0, minStart = 0, minEnd = 0;
int count = t.length();
int minLen = Integer.MAX_VALUE;
for (char c : t.toCharArray()) {
++map[c];
}
while (end < s.length()) {
if (map[s.charAt(end)] > 0) {
--count;
}
--map[s.charAt(end)];
++end;
while (count == 0) {
if (end - start < minLen) {
minStart = start;
minEnd = end;
minLen = end - start;
}
if (map[s.charAt(start)] >= 0) {
++count;
}
++map[s.charAt(start)];
++start;
}
}
return minLen == Integer.MAX_VALUE ? "" : s.substring(minStart, minEnd);
}