Given a string, find the length of the longest substring without repeating characters.

Example 1:

Input: “abcabcbb” Output: 3 Explanation: The answer is “abc”, with the length of 3. Example 2:

Input: “bbbbb” Output: 1 Explanation: The answer is “b”, with the length of 1. Example 3:

Input: “pwwkew” Output: 3 Explanation: The answer is “wke”, with the length of 3.

Note that the answer must be a substring, “pwke” is a subsequence and not a substring.

This is the classic sliding window problem. we can use our sliding window template. Please review Leetcode 76 Minimun Window Substring.

```
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int left = 0, ans = 0;
int count = 0; /*❶*/
unordered_map<char, int> map;
for(int r = 0; r < s.size(); ++r){
if(++map[s[r]] > 1) { /*❷*/
count++;
}
while(count > 0) { /*❸*/
if(map[s[left]]-- > 1){
count--;
}
left++;
}
ans = max(ans, r - left + 1); /*❹*/
}
return ans;
}
};
```

❶ The property of the window. In this case, it is how many characters are repeated.

❷ The condition to move right edge of the window.

❸ The condition to move left edge of the window. In this case, if there is a character repeated, we need update left edge.

❹ Update the result. The place we update result is different from leetcode 76. Why?

You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.

You may assume the two numbers do not contain any leading zero, except the number 0 itself.

Example: Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) Output: 7 -> 0 -> 8 Explanation: 342 + 465 = 807.

This is a linkedlist question. For linkedlist question, we can use a dummy head for clear solution. It is not hard question. Just remember how iterate the linkedlist.

```
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
int carry = 0;
ListNode dummyHead(0);
ListNode* iter = &dummyHead; /*❶*/
while(carry || l1 || l2) { /*❷*/
if(l1){
carry += l1->val;
l1 = l1->next;
}
if(l2) {
carry += l2->val;
l2 = l2->next;
}
iter->next = new ListNode(carry%10);
iter = iter->next;
carry /= 10;
}
return dummyHead.next; /*❸*/
}
};
```

❶ use a dummy head.

❷ it is the template regarding to adding number with carry.

❸ return dummy head’s next.

Given an input string (s) and a pattern (p), implement regular expression matching with support for ‘.’ and ‘*’.

’.’ Matches any single character.

‘*’ Matches zero or more of the preceding element.

The matching should cover the entire input string (not partial).Note: s could be empty and contains only lowercase letters a-z. p could be empty and contains only lowercase letters a-z, and characters like . or *.

Example 1: Input: s = “aa” p = “a” Output: false

Explanation: “a” does not match the entire string “aa”.Example 2: Input: s = “aa” p = “a

” Output: true’ means zero or more of the precedeng element, ‘a’. Therefore, by repeating ‘a’ once, it becomes “aa”.

Explanation: ‘Example 3: Input: s = “ab” p = “.

” Output: true” means “zero or more (*) of any character (.)”.

Explanation: “.Example 4: Input: s = “aab” p = “c

ab” Output: true

Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore it matches “aab”.Example 5: Input: s = “mississippi” p = “mis

isp*.” Output: false

Use dynamic programming. dp[i][j] means if s[0…i-1] matches p[0…j-1].

The first case is easy to understand. Let check the second case, if p[j-1] = ‘*’ and we use * to match zero time, dp[i][j] = dp[i][j-2], it is because we want to match zero time, which (x*) is not useful and can be discarded. eg. aa* matches a. if we want to match more then zero times, which (x*) can be use multiple times. So if dp[i][j] = dp[i-1][j] &s[i-1] = p[j-2]. eg, aa* matches aaa, aa* doesn’t match abaa.

Also for all the dot, we can think of it equals to any character. please go through the example below to fully understand it.

```
class Solution {
public:
bool isMatch(string s, string p) {
int m = s.size();
int n = p.size();
vector<vector<bool>> res(m + 1, vector<bool>(n + 1, false));
res[0][0] = true; //s[0..i-1] p[0..j-1]
for(int i = 2; i <= n; ++i){
if('*' == p[i-1] && res[0][i-2]) {
res[0][i] = true;
}
}
for(int i = 1; i <= m; ++i) {
for(int j = 1; j <= n; ++j) {
if(p[j-1] != '*') {
res[i][j] = res[i-1][j-1] && (s[i-1] == p[j-1] || '.' == p[j-1]);
} else {
res[i][j] = res[i][j-2] /*match zero */|| (res[i-1][j] && (s[i-1] == p[j-2] || '.' == p[j-2])/*math more than zero times*/);
}
}
}
return res[m][n];
}
};
```

There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)). You may assume nums1 and nums2 cannot be both empty.

Example 1: nums1 = [1, 3] nums2 = [2] The median is 2.0

Example 2: nums1 = [1, 2] nums2 = [3, 4]

The median is (2 + 3)/2 = 2.5

This question can be solved in two ways. one is using find kth number in two sorted array. another is binary search. Let us talk about the binary search approach. First, we should know what’s the meaning of the median. Here is the quote from wiki:

The median is the value separating the higher half from the lower half of a data sample. So for the odd number of data element, the median will be the mid element. For the even number of data element, the median will be the average of mid two elements. Lets take the example from wiki:

After we know the definition of median, lets think about how can we find the median in two sort arrays. If it is one sorted array, we just need find one separating position in that array which is the mid position. So in two sorted array, what we need to do is find two separating positions in two arrays, which we can get two merged parts from two array with same size. Then we can simply calculate the median by the mid elements.

lets say we find two separating positions which help us get two merged array with same size, but we still have to make sure the first merged half are not larger than the second merged half. At this point, we are safe to use the elements at separating position.

For example:
We have two sorted arrays as below, calculate the two separating positions, mid1 and mid2. we will make first half has one more element when element number id odd.

Then we check if all the elements in first merged half not larger than the elements in second merged half. In this case, 12 is larger than 8. so we move mid1 backwards, and mid2 forwards to make sure the same size. And then we check again. This time works. and the median is max(8, 7).

```
lass Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int N1 = nums1.size();
int N2 = nums2.size();
if(N1 > N2) {
return findMedianSortedArrays(nums2, nums1);
}
int lo = 0, hi = N1;
while (lo <= hi) {
int mid1 = (lo + hi) / 2; /*❶*/
int mid2 = (N1+N2+1)/2 - mid1; /*❷*/
double L1 = (mid1 == 0) ? INT_MIN : nums1[mid1-1]; /*❸*/
double R1 = (mid1 == N1) ? INT_MAX : nums1[mid1];
double L2 = (mid2 == 0) ? INT_MIN : nums2[mid2-1];
double R2 = (mid2 == N2) ? INT_MAX : nums2[mid2];
if(L1 > R2) {
hi = mid1 - 1; /*❹*/
} else if(L2 > R1) {
lo = mid1 + 1; /*❺*/
} else { /*❻*/
if((N1+N2)%2 == 0) {
return (max(L1,L2) + min(R1, R2)) / 2;
} else {
return max(L1, L2);
}
}
}
return -1;
};
```

❶ Make sure num1 is the shorter one, we will do binary search on the shore one, why?.

❷ Find separating position mid2 in short array num2.

❸ Base on same size, calculate separating position in long array num2.

❹ Get L1, R1, L2, R2 respectively at separating position.

❺ The num1’s lower half is too big, need to move mid1 to left.

❻ The num2’s lower half is too big, need to move mid1 to right.

❼ L1 <= R2 && L2 <= R1, and we have two partitions with same number of elements.

In general, there are fours ways to traverse a tree, they are pre-order, in-order, post-order, and level-order. For the first three ways, we can do it clearly by using recursive as below.

```
void traverseTree(TreeNode* root) {
// base case of recursive
cout << root->value; /*❶*/
traverseTree(root->left);
cout << root->value; /*❷*/
traverseTree(root->right);
cout << root->value; /*❸*/
}
```

❶ visit root value here is pre-order

❷ visit root value here is in-order

❸ visit root value here is post-order

So for a tree as below, we can have three traverse result:

pre-order: [5, 4, 2, 0, 1, 6, 3]

in-order: [2, 0, 4, 1, 5, 6, 3]

post-order: [0, 2, 1, 4, 3, 6, 5]

And level order traverse is simple: [5, 4, 6, 2, 1, 3, 0]

- General binary tree/binary search tree recursive question.
Almost 99% of the binary tree question can be solved in recursive way. And there are three kind of question in general.
- pass the result value from top down to bottom.

Eg. Check valid BST( leetcode 98) - pass the result value from bottom to top.

Eg. Get Height of the tree. Check tree is balanced (leetcode 110). Check tree is symmetric (leetcode 101). Assign the value of each node to be the total number of nodes that belong to its left substree. - Pass the help value from bottom to top, and meanwhile update the result according to the help value. Most hard problem can be done by this approach. and there are many questions in leetcode you can practice.

- pass the result value from top down to bottom.
- Rebuild tree

Use two kinds of traverse result to rebuild the tree. - Serialize the tree structure.
- Binary search tree

To use BST properties to solve the problem. - Level order traverse question

- Have to decide
**which kind of traverse**we gonna use. Eg. if it is BST and we want to leverage the ordered property of the BST. In-order traverse is nice to use. if we want the value from left subtree and right subtree, post order is good to use. - Decide
**what operations**we need to do for current node. Eg. What values we need to return? how we update the result value? What relationship among root and its left subtree, right subtree.

We are keep tracking the binary search tree question, I will try to categorize each question. Another thing good to mention is many question can be solve in different way, but they all fits in categories we talked above.

ID | Question | Type |
---|---|---|

94 | Binary Tree Inorder Traversal | XXX |

95 | Unique Binary Search Trees II | XXX |

96 | Unique Binary Search Trees | XXX |

98 | Validate Binary Search Tree | XXX |

99 | Recover Binary Search Tree | XXX |

100 | Same Tree | XXX |

101 | Symmetric Tree | XXX |

102 | Binary Tree Level Order Traversal | XXX |

103 | Binary Tree Zigzag Level Order Traversal | XXX |

104 | Maximum Depth of Binary Tree | post-order，bottom up |

105 | Construct Binary Tree from Preorder and Inorder Traversal | XXX |

106 | Construct Binary Tree from Inorder and Postorder Traversal | XXX |

107 | Binary Tree Level Order Traversal II | XXX |

108 | Convert Sorted Array to Binary Search Tree | XXX |

110 | Balanced Binary Tree | XXX |

111 | Minimum Depth of Binary Tree | XXX |

112 | Path Sum | XXX |

113 | Path Sum II | XXX |

114 | Flatten Binary Tree to Linked List | XXX |

116 | Populating Next Right Pointers in Each Node | XXX |

117 | Populating Next Right Pointers in Each Node | XXX |

124 | Binary Tree Maximum Path Sum | post-order，bottom up，update result |

129 | Sum Root to Leaf Numbers | XXX |

144 | Binary Tree Preorder Traversal | XXX |

145 | Binary Tree Postorder Traversal | XXX |

156 | Binary Tree Upside Down | XXX |

173 | Binary Search Tree Iterator | XXX |

199 | Binary Tree Right Side View | XXX |

222 | Count Complete Tree Nodes | XXX |

226 | Invert Binary Tree | XXX |

230 | Kth Smallest Element in a BST | XXX |

235 | Lowest Common Ancestor of a Binary Search Tree | XXX |

236 | Lowest Common Ancestor of a Binary Tree | XXX |

250 | Count Univalue Subtrees | XXX |

255 | Verify Preorder Sequence in Binary Search Tree | XXX |

257 | Binary Tree Paths | XXX |

270 | Closest Binary Search Tree Value | XXX |

272 | Closest Binary Search Tree Value II | XXX |

285 | Inorder Successor in BST | XXX |

297 | Serialize and Deserialize Binary Tree | XXX |

298 | Binary Tree Longest Consecutive Sequence | XXX |

333 | Largest BST Subtree | XXX |

337 | House Robber III | XXX |

366 | Find Leaves of Binary Tree | XXX |

404 | Sum of Left Leaves | XXX |

426 | Convert Binary Search Tree to Sorted Doubly Linked List | XXX |

428 | Serialize and Deserialize N-ary Tree | XXX |

429 | N-ary Tree Level Order Traversal | XXX |

431 | Encode N-ary Tree to Binary Tree | XXX |

437 | Path Sum III | XXX |

449 | Serialize and Deserialize BST | XXX |

450 | Delete Node in a BST | XXX |

501 | Find Mode in Binary Search Tree | XXX |

508 | Most Frequent Subtree Sum | XXX |

510 | Inorder Successor in BST II | XXX |

513 | Find Bottom Left Tree Value | XXX |

515 | Find Largest Value in Each Tree Row | XXX |

536 | Construct Binary Tree from String | XXX |

538 | Convert BST to Greater Tree | XXX |

543 | Diameter of Binary Tree | XXX |

545 | Boundary of Binary Tree | XXX |

549 | Binary Tree Longest Consecutive Sequence II | XXX |

559 | Maximum Depth of N-ary Tree | XXX |

563 | Binary Tree Tilt | XXX |

572 | Subtree of Another Tree | XXX |

582 | Kill Process | XXX |

589 | N-ary Tree Preorder Traversal | XXX |

590 | N-ary Tree Postorder Traversal | XXX |

606 | Construct String from Binary Tree | XXX |

617 | Merge Two Binary Trees | XXX |

623 | Add One Row to Tree | XXX |

637 | Average of Levels in Binary Tree | XXX |

652 | Find Duplicate Subtrees | XXX |

653 | Two Sum IV - Input is a BST | XXX |

654 | Maximum Binary Tree | XXX |

655 | Print Binary Tree | XXX |

662 | Maximum Width of Binary Tree | XXX |

663 | Equal Tree Partition | XXX |

666 | Path Sum IV | XXX |

669 | Trim a Binary Search Tree | XXX |

671 | Second Minimum Node In a Binary Tree | XXX |

684 | Redundant Connection | XXX |

685 | Redundant Connection II | XXX |

687 | Longest Univalue Path | XXX |

700 | Search in a Binary Search Tree | XXX |

701 | Insert into a Binary Search Tree | XXX |

742 | Closest Leaf in a Binary Tree | XXX |

814 | Binary Tree Pruning | XXX |

834 | Sum of Distances in Tree | XXX |

863 | All Nodes Distance K in Binary Tree | XXX |

865 | Smallest Subtree with all the Deepest Nodes | XXX |

872 | Leaf-Similar Trees | XXX |

889 | Construct Binary Tree from Preorder and Postorder Traversal | XXX |

894 | All Possible Full Binary Trees | XXX |

897 | Increasing Order Search Tree | XXX |

919 | Complete Binary Tree Inserter | XXX |

951 | Flip Equivalent Binary Trees | XXX |

958 | Check Completeness of a Binary Tree | XXX |

965 | Univalued Binary Tree | XXX |

968 | Binary Tree Cameras | XXX |

971 | Flip Binary Tree To Match Preorder Traversal | XXX |

979 | Distribute Coins in Binary Tree | XXX |

987 | Vertical Order Traversal of a Binary Tree | XXX |

988 | Smallest String Starting From Leaf | XXX |

993 | Cousins in Binary Tree | XXX |

998 | Maximum Binary Tree II | XXX |

Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).

Example: Input: S = “ADOBECODEBANC”, T = “ABC” Output: “BANC”

Note: If there is no such window in S that covers all characters in T, return the empty string “”. If there is such window, you are guaranteed that there will always be only one unique minimum window in S.

This is the classic sliding window question. All the sliding window question can use the template below. Pay an attention to all the steps, and try to understand it very well.

```
class Solution {
public:
string minWindow(string s, string t) {
unordered_map<char, int> countMap;
for(auto c: t) { /*❶*/
countMap[c]++;
}
int left = 0;
int count = countMap.size();
int min = s.size();
string res = "";
for(int right = 0; right < s.size(); ++right) {
if(countMap.count(s[right])) { /*❷*/
if(--countMap[s[right]] == 0) {
count --;
}
}
while(count==0){
if(right - left + 1 <= min) { /*❸*/
min = right - left + 1;
res = s.substr(left, min);
}
if(countMap.count(s[left])) { /*❹*/
if( ++countMap[s[left]] > 0) {
count++;
}
}
left++; /*❹*/
}
}
return res;
}
};
```

❶ build a count map from the target

❷ moving right side of a window, and update a certain state

❸ update the result as the window is changed

❹ update a certain condition as window is changed.

❹ moving left side of the window, and in the while loop until it can not meet the condition.

Given an array of integers and an integer k, you need to find the total number of continuous subarrays whose sum equals to k.

Example 1: Input:nums = [1,1,1], k = 2 Output: 2 Note: The length of the array is in range [1, 20,000]. The range of numbers in the array is [-1000, 1000] and the range of the integer k is [-1e7, 1e7].

This question can be solved by using range sum approach. Basically, a sum of a range in a array can be calculated as below:

So, for this question, we can keep records of sum along with the array iteration, then check if there is an element in the past that helps build a range sum equals to target K.

```
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
int sum = 0, res = 0;
unordered_map<int, int> preSumCount;
preSumCount[0] = 1; /*❶*/
for(int i = 0; i < nums.size(); ++i) {
sum += nums[i];
if(preSumCount.count(sum - k)){ /*❷*/
res += preSumCount[sum - k];
}
preSumCount[sum]++; /*❸*/
}
return res;
}
};
```

❶ key is the sum value at current index, value is the number of current sum value.

❷ check if we have a right value, conforms sum(current) - sum(aValue) = K.

❸ update the map states.

We have a list of points on the plane. Find the K closest points to the origin (0, 0).

(Here, the distance between two points on a plane is the Euclidean distance.)

You may return the answer in any order. The answer is guaranteed to be unique (except for the order that it is in.)

Example 1: Input: points = [[1,3],[-2,2]], K = 1 Output: [[-2,2]] Explanation: The distance between (1, 3) and the origin is sqrt(10). The distance between (-2, 2) and the origin is sqrt(8). Since sqrt(8) < sqrt(10), (-2, 2) is closer to the origin. We only want the closest K = 1 points from the origin, so the answer is just [[-2,2]].

Example 2: Input: points = [[3,3],[5,-1],[-2,4]], K = 2 Output: [[3,3],[-2,4]] (The answer [[-2,4],[3,3]] would also be accepted.)

Note: 1 <= K <= points.length <= 10000 -10000 < points[i][0] < 10000 -10000 < points[i][1] < 10000

This question is the TopK question. For this kind of question, there are two ways to do it.

- Use priority queue. Eg, top k largest, we can use size k min-heap. or can we use size N max-heap, which N is whole data size.
- Use quick selection. Leverage the quick sort approach.

Here we are using second method. Time complexity average is O(n), worst is O(n^2), when pivot chosen is bad to reduce the data;

```
class Solution {
public:
vector<vector<int>> kClosest(vector<vector<int>>& points, int K) {
int len = points.size(), l = 0, r = len - 1;
kselection(points, l, r, K);
return vector<vector<int>>(points.begin(), points.begin()+K);
}
void kselection(vector<vector<int>>& points, int l, int r, int k) {
if(l >= r) return; /*❶*/
vector<int>& pivot = points[r]; /*❷*/
int i = l, j = l;
while(j < r) { /*❸*/
if(comparator(points[j], pivot) < 0) {
swap(points[i++], points[j++]);
} else {
j++;
}
}
swap(points[i], points[r]); /*❹*/
int num = i - l + 1;
if(num > k) {
kselection(points, l, i - 1, k); /*❺*/
} else if(num < k){
kselection(points, i + 1, r, k - num);
}
}
int comparator(vector<int>& lhs, vector<int>& rhs) {
return lhs[0] * lhs[0] + lhs[1]*lhs[1] - rhs[0]* rhs[0] - rhs[1]*rhs[1];
}
};
```

❶ Recursive base case.

❷ Choose last element as pivot.

❸ Three pointers approach for rainbow sort.

❹ When while loop ends, i is the position of the first element which value is larger than pivot.

❺ Decide which part we need to k select again.

Given a 32-bit signed integer, reverse digits of an integer.

Example 1: Input: 123 Output: 321

Example 2: Input: -123 Output: -321

Example 3: Input: 120 Output: 21

Note: Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−231, 231 − 1]. For the purpose of this problem, assume that your function returns 0 when the reversed integer overflows.

Use the typical way to get last digit of a number and shift the digit to most significant position. like,

```
int ret = 0;
while(x) {
int remain = x % 10;
...
ret = ret * 10 + remain;
x /= 10;
}
```

However, all the number conversion stuff needs to pay a attention about overflow. For a integer, the range is from -2147483648 to 2147483627. And we usually use this formula:

```
class Solution {
public:
int reverse(int x) {
int ret = 0;
while(x) {
int remain = x % 10;
if(ret > INT_MAX/10 || ret < INT_MIN/10) return 0; /*❶*/
/* if x is string, we need the second condition*/ /*❷*/
/* if(ret > INT_MAX/10 || (ret == INT_MAX/10 && remain > 7) ||
ret < INT_MIN/10 || (ret == INT_MIN/10 && remain < -8)) {
return 0;
} */
ret = ret * 10 + remain;
x /= 10;
}
return ret;
}
};
```

❶ As the input is integer, if the last digit is not 0, 1, 2, this is impossible to meet the condition (ret == INT_MAX/10 && remain > 7 or (ret == INT_MIN/10 && remain < -8)). So we can only use first set of condition.

❷ As the inpur is string, there could be other numbers beside 0, 1, 2.

Given an array A of 0s and 1s, we may change up to K values from 0 to 1. Return the length of the longest (contiguous) subarray that contains only 1s.

Example 1: Input: A = [1,1,1,0,0,0,1,1,1,1,0], K = 2 Output: 6 Explanation: [1,1,1,0,0,1,1,1,1,1,1] Bolded numbers were flipped from 0 to 1. The longest subarray is underlined.

Example 2: Input: A = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], K = 3 Output: 10 Explanation: [0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1] Bolded numbers were flipped from 0 to 1. The longest subarray is underlined.

Note: 1 <= A.length <= 20000 0 <= K <= A.length A[i] is 0 or 1

We can think this problem in another way. Lets use classic sliding window template in the thread

```
class Solution {
public:
int longestOnes(vector<int>& A, int K) {
int maxLength = 0;
int left = 0;
int count = 0;
for(int i = 0; i < A.size(); ++i) {
if(A[i] == 0) { /*❶*/
count++;
}
while(count > K) { /*❷*/
if(A[left] == 0){
count--;
}
left++;
}
maxLength = max(maxLength, i - left + 1);/*❸*/
}
return maxLength;
}
};
```

❶ update count, it is related to K.

❷ move left bound of window and update the count.

❸ update the length of window.

There are lots of questions can be solved by similar way. And sliding window technique is very popular approach.

]]>