Download PDF
1. Two Sum
Description
Given an array of integers, return indices of the two numbers such that they add
up to a specific target.
You may assume that each input would have exactly one solution, and you may not
use the same element twice.
Example:
01/02/2020:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> m;
for (int i = 0; i < nums.size(); ++i) {
if (m.find(target - nums[i]) == m.end()) {
m[nums[i]] = i;
} else {
return {m[target - nums[i]], i};
}
}
return {-1, -1};
}
};
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.
Solution
05/21/2020:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_map<char, int> seen;
int ret = 0, slow = 0, n = s.size();
for (int fast = 0; fast < n; ++fast) {
if (seen.count(s[fast]) != 0) slow = max(slow, seen[s[fast]] + 1);
seen[s[fast]] = fast;
ret = max(ret, fast - slow + 1);
}
return ret;
}
};
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)).
Example 1:
nums1 = [1, 3]
nums2 = [2]
nums1 = [1, 2]
nums2 = [3, 4]
Solution
01/02/2020:
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int n = nums1.size() + nums2.size();
vector<int> nums(n, 0);
auto it1 = nums1.begin();
auto it2 = nums2.begin();
auto it = nums.begin();
for (; it != nums.end(); ++it) {
*it = it2 == nums2.end() || (it1 != nums1.end() && *it1 < *it2) ? *it1++ :
*it2++;
}
if (n % 2 == 0) {
return ((double) nums[n/2] + nums[n/2-1]) / 2;
} else {
return (double) nums[n/2];
}
}
};
Given a string s, find the longest palindromic substring in s. You may assume
that the maximum length of s is 1000.
Example 1:
Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.
Example 2:
Input: "cbbd"
Output: "bb"
Solution
class Solution {
public:
string longestPalindrome(string s) {
int n = s.size(), start, max_len = 0;
if (n == 0) return "";
vector<vector<bool>> dp(n, vector<bool>(n, false));
for (int i = 0; i < n; ++i) dp[i][i] = true;
for (int i = 0; i < n - 1; ++i) dp[i][i + 1] = s[i] == s[i + 1];
for (int i = n - 3; i >= 0; --i) {
for (int j = i + 2; j < n; ++j) {
dp[i][j] = dp[i + 1][j - 1] && s[i] == s[j];
}
}
for (int i = 0; i < n; ++i) {
for (int j = i; j < n; ++j) {
if (dp[i][j] && j - i + 1 > max_len) {
max_len = j - i + 1;
start = i;
}
}
}
return s.substr(start, max_len);
}
};
class Solution {
public:
string longestPalindrome(string s) {
int n = s.size(), start = 0, max_len = n > 0 ? 1 : 0;
for(int i = 0; i < n; ++i) {
for (int l = i - 1, r = i; l >= 0 && r < n && s[l] == s[r]; --l, ++r) {
if (r - l + 1 > max_len) {
max_len = r - l + 1;
start = l;
}
}
for (int l = i - 1, r = i + 1; l >= 0 && r < n && s[l] == s[r]; --l, ++r)
{
if (r - l + 1 > max_len) {
max_len = r - l + 1;
start = l;
}
}
}
return max_len == 0 ? "" : s.substr(start, max_len);
}
};
6. ZigZag Conversion
Description
P A H N
A P L S I I G
Y I R
And then read line by line: "PAHNAPLSIIGYIR"
Write the code that will take a string and make this conversion given a number
of rows:
P I N
A L S I G
Y A H R
P I
Solution
05/24/2020:
class Solution {
public:
string convert(string s, int numRows) {
if (s.empty()) return "";
if (numRows <= 1) return s;
int k = 0, increment = 1;
vector<string> strs(numRows);
for (int i = 0; i < (int)s.size(); ++i) {
strs[k].push_back(s[i]);
if (k == numRows - 1) {
increment = -1;
} else if (k == 0) {
increment = 1;
}
k += increment;
}
string ret;
for (auto& s : strs) ret += s;
return ret;
}
};
The function first discards as many whitespace characters as necessary until the
first non-whitespace character is found. Then, starting from this character,
takes an optional initial plus or minus sign followed by as many numerical
digits as possible, and interprets them as a numerical value.
The string can contain additional characters after those that form the integral
number, which are ignored and have no effect on the behavior of this function.
Note:
Input: "42"
Output: 42
Example 2:
Input: "-91283472332"
Output: -2147483648
Explanation: The number "-91283472332" is out of the range of a 32-bit signed
integer.
Thefore INT_MIN (−231) is returned.
Solution
05/24/2020:
class Solution {
public:
int myAtoi(string str) {
long long ret = atol(str.c_str());
ret = ret > INT_MAX ? INT_MAX : ret;
ret = ret < INT_MIN ? INT_MIN : ret;
return ret;
}
};
class Solution {
public:
int myAtoi(string str) {
if (str.empty()) return 0;
long long ret = 0;
istringstream iss(str);
iss >> ret;
ret = ret < INT_MIN ? INT_MIN : ret;
ret = ret > INT_MAX ? INT_MAX : ret;
return ret;
}
};
Given n non-negative integers a1, a2, ..., an , where each represents a point at
coordinate (i, ai). n vertical lines are drawn such that the two endpoints of
line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis
forms a container, such that the container contains the most water.
Example:
Input: [1,8,6,2,5,4,8,3,7]
Output: 49
Solution
05/24/2020:
class Solution {
public:
int maxArea(vector<int>& height) {
int left = 0, right = height.size() - 1, ret = 0;
while (left < right) {
ret = max(ret, min(height[left], height[right]) * (right - left));
height[left] < height[right] ? left += 1 : right -= 1;
}
return ret;
}
};
Write a function to find the longest common prefix string amongst an array of
strings.
Example 1:
Input: ["flower","flow","flight"]
Output: "fl"
Example 2:
Input: ["dog","racecar","car"]
Output: ""
Explanation: There is no common prefix among the input strings.
Note:
Solution
05/24/2020:
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
if (strs.empty() || strs[0].empty()) return "";
int minLength = strs[0].size();
for (auto& s : strs) minLength = min(minLength, (int)s.size());
string ret;
for (int i = 0; i < minLength; ++i) {
char cur = strs[0][i];
for (int j = 1; j < (int)strs.size(); ++j) {
if (strs[j][i] != cur) {
return ret;
}
}
ret += cur;
}
return ret;
}
};
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
if (strs.empty() || strs[0].empty()) return "";
sort(strs.begin(), strs.end(), [](const string& s1, const string& s2) {
if (s1.size() == s2.size()) return s1 < s2;
return s1.size() < s2.size();
});
string ret;
for (int k = (int)strs[0].size(); k >= 0; --k) {
bool isCommonPrefix = true;
string prefix = strs[0].substr(0, k);
for (int i = 1; i < (int)strs.size(); ++i) {
if (prefix != strs[i].substr(0, k)) {
isCommonPrefix = false;
break;
}
}
if (isCommonPrefix) {
ret = prefix;
break;
}
}
return ret;
}
};
struct Node {
bool isWord;
vector<Node*> children;
Node() { isWord = false; children.resize(26, nullptr); }
~Node() { for (auto& c : children) delete c; }
};
class Trie {
private:
Node* root;
public:
Trie() { root = new Node(); }
string commonPrefix() {
string ret;
Node* cur = root;
while (true) {
int cnt = 0;
char ch = 'a';
bool isUnique = false;
for (int i = 0; i < 26; ++i) {
if (cur->children[i] != nullptr) {
isUnique = true;
if (++cnt > 1) {
isUnique = false;
break;
}
ch = i + 'a';
}
}
if (isUnique) {
ret += ch;
cur = cur->children[ch - 'a'];
} else {
break;
}
}
return ret;
}
};
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
Trie t;
int minLength = INT_MAX;
for (auto& s : strs) {
if (s.empty()) return "";
t.insert(s);
minLength = min(minLength, (int)s.size());
}
return t.commonPrefix().substr(0, minLength);
}
};
Given a linked list, remove the n-th node from the end of list and return its
head.
Example:
After removing the second node from the end, the linked list becomes 1->2->3->5.
Note:
Given n will always be valid.
Follow up:
Solution
05/23/2020:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode *pre = new ListNode(0, head), *slow = pre, *fast = pre;
while (fast->next != nullptr && n-- > 0) fast = fast->next;
while (fast->next != nullptr) {
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;
return pre->next;
}
};
Example:
Input:
[
1->4->5,
1->3->4,
2->6
]
Output: 1->1->2->3->4->4->5->6
Solution
01/02/2020:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
vector<int> v;
for (auto& l : lists) {
vector<int> tmp = ListNode2vector(l);
v.insert(v.begin(), tmp.begin(), tmp.end());
}
sort(v.begin(), v.end());
return vector2ListNode(v);
}
ListNode* vector2ListNode(vector<int>& v) {
ListNode *pre = new ListNode(0), *cur = pre;
for (auto& n : v) {
cur->next = new ListNode(n);
cur = cur->next;
}
return pre->next;
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
int n = lists.size();
if (n == 0) return nullptr;
if (n == 1) return lists[0];
vector<ListNode*> lists1(lists.begin(), lists.begin() + n / 2);
vector<ListNode*> lists2(lists.begin() + n / 2, lists.end());
ListNode* l1 = mergeKLists(lists1);
ListNode* l2 = mergeKLists(lists2);
if (l1 == nullptr) return l2;
ListNode* ret = l1;
while (l2 != nullptr) {
if (l1->val > l2->val) swap(l1->val, l2->val);
while(l1->next && l1->next->val < l2->val) l1 = l1->next;
ListNode* tmp2 = l2->next;
l2->next = l1->next;
l1->next = l2;
l2 = tmp2;
}
return ret;
}
};
You may not modify the values in the list's nodes, only nodes itself may be
changed.
Example:
Solution
05/22/2020:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
// pre -> A -> B -> C -> D -> null
// pre -> B (pre->next = pre->next->next)
// A -> C (A->next = A->next->next)
// B -> A (B->next = A):
// (B -> A -> C -> D -> null)
ListNode* pre = new ListNode(0, head);
ListNode* cur = pre;
while (cur->next && cur->next->next) {
ListNode* tmp = cur->next;
cur->next = cur->next->next;
tmp->next = tmp->next->next;
cur->next->next = tmp;
cur = tmp;
}
return pre->next;
}
};
26. Remove Duplicates from Sorted Array
Description
Given a sorted array nums, remove the duplicates in-place such that each element
appear only once and return the new length.
Do not allocate extra space for another array, you must do this by modifying the
input array in-place with O(1) extra memory.
Example 1:
Your function should return length = 2, with the first two elements of nums
being 1 and 2 respectively.
Your function should return length = 5, with the first five elements of nums
being modified to 0, 1, 2, 3, and 4 respectively.
It doesn't matter what values are set beyond the returned length.
Clarification:
Confused why the returned value is an integer but your answer is an array?
Note that the input array is passed in by reference, which means modification to
the input array will be known to the caller as well.
Solution
05/27/2020:
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if (nums.size() <= 1) return nums.size();
int slow = 0, fast = 1, n = nums.size();
for (; fast < n; ++fast) {
while (nums[fast] == nums[fast - 1]) if (++fast >= n) break;
if (fast < n) nums[++slow] = nums[fast];
}
return slow + 1;
}
};
Given an array nums and a value val, remove all instances of that value in-place
and return the new length.
Do not allocate extra space for another array, you must do this by modifying the
input array in-place with O(1) extra memory.
The order of elements can be changed. It doesn't matter what you leave beyond
the new length.
Example 1:
Your function should return length = 2, with the first two elements of nums
being 2.
Your function should return length = 5, with the first five elements of nums
containing 0, 1, 3, 0, and 4.
It doesn't matter what values are set beyond the returned length.
Clarification:
Confused why the returned value is an integer but your answer is an array?
Note that the input array is passed in by reference, which means modification to
the input array will be known to the caller as well.
Solution
05/23/2020:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int right = nums.size() - 1, n = nums.size(), cnt = n;
for (int i = 0; i < n && i <= right; ++i) {
while (right >= 0 && nums[right] == val) {
--right;
--cnt;
}
if (nums[i] == val && i <= right) {
swap(nums[i], nums[right--]);
--cnt;
}
}
return cnt;
}
};
You are given a target value to search. If found in the array return its index,
otherwise return -1.
Example 1:
Solution
04/28/2020:
class Solution {
public:
int search(vector<int>& nums, int target) {
int lo = 0, hi = nums.size() - 1;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
if (nums[mid] == target) {
return mid;
} else {
if (nums[mid] < nums[lo]) {
if (target > nums[lo] && target > nums[hi]) {
hi = mid - 1;
} else {
lo = mid + 1;
}
} else {
if (target > nums[lo] && target > nums[hi]) {
hi = mid - 1;
} else {
lo = mid + 1;
}
}
}
}
return -1;
}
};
Given an array of integers nums sorted in ascending order, find the starting and
ending position of a given target value.
Example 1:
Solution
04/28/2020:
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
if (nums.empty()) return {-1, -1};
int n = nums.size();
int lower = -1, upper = -1;
// to find lower_bound
int lo = 0, hi = n - 1;
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (nums[mid] >= target) {
hi = mid;
} else {
lo = mid + 1;
}
}
if (nums[lo] < target) ++lo;
lower = lo;
if (lower > hi) return {-1, -1};
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
if (binary_search(nums.begin(), nums.end(), target)) {
auto p = equal_range(nums.begin(), nums.end(), target);
return {int(p.first - nums.begin()), int(p.second - nums.begin() - 1)};
} else {
return {-1, -1};
}
}
};
Given a sorted array and a target value, return the index if the target is
found. If not, return the index where it would be if it were inserted in order.
Example 1:
Input: [1,3,5,6], 5
Output: 2
Example 2:
Input: [1,3,5,6], 2
Output: 1
Example 3:
Input: [1,3,5,6], 7
Output: 4
Example 4:
Input: [1,3,5,6], 0
Output: 0
Solution
04/23/2020:
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int lo = 0, hi = nums.size() - 1;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] > target) {
hi = mid - 1;
} else {
lo = mid + 1;
}
}
return lo;
}
};
The count-and-say sequence is the sequence of integers with the first five terms
as following:
1. 1
2. 11
3. 21
4. 1211
5. 111221
1 is read off as "one 1" or 11.
11 is read off as "two 1s" or 21.
21 is read off as "one 2, then one 1" or 1211.
Given an integer n where 1 ≤ n ≤ 30, generate the nth term of the count-and-say
sequence. You can do so recursively, in other words from the previous member
read off the digits, counting the number of digits in groups of the same digit.
Example 1:
Input: 1
Output: "1"
Explanation: This is the base case.
Example 2:
Input: 4
Output: "1211"
Explanation: For n = 3 the term was "21" in which we have two groups "2" and
"1", "2" can be read as "12" which means frequency = 1 and value = 2, the same
way "1" is read as "11", so the answer is the concatenation of "12" and "11"
which is "1211".
Solution
05/24/2020:
class Solution {
public:
string countAndSay(int n) {
if (n == 1) return "1";
string s = countAndSay(n - 1);
string ret;
int cnt = 1;
char cur = s[0];
for (int i = 1; i < (int)s.size(); ++i) {
if (s[i] == cur) {
++cnt;
} else {
ret += to_string(cnt) + cur;
cur = s[i];
cnt = 1;
}
}
if (cnt > 0) {
ret += to_string(cnt) + cur;
}
return ret;
}
};
Given an unsorted integer array, find the smallest missing positive integer.
Example 1:
Input: [1,2,0]
Output: 3
Example 2:
Input: [3,4,-1,1]
Output: 2
Example 3:
Input: [7,8,9,11,12]
Output: 1
Note:
Your algorithm should run in O(n) time and uses constant extra space.
Solution
05/24/2020:
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
unordered_set<int> seen;
for (auto& i : nums) {
if (i > 0) {
seen.insert(i);
}
}
int i = 1, n = nums.size();
while (i <= n) {
if (seen.count(i) == 0) return i;
++i;
}
return i;
}
};
46. Permutations
Description
Example:
Input: [1,2,3]
Output:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
Solution
class Solution {
public:
vector<vector<int>> permute(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<vector<int>> ret{nums};
while (next_permutation(nums.begin(), nums.end())) ret.push_back(nums);
return ret;
}
};
05/26/2020 (Backtracking):
class Solution {
public:
vector<vector<int>> permute(vector<int>& nums) {
int n = nums.size(),numOfChosen = 0;
vector<bool> chosen(n, false);
vector<vector<int>> ret;
vector<int> permutation;
backtrack(nums, chosen, numOfChosen, permutation, ret);
return ret;
}
05/05/2020:
class Solution {
public:
vector<vector<int>> permute(vector<int>& nums) {
int n = nums.size();
if (n <= 1) return {nums};
vector<vector<int>> ret;
for (int i = 0; i < n; ++i) {
int cur = nums[i];
swap(nums[i], nums[n - 1]);
nums.pop_back();
vector<vector<int>> sub = permute(nums);
for (auto& s : sub) {
s.push_back(cur);
ret.push_back(s);
}
nums.push_back(cur);
swap(nums[i], nums[n - 1]);
}
return ret;
}
};
50. Pow(x, n)
Description
Example 1:
Input: 2.00000, 10
Output: 1024.00000
Example 2:
Input: 2.10000, 3
Output: 9.26100
Example 3:
Input: 2.00000, -2
Output: 0.25000
Explanation: 2-2 = 1/22 = 1/4 = 0.25
Note:
Solution
04/23/2020:
Discussion
Binary Exponentiation: given a positive power n, e.g., n = 22 (binary: 10110) = 16 (binary:
10000) + 4 (binary: 100)+ 2 (binary: 10), then pow(x, n) = x^n = x^22 = x^(16 + 4 +
2) = x^16 * x^4 * x^2. For negative powers, we just flip the sign first, and once we calculate the
value and return its reciprocal.
Time complexity: O(n);
Space complexity: O(1).
class Solution {
public:
double myPow(double x, int n) {
long double ret = 1.0, pow_x = x;
for (long m = n >= 0 ? (long)n : -1 * (long)n; m != 0; m >>= 1) {
if (m & 1) ret *= pow_x;
pow_x = pow_x * pow_x;
}
return n >= 0 ? ret : 1.0L / ret;
}
};
51. N-Queens
Description
The n-queens puzzle is the problem of placing n queens on an n×n chessboard such
that no two queens attack each other.
Example:
Input: 4
Output: [
[".Q..", // Solution 1
"...Q",
"Q...",
"..Q."],
["..Q.", // Solution 2
"Q...",
"...Q",
".Q.."]
]
Explanation: There exist two distinct solutions to the 4-queens puzzle as shown
above.
Solution
05/27/2020:
class Solution {
public:
unordered_set<string> seen;
vector<vector<string>> solveNQueens(int n) {
vector<vector<string>> ret;
vector<string> board(n, string(n, '.'));
vector<bool> col(n, false);
vector<bool> diag1(2 * n - 1, false);
vector<bool> diag2(2 * n - 1, false);
backtrack(0, n, board, col, diag1, diag2, ret);
return ret;
}
Example:
Input: [-2,1,-3,4,-1,2,1,-5,4],
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.
Follow up:
If you have figured out the O(n) solution, try coding another solution using the
divide and conquer approach, which is more subtle.
Solution
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int n = nums.size(), max_sum = nums[0];
for (int i = 1; i < n; ++i) {
if (nums[i - 1] > 0) nums[i] += nums[i - 1];
max_sum = max(max_sum, nums[i]);
}
return max_sum;
}
};
1984
526
Add to List
Share
Given a matrix of m x n elements (m rows, n columns), return all elements of the
matrix in spiral order.
Example 1:
Input:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
Output: [1,2,3,6,9,8,7,4,5]
Example 2:
Input:
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12]
]
Output: [1,2,3,4,8,12,11,10,9,5,6,7]
Solution
04/23/2020:
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
int m = matrix.size();
if (m == 0) return {};
int n = matrix[0].size();
if (n == 0) return {};
vector<vector<int>> dir{ {0, 1}, {1, 0}, {0, -1}, {-1, 0} };
vector<int> ret;
int N = m * n, d = 0, i = 0, j = -1;
while (ret.size() < N) {
int ni = i + dir[d][0], nj = j + dir[d][1];
while (ni < 0 || ni >= m || nj < 0 || nj >= n || matrix[ni][nj] ==
INT_MIN) {
d = (d + 1) % 4;
ni = i + dir[d][0], nj = j + dir[d][1];
}
ret.push_back(matrix[ni][nj]);
matrix[ni][nj] = INT_MIN;
i = ni;
j = nj;
}
return ret;
}
};
Each element in the array represents your maximum jump length at that position.
Example 1:
Input: [2,3,1,1,4]
Output: true
Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index.
Example 2:
Input: [3,2,1,0,4]
Output: false
Explanation: You will always arrive at index 3 no matter what. Its maximum
jump length is 0, which makes it impossible to reach the last
index.
Solution
04/24/2020:
class Solution {
public:
bool canJump(vector<int>& nums) {
int ret = 0, n = nums.size();
for (int i = 0; i < n; ++i) {
if (i <= ret) {
ret = max(i + nums[i], ret);
} else {
break;
}
}
return ret >= n - 1;
}
};
59. Spiral Matrix II
Description
Given a positive integer n, generate a square matrix filled with elements from 1
to n2 in spiral order.
Example:
Input: 3
Output:
[
[ 1, 2, 3 ],
[ 8, 9, 4 ],
[ 7, 6, 5 ]
]
Solution
Discussion:
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
if (n <= 0) return {};
vector<vector<int>> dir{ {0, 1}, {1, 0}, {0, -1}, {-1, 0} };
vector<vector<int>> matrix(n, vector<int>(n, 0));
int i = 0, j = -1, d = 0, N = n * n, cnt = 0;
while (cnt < N) {
int ni = i + dir[d][0], nj = j + dir[d][1];
while (ni < 0 || ni >= n || nj < 0 || nj >= n || matrix[ni][nj] != 0) {
d = (d + 1) % 4;
ni = i + dir[d][0];
nj = j + dir[d][1];
}
i = ni;
j = nj;
matrix[i][j] = ++cnt;
}
return matrix;
}
};
By listing and labeling all of the permutations in order, we get the following
sequence for n = 3:
"123"
"132"
"213"
"231"
"312"
"321"
Given n and k, return the kth permutation sequence.
Note:
Input: n = 3, k = 3
Output: "213"
Example 2:
Input: n = 4, k = 9
Output: "2314"
Solution
05/26/2020:
class Solution {
public:
string getPermutation(int n, int k) {
string s;
for (int i = 0; i < n; ++i) s += to_string(i + 1);
while (--k > 0 && next_permutation(s.begin(), s.end()));
return s;
}
};
The digits are stored such that the most significant digit is at the head of the
list, and each element in the array contain a single digit.
You may assume the integer does not contain any leading zero, except the number
0 itself.
Example 1:
Input: [1,2,3]
Output: [1,2,4]
Explanation: The array represents the integer 123.
Example 2:
Input: [4,3,2,1]
Output: [4,3,2,2]
Explanation: The array represents the integer 4321.
Solution
05/23/2020:
class Solution {
public:
vector<int> plusOne(vector<int>& digits) {
if (digits.empty()) return {1};
int carry = 1, n = digits.size();;
for (int i = n - 1; i >= 0; --i) {
carry += digits[i];
digits[i] = carry % 10;
carry /= 10;
}
if (carry > 0) digits.insert(digits.begin(), carry);
return digits;
}
};
Given two binary strings, return their sum (also a binary string).
The input strings are both non-empty and contains only characters 1 or 0.
Example 1:
Constraints:
Solution
05/12/2020:
class Solution {
public:
string addBinary(string a, string b) {
int i = a.size() - 1, j = b.size() - 1;
int carry = 0;
string ret;
for (; i >= 0 || j >= 0; --i, --j) {
if (i >= 0) carry += a[i] - '0';
if (j >= 0) carry += b[j] - '0';
ret += (carry & 1) + '0';
carry >>= 1;
}
if (carry > 0) ret += carry + '0';
reverse(ret.begin(), ret.end());
return ret;
}
};
69. Sqrt(x)
Description
Since the return type is an integer, the decimal digits are truncated and only
the integer part of the result is returned.
Example 1:
Input: 4
Output: 2
Example 2:
Input: 8
Output: 2
Explanation: The square root of 8 is 2.82842..., and since
the decimal part is truncated, 2 is returned.
Solution
04/28/2020:
class Solution {
public:
int mySqrt(int x) {
int lo = 0, hi = x;
while (lo <= hi) {
long long mid = lo + (hi - lo) / 2;
long long sq = mid * mid;
if (sq == x) {
return mid;
} else if (sq > x) {
hi = mid - 1;
} else {
lo = mid + 1;
}
}
return hi;
}
};
Each time you can either climb 1 or 2 steps. In how many distinct ways can you
climb to the top?
Example 1:
Input: 2
Output: 2
Explanation: There are two ways to climb to the top.
1. 1 step + 1 step
2. 2 steps
Example 2:
Input: 3
Output: 3
Explanation: There are three ways to climb to the top.
1. 1 step + 1 step + 1 step
2. 1 step + 2 steps
3. 2 steps + 1 step
Solution
class Solution {
public:
int climbStairs(int n) {
int s1 = 1, s2 = 2;
for (int i = 2; i < n; ++i) {
s1 = s1 + s2;
swap(s1, s2);
}
return n >= 2 ? s2 : s1;
}
};
Given two words word1 and word2, find the minimum number of operations required
to convert word1 to word2.
You have the following 3 operations permitted on a word:
Insert a character
Delete a character
Replace a character
Example 1:
Solution
05/31/2020:
class Solution {
public:
int minDistance(string word1, string word2) {
int m = word1.size(), n = word2.size();
if (m == 0) return n;
if (n == 0) return m;
const int INF = 1e9 + 5;
vector<vector<int>> dp(m + 1, vector(n + 1, INF));
dp[0][0] = 0;
// dp[i][j]: the edit distance between word1[0..i] and word2[0..j]
// dp[i][j] = dp[i - 1][j - 1] if word1[i] == word2[j]: no operations
needed
// dp[i][j] = min( if word1[i] != word2[j]
// dp[i - 1][j - 1] + 1, replace word1[i] by word2[j]
// dp[i - 1][j] + 1, delete character word1[i]
// dp[i][j - 1] + 1 delete character word2[j]
// )
for (int i = 1; i <= m; ++i) dp[i][0] = dp[i - 1][0] + 1;
for (int j = 1; j <= n; ++j) dp[0][j] = dp[0][j - 1] + 1;
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
if (word1[i - 1] == word2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1];
} else {
dp[i][j] = min(dp[i - 1][j], min(dp[i][j - 1], dp[i - 1][j - 1])) + 1;
}
}
}
return dp[m][n];
}
};
class Solution {
public:
int minDistance(string word1, string word2) {
int m = word1.size(), n = word2.size();
vector<vector<int>> dp(m + 1, vector<int>(n + 1, INT_MAX));
for (int i = 0; i <= m; ++i) {
for (int j = 0; j <= n; ++j) {
if (i == 0) {
dp[i][j] = j;
} else if (j == 0) {
dp[i][j] = i;
} else if (word1[i - 1] == word2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1];
} else {
dp[i][j] = min({dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]}) + 1;
}
}
}
return dp[m][n];
}
};
Input:
matrix = [
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
target = 3
Output: true
Example 2:
Input:
matrix = [
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
target = 13
Output: false
Solution
05/23/2020:
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
if (matrix.empty() || matrix[0].empty()) return false;
int m = matrix.size(), n = matrix[0].size();
int lo = 0, hi = m * n - 1;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
int i = mid / n, j = mid % n;
if (matrix[i][j] == target) {
return true;
} else if (matrix[i][j] < target) {
lo = mid + 1;
} else {
hi = mid - 1;
}
}
return false;
}
};
75. Sort Colors
Description
Given an array with n objects colored red, white or blue, sort them in-place so
that objects of the same color are adjacent, with the colors in the order red,
white and blue.
Here, we will use the integers 0, 1, and 2 to represent the color red, white,
and blue respectively.
Note: You are not suppose to use the library's sort function for this problem.
Example:
Input: [2,0,2,1,1,0]
Output: [0,0,1,1,2,2]
Follow up:
Solution
05/12/2020:
class Solution {
public:
void sortColors(vector<int>& nums) {
sort(nums.begin(), nums.end());
}
};
77. Combinations
Description
Given two integers n and k, return all possible combinations of k numbers out of
1 ... n.
Example:
Input: n = 4, k = 2
Output:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
Solution
05/27/2020:
class Solution {
public:
vector<vector<int>> combine(int n, int k) {
vector<int> combination;
vector<vector<int>> ret;
vector<bool> chosen(n + 1, false);
backtrack(1, n, k, chosen, combination, ret);
return ret;
}
78. Subsets
Description
Given a set of distinct integers, nums, return all possible subsets (the power
set).
Example:
Solution
05/26/2020:
class Solution {
public:
vector<int> subset;
vector<vector<int>> s;
int n;
vector<vector<int>> subsets(vector<int>& nums) {
n = nums.size();
search(0);
vector<vector<int>> ret;
for (auto& ss : s) {
vector<int> tmp;
for (auto& i : ss) {
tmp.push_back(nums[i]);
}
ret.push_back(tmp);
}
return ret;
}
void search(int k) {
if (k == n) {
s.push_back(subset);
} else {
subset.push_back(k);
search(k + 1);
subset.pop_back();
search(k + 1);
}
}
};
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> ret;
vector<int> subset;
backtrack(0, nums, subset, ret);
return ret;
}
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> ret{ {} };
for (auto& n : nums) {
int sz = ret.size();
for (int i = 0; i < sz; ++i) {
ret.push_back(ret[i]);
ret.back().push_back(n);
}
}
return ret;
}
};
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> ret;
vector<int> subset;
backtrack(0, nums, subset, ret);
return ret;
}
Given a 2D board and a word, find if the word exists in the grid.
The word can be constructed from letters of sequentially adjacent cell, where
"adjacent" cells are those horizontally or vertically neighboring. The same
letter cell may not be used more than once.
Example:
board =
[
['A','B','C','E'],
['S','F','C','S'],
['A','D','E','E']
]
Constraints:
board and word consists only of lowercase and uppercase English letters.
1 <= board.length <= 200
1 <= board[i].length <= 200
1 <= word.length <= 10^3
Solution
05/27/2020:
class Solution {
public:
int dir[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
bool exist(vector<vector<char>>& board, string word) {
if (word.empty()) return true;
if (board.empty() || board[0].empty()) return false;
int m = board.size(), n = board[0].size(), k = word.size();
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
if (backtrack(board, word, i, j, 0))
return true;
return false;
}
Given a sorted array nums, remove the duplicates in-place such that duplicates
appeared at most twice and return the new length.
Do not allocate extra space for another array, you must do this by modifying the
input array in-place with O(1) extra memory.
Example 1:
Your function should return length = 5, with the first five elements of nums
being 1, 1, 2, 2 and 3 respectively.
Your function should return length = 7, with the first seven elements of nums
being modified to 0, 0, 1, 1, 2, 3 and 3 respectively.
It doesn't matter what values are set beyond the returned length.
Clarification:
Confused why the returned value is an integer but your answer is an array?
Note that the input array is passed in by reference, which means modification to
the input array will be known to the caller as well.
Solution
05/27/2020:
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if (nums.size() <= 2) return nums.size();
int slow = 0, fast = 1, n = nums.size(), cnt = 1;
for (; fast < n; ++fast) {
while (fast < n && nums[fast] == nums[fast - 1]) {
if (cnt <= 1) {
++cnt;
nums[++slow] = nums[fast];
}
++fast;
}
if (fast < n && nums[fast] != nums[slow]) {
cnt = 1;
nums[++slow] = nums[fast];
}
}
return slow + 1;
}
};
You are given a target value to search. If found in the array return true,
otherwise return false.
Example 1:
This is a follow up problem to Search in Rotated Sorted Array, where nums may
contain duplicates.
Would this affect the run-time complexity? How and why?
Solution
05/27/2020:
class Solution {
public:
bool search(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());
return binary_search(nums.begin(), nums.end(), target);
}
};
Given a sorted linked list, delete all duplicates such that each element appear
only once.
Example 1:
Input: 1->1->2
Output: 1->2
Example 2:
Input: 1->1->2->3->3
Output: 1->2->3
Solution
05/27/2020:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if (head == nullptr || head->next == nullptr) return head;
ListNode *slow = head, *fast = head->next;
while (fast->next) {
while (fast && fast->val == slow->val && fast->next) fast = fast->next;
if (fast && fast->val != slow->val) {
slow->next = fast;
slow = slow->next;
}
}
if (slow->val == fast->val) {
slow->next = fast->next;
}
return head;
}
};
Given n non-negative integers representing the histogram's bar height where the
width of each bar is 1, find the area of largest rectangle in the histogram.
The largest rectangle is shown in the shaded area, which has area = 10 unit.
Solution
01/14/2020 (Stack):
class Solution {
public:
// Approach 1: Brute Force
// int largestRectangleArea(vector<int>& heights) {
// int max_area = INT_MIN;
// for (int i = 0; i < heights.size(); ++i) {
// for (int j = i; j < heights.size(); ++j) {
// int min_height = *min_element(heights.begin() + i, heights.begin() +
j + 1);
// max_area = max(max_area, min_height * (j - i + 1));
// }
// }
// return max_area;
// }
// Approach 4: Stack
int largestRectangleArea(vector<int>& heights) {
stack<int> s;
s.push(-1);
int max_area = 0;
for (int i = 0; i < heights.size(); ++i) {
while (s.top() != -1 && heights[s.top()] >= heights[i]) {
int k = s.top();
s.pop();
max_area = max(max_area, heights[k] * (i - s.top() - 1));
}
s.push(i);
}
while (s.top() != -1) {
int k = s.top();
s.pop();
max_area = max(max_area, heights[k] * ((int)heights.size() - s.top() -
1));
}
return max_area;
}
};
88. Merge Sorted Array
Description
Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one
sorted array.
Note:
The number of elements initialized in nums1 and nums2 are m and n respectively.
You may assume that nums1 has enough space (size that is greater or equal to m +
n) to hold additional elements from nums2.
Example:
Input:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3
Output: [1,2,2,3,5,6]
Solution
05/23/2020:
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
copy(nums2.begin(), nums2.end(), nums1.begin() + m);
inplace_merge(nums1.begin(), nums1.begin() + m, nums1.end());
}
};
Example:
Input: [1,null,2,3]
1
\
2
/
3
Output: [1,3,2]
Follow up: Recursive solution is trivial, could you do it iteratively?
Solution
05/20/2020:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
if (!root) return {};
stack<TreeNode*> st;
st.push(root);
unordered_set<TreeNode*> visited;
vector<int> ret;
while (!st.empty()) {
TreeNode* cur = st.top(); st.pop();
if (cur->left && visited.count(cur->left) == 0) {
if (cur->right) st.push(cur->right);
st.push(cur);
st.push(cur->left);
} else if (!cur->left) {
if (cur->right) st.push(cur->right);
ret.push_back(cur->val);
visited.insert(cur);
} else {
ret.push_back(cur->val);
visited.insert(cur);
}
}
return ret;
}
};
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
if (!root) return {};
vector<int> ret = inorderTraversal(root->left);
ret.push_back(root->val);
vector<int> right = inorderTraversal(root->right);
ret.insert(ret.end(), right.begin(), right.end());
return ret;
}
};
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
if (!root) return {};
vector<int> ret;
TreeNode* cur = root;
stack<TreeNode*> st;
while (cur || !st.empty()) {
while (cur) {
st.push(cur);
cur = cur->left;
}
cur = st.top(); st.pop();
ret.push_back(cur->val);
cur = cur->right;
}
return ret;
}
};
Given n, how many structurally unique BST's (binary search trees) that store
values 1 ... n?
Example:
Input: 3
Output: 5
Explanation:
Given n = 3, there are a total of 5 unique BST's:
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
Solution
06/24/2020:
class Solution {
public:
int numTrees(int n) {
long C = 1;
for (int i = 0; i < n; ++i) C = C * 2 * (2 * i + 1) / (i + 2);
return C;
}
};
1
/ \
2 2
/ \ / \
3 4 4 3
Solution
class Solution {
public:
bool isSymmetric(TreeNode* root) {
stack<pair<TreeNode*, TreeNode*>> st;
st.emplace(root, root);
while (!st.empty()) {
pair<TreeNode*, TreeNode*> cur = st.top(); st.pop();
if (cur.first == nullptr && cur.second == nullptr) continue;
if (cur.first != nullptr && cur.second == nullptr) return false;
if (cur.first == nullptr && cur.second != nullptr) return false;
if (cur.first->val != cur.second->val) return false;
st.emplace(cur.first->left, cur.second->right);
st.emplace(cur.first->right, cur.second->left);
}
return true;
}
};
Recursive DFS:
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if (!root) return true;
return isSubtreeSymmetric(root->left, root->right);
}
Given a binary tree, return the level order traversal of its nodes' values. (ie,
from left to right, level by level).
For example:
Given binary tree [3,9,20,null,null,15,7],
3
/ \
920
/ \
15 7
return its level order traversal as:
[
[3],
[9,20],
[15,7]
]
Solution
04/26/2020:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
if (root == nullptr) return {};
vector<vector<int>> ret;
queue<TreeNode*> q;
q.push(root);
while (!q.empty()) {
int n = q.size();
vector<int> level;
for (int i = 0; i < n; ++i) {
TreeNode* cur = q.front(); q.pop();
level.push_back(cur->val);
if (cur->left) q.push(cur->left);
if (cur->right) q.push(cur->right);
}
ret.push_back(level);
}
return ret;
}
};
Given a binary tree, return the zigzag level order traversal of its nodes'
values. (ie, from left to right, then right to left for the next level and
alternate between).
For example:
Given binary tree [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
return its zigzag level order traversal as:
[
[3],
[20,9],
[15,7]
]
Solution
Discussion 04/26/2020:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
vector<vector<int>> ret;
if (root == nullptr) return ret;
queue<pair<TreeNode*, int>> q;
q.emplace(root, 0);
while (!q.empty()) {
int n = q.size();
vector<int> level;
int depth = q.front().second;
for (int i = 0; i < n; ++i) {
pair<TreeNode*, int> cur = q.front(); q.pop();
level.push_back(cur.first->val);
if (cur.first->left) q.emplace(cur.first->left, cur.second + 1);
if (cur.first->right) q.emplace(cur.first->right, cur.second + 1);
}
if (depth % 2 != 0) reverse(level.begin(), level.end());
ret.push_back(level);
}
return ret;
}
};
Better:
class Solution {
public:
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
vector<vector<int>> ret;
if (root == nullptr) return ret;
queue<TreeNode*> q;
q.push(root);
for (int depth = 0; !q.empty(); ++depth) {
int n = q.size();
vector<int> level;
for (int j = 0; j < n; ++j) {
TreeNode* cur = q.front(); q.pop();
level.push_back(cur->val);
if (cur->left) q.push(cur->left);
if (cur->right) q.push(cur->right);
}
if (depth % 2 != 0) reverse(level.begin(), level.end());
ret.push_back(level);
}
return ret;
}
};
Given preorder and inorder traversal of a tree, construct the binary tree.
Note:
You may assume that duplicates do not exist in the tree.
preorder = [3,9,20,15,7]
inorder = [9,3,15,20,7]
Return the following binary tree:
3
/ \
9 20
/ \
15 7
Solution
05/20/2020:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left),
right(right) {}
* };
*/
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder, int p_start
= 0, int p_stop = INT_MAX, int i_start = 0, int i_stop = INT_MAX) {
if (p_stop == INT_MAX) p_stop = i_stop = inorder.size() - 1;
if (i_start > i_stop) return nullptr;
int i = i_start;
for (; i <= i_stop; ++i)
if (inorder[i] == preorder[p_start])
break;
TreeNode* root = new TreeNode(preorder[p_start]);
root->left = buildTree(preorder, inorder, p_start + 1, p_start + 1 + (i -
1) - i_start, i_start, i - 1);
root->right = buildTree(preorder, inorder, p_start + 1 + (i - 1) - i_start
+ 1, p_stop, i + 1, i_stop);
return root;
}
};
Given a singly linked list where elements are sorted in ascending order, convert
it to a height balanced BST.
Example:
Given the sorted linked list: [-10,-3,0,5,9],
0
/ \
-3 9
/ /
-10 5
Solution
05/27/2020:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left),
right(right) {}
* };
*/
class Solution {
public:
TreeNode* sortedListToBST(ListNode* head) {
if (head == nullptr) return nullptr;
if (head->next == nullptr) return new TreeNode(head->val);
ListNode *slow = head, *fast = head, *preSlow = head;
while (fast && fast->next) {
preSlow = slow;
slow = slow->next;
fast = fast->next->next;
}
preSlow->next = nullptr;
TreeNode* root = new TreeNode(slow->val);
root->left = sortedListToBST(head);
root->right = sortedListToBST(slow->next);
return root;
}
};
a binary tree in which the left and right subtrees of every node differ in
height by no more than 1.
Example 1:
3
/ \
9 20
/ \
15 7
Return true.
Example 2:
1
/ \
2 2
/ \
3 3
/ \
4 4
Return false.
Solution
05/27/2020:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left),
right(right) {}
* };
*/
class Solution {
public:
bool isBalanced(TreeNode* root) {
if (root == nullptr) return true;
return abs(depth(root->left) - depth(root->right)) <= 1 && isBalanced(root-
>left) && isBalanced(root->right);
}
1
/ \
2 5
/ \ \
3 4 6
The flattened tree should look like:
1
\
2
\
3
\
4
\
5
\
6
Solution
05/27/2020:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left),
right(right) {}
* };
*/
class Solution {
public:
void flatten(TreeNode* root) {
if (root == nullptr) return;
flatten(root->left);
flatten(root->right);
if (root->left) {
TreeNode* cur = root->left;
while (cur->right) cur = cur->right;
cur->right = root->right;
root->right = root->left;
root->left = nullptr;
}
}
};
class Solution {
public:
void flatten(TreeNode* root) {
if (root == nullptr) return;
TreeNode *list = new TreeNode(0), *l = list;
stack<TreeNode*> st;
st.push(root);
while (!st.empty()) {
TreeNode* cur = st.top(); st.pop();
if (cur->right) st.push(cur->right);
if (cur->left) st.push(cur->left);
l->right = cur;
cur->left = nullptr;
l = l->right;
}
root = list->right;
}
};
In Pascal's triangle, each number is the sum of the two numbers directly above
it.
Example:
Input: 5
Output:
[
[1],
[1,1],
[1,2,1],
[1,3,3,1],
[1,4,6,4,1]
]
Solution
05/27/2020:
class Solution {
public:
vector<vector<int>> generate(int numRows) {
if (numRows < 0) return {};
vector<vector<int>> ret(numRows);
for (int i = 0; i < numRows; ++i) {
ret[i].resize(i + 1, 1);
for (int j = 1; j < i; ++j)
ret[i][j] = ret[i - 1][j] + ret[i - 1][j - 1];
}
return ret;
}
};
Given a non-negative index k where k ≤ 33, return the kth index row of the
Pascal's triangle.
In Pascal's triangle, each number is the sum of the two numbers directly above
it.
Example:
Input: 3
Output: [1,3,3,1]
Follow up:
Could you optimize your algorithm to use only O(k) extra space?
Solution
05/27/2020:
class Solution {
public:
vector<int> getRow(int rowIndex) {
if (rowIndex <= 1) return vector<int>(rowIndex + 1, 1);
vector<int> ret(2, 1);
for (int i = 2; i <= rowIndex; ++i) {
vector<int> nextRow(i + 1, 1);
for (int j = 1; j < i; ++j)
nextRow[j] = ret[j - 1] + ret[j];
ret = nextRow;
}
return ret;
}
};
class Solution {
public:
vector<int> getRow(int rowIndex) {
int n = rowIndex + 1;
vector<vector<int>> ret(n);
for (int i = 0; i < n; ++i) {
ret[i].resize(i + 1, 1);
for (int j = 1; j < i; ++j) {
ret[i][j] = ret[i - 1][j - 1] + ret[i - 1][j];
}
}
return ret.back();
}
};
Say you have an array for which the ith element is the price of a given stock on
day i.
If you were only permitted to complete at most one transaction (i.e., buy one
and sell one share of the stock), design an algorithm to find the maximum
profit.
Note that you cannot sell a stock before you buy one.
Example 1:
Input: [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-
1 = 5.
Not 7-1 = 6, as selling price needs to be larger than buying price.
Example 2:
Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.
Solution
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
if (n <= 1) return 0;
vector<int> diff(n - 1, 0);
for (int i = 0; i < n - 1; ++i) {
diff[i] = prices[i + 1] - prices[i];
}
int max_sum = max(0, diff[0]);
for (int i = 1; i < n - 1; ++i) {
if (diff[i - 1] > 0) diff[i] += diff[i - 1];
max_sum = max(diff[i], max_sum);
}
return max_sum;
}
};
Given a binary tree containing digits from 0-9 only, each root-to-leaf path
could represent a number.
An example is the root-to-leaf path 1->2->3 which represents the number 123.
Example:
Input: [1,2,3]
1
/ \
2 3
Output: 25
Explanation:
The root-to-leaf path 1->2 represents the number 12.
The root-to-leaf path 1->3 represents the number 13.
Therefore, sum = 12 + 13 = 25.
Example 2:
Input: [4,9,0,5,1]
4
/ \
9 0
/ \
5 1
Output: 1026
Explanation:
The root-to-leaf path 4->9->5 represents the number 495.
The root-to-leaf path 4->9->1 represents the number 491.
The root-to-leaf path 4->0 represents the number 40.
Therefore, sum = 495 + 491 + 40 = 1026.
Solution
06/26/2020:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left),
right(right) {}
* };
*/
class Solution {
public:
int sumNumbers(TreeNode* root) {
long long ret = 0, num = 0;
backtrack(num, ret, root);
return ret;
}
Given a 2D board containing 'X' and 'O' (the letter O), capture all regions
surrounded by 'X'.
A region is captured by flipping all 'O's into 'X's in that surrounded region.
Example:
X X X X
X O O X
X X O X
X O X X
After running your function, the board should be:
X X X X
X X X X
X X X X
X O X X
Explanation:
Surrounded regions shouldn’t be on the border, which means that any 'O' on the
border of the board are not flipped to 'X'. Any 'O' that is not on the border
and it is not connected to an 'O' on the border will be flipped to 'X'. Two
cells are connected if they are adjacent cells connected horizontally or
vertically.
Solution
05/08/2020 Discussion:
The idea is borrowed from one of the assignments of the course Algorithms (Part 1):
1. We assume there is a virtual cell (labeled as m * n) that the node on the boundary of the board is
automatically connected to it.
2. We only need to deal with the cells that are 'O': merge these neighboring 'O' cells.
3. Traverse 'O' cells which are stored in visited: if the cell is connected to the virtual cell do nothing;
otherwise, change it to 'X'.
class UnionFind {
private:
vector<int> id;
vector<int> sz;
public:
UnionFind (int n) {
id.resize(n);
iota(id.begin(), id.end(), 0);
sz.resize(n, 1);
}
int find(int x) {
if (x == id[x]) return x;
return id[x] = find(id[x]);
}
class Solution {
public:
void solve(vector<vector<char>>& board) {
if (board.empty() || board[0].empty()) return;
int m = board.size(), n = board[0].size(), bound = m * n;
UnionFind uf(m * n + 1);
int dir[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
unordered_set<int> visited;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (board[i][j] == 'X' || visited.count(i * n + j)) continue;
if (i == 0 || i == m - 1 || j == 0 || j == n - 1) uf.merge(i * n + j,
bound);
for (int d = 0; d < 4; ++d) {
int ni = i + dir[d][0], nj = j + dir[d][1];
if (ni >= 0 && ni < m && nj >= 0 && nj < n && board[ni][nj] == 'O' &&
visited.count(i * n + j) == 0) {
uf.merge(i * n + j, ni * n + nj);
}
}
visited.insert(i * n + j);
}
}
for (auto& p : visited) {
if (!uf.connected(bound, p)) {
int i = p / n, j = p % n;
board[i][j] = 'X';
}
}
}
};
Update: Inspired by the above, we can actually use a set uncaptured to store all the cells that are
connected to the bounds. We can always use BFS which starts from the 'O' cells on the boundary to find
the inner cells which are connected to the boundary.
class Solution {
public:
void solve(vector<vector<char>>& board) {
if (board.empty() || board[0].empty()) return;
int m = board.size(), n = board[0].size();
unordered_set<int> uncaptured;
int dir[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (i == 0 || i == m - 1 || j == 0 || j == n - 1) {
if (board[i][j] == 'X') continue;
queue<int> q;
q.push(i * n + j);
while (!q.empty()) {
int sz = q.size();
for (int s = 0; s < sz; ++s) {
int cur = q.front(); q.pop();
if (uncaptured.count(cur) > 0) continue;
for (int d = 0; d < 4; ++d) {
int ni = cur / n + dir[d][0], nj = cur % n + dir[d][1];
if (ni >= 0 && ni < m && nj >= 0 && nj < n && board[ni][nj] ==
'O') {
q.push(ni * n + nj);
}
}
uncaptured.insert(cur);
}
}
}
}
}
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (board[i][j] == 'O' && uncaptured.count(i * n + j) == 0) {
board[i][j] = 'X';
}
}
}
}
};
Given a non-empty array of integers, every element appears twice except for one.
Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it
without using extra memory?
Example 1:
Input: [2,2,1]
Output: 1
Example 2:
Input: [4,1,2,1,2]
Output: 4
Solution
05/27/2020:
class Solution {
public:
int singleNumber(vector<int>& nums) {
int ret = 0;
for (auto& i : nums) ret ^= i;
return ret;
}
};
Given a non-empty array of integers, every element appears three times except
for one, which appears exactly once. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it
without using extra memory?
Example 1:
Input: [2,2,3,2]
Output: 3
Example 2:
Input: [0,1,0,1,0,1,99]
Output: 99
Solution
05/27/2020:
class Solution {
public:
int singleNumber(vector<int>& nums) {
unordered_map<int, int> cnt;
for (auto& i : nums) ++cnt[i];
for (auto& [k, v] : cnt)
if (v == 1)
return k;
return 0;
}
};
Given a binary tree, return the preorder traversal of its nodes' values.
Example:
Input: [1,null,2,3]
1
\
2
/
3
Output: [1,2,3]
Follow up: Recursive solution is trivial, could you do it iteratively?
Solution
05/20/2020:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
if (root == nullptr) return {};
vector<int> ret;
stack<TreeNode*> st;
st.push(root);
while (!st.empty()) {
TreeNode* cur = st.top(); st.pop();
ret.push_back(cur->val);
if (cur->right) st.push(cur->right);
if (cur->left) st.push(cur->left);
}
return ret;
}
};
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
if (root == nullptr) return {};
vector<int> ret;
ret.push_back(root->val);
vector<int> l = preorderTraversal(root->left);
vector<int> r = preorderTraversal(root->right);
ret.insert(ret.end(), l.begin(), l.end());
ret.insert(ret.end(), r.begin(), r.end());
return ret;
}
};
Example:
Input: [1,null,2,3]
1
\
2
/
3
Output: [3,2,1]
Follow up: Recursive solution is trivial, could you do it iteratively?
Solution
05/20/2020:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> ret;
if (root == nullptr) return ret;
stack<TreeNode*> st;
st.push(root);
while (!st.empty()) {
TreeNode* cur = st.top(); st.pop();
ret.push_back(cur->val);
if (cur->left != nullptr) st.push(cur->left);
if (cur->right != nullptr) st.push(cur->right);
}
reverse(ret.begin(), ret.end());
return ret;
}
};
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
if (!root) return {};
stack<TreeNode*> st;
st.push(root);
vector<int> ret;
unordered_set<TreeNode*> visited;
while (!st.empty()) {
TreeNode* cur = st.top(); st.pop();
if ((!cur->left || visited.count(cur->left)) && (!cur->right ||
visited.count(cur->right))) {
ret.push_back(cur->val);
visited.insert(cur);
} else {
st.push(cur);
if (cur->right) st.push(cur->right);
if (cur->left) st.push(cur->left);
}
}
return ret;
}
};
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
if (!root) return {};
vector<int> ret = postorderTraversal(root->left);
vector<int> right = postorderTraversal(root->right);
ret.insert(ret.end(), right.begin(), right.end());
ret.push_back(root->val);
return ret;
}
};
Design and implement a data structure for Least Recently Used (LRU) cache. It
should support the following operations: get and put.
get(key) - Get the value (will always be positive) of the key if the key exists
in the cache, otherwise return -1.
put(key, value) - Set or insert the value if the key is not already present.
When the cache reached its capacity, it should invalidate the least recently
used item before inserting a new item.
Follow up:
Could you do both operations in O(1) time complexity?
Example:
cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // returns 1
cache.put(3, 3); // evicts key 2
cache.get(2); // returns -1 (not found)
cache.put(4, 4); // evicts key 1
cache.get(1); // returns -1 (not found)
cache.get(3); // returns 3
cache.get(4); // returns 4
Solution
Discussion:
class LRUCache {
private:
unordered_map<int, int> cache;
unordered_map<int, int> priority;
priority_queue<pair<int, int>, vector<pair<int, int>>, less<pair<int, int>>>
pq; // max-heap
int capacity, rank;
public:
LRUCache(int capacity) {
this->capacity = capacity;
rank = INT_MAX;
cache.clear();
priority.clear();
}
Example 1:
Input: [3,4,5,1,2]
Output: 1
Example 2:
Input: [4,5,6,7,0,1,2]
Output: 0
Solution
04/28/2020:
class Solution {
public:
int findMin(vector<int>& nums) {
if (nums.empty()) return -1;
int n = nums.size();
int lo = 0, hi = n - 1;
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (nums[mid] > nums[hi]) {
lo = mid + 1;
} else {
hi = mid;
}
}
return nums[hi];
}
};
Given an input array nums, where nums[i] ≠ nums[i+1], find a peak element and
return its index.
The array may contain multiple peaks, in that case return the index to any one
of the peaks is fine.
You may imagine that nums[-1] = nums[n] = -∞.
Example 1:
Solution
04/28/2020:
class Solution {
public:
int findPeakElement(vector<int>& nums) {
if (nums.empty()) return -1;
int lo = 0, hi = nums.size() - 1;
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (mid - 1 >= lo && nums[mid] < nums[mid - 1]) {
hi = mid - 1;
} else if (mid + 1 <= hi && nums[mid] < nums[mid + 1]) {
lo = mid + 1;
} else {
return mid;
}
}
return lo;
}
};
Given a sorted integer array nums, where the range of elements are in the
inclusive range [lower, upper], return its missing ranges.
Example:
Solution
05/24/2020:
class Solution {
public:
vector<string> findMissingRanges(vector<int>& nums, int lower, int upper) {
if (nums.empty()) {
string s = lower == upper ? to_string(lower) : to_string(lower) + "->" +
to_string(upper);
return {s};
}
long long cur = nums.back(); nums.pop_back();
vector<string> ranges;
string s = cur + 1 < upper ? to_string(cur + 1) + "->" + to_string(upper) :
to_string(cur + 1);
if (cur - 1 >= lower) ranges = findMissingRanges(nums, lower, cur - 1);
if (cur + 1 <= upper) ranges.push_back(s);
return ranges;
}
};
class Solution {
public:
vector<string> findMissingRanges(vector<int>& nums, int lower, int upper) {
if (lower > upper) return {};
if (nums.empty()) {
if (lower == upper)
return { to_string(lower) };
else
return { to_string(lower) + "->" + to_string(upper) };
}
long long cur = nums.back(); nums.pop_back();
vector<string> ranges;
if (cur - 1 >= INT_MIN) {
ranges = findMissingRanges(nums, lower, cur - 1);
}
if (cur + 1 < upper) {
ranges.push_back(to_string(cur + 1) + "->" + to_string(upper));
} else if (cur + 1 == upper) {
ranges.push_back(to_string(cur + 1));
}
return ranges;
}
};
Given an array of size n, find the majority element. The majority element is the
element that appears more than ⌊ n/2 ⌋ times.
You may assume that the array is non-empty and the majority element always exist
in the array.
Example 1:
Input: [3,2,3]
Output: 3
Example 2:
Input: [2,2,1,1,1,2,2]
Output: 2
Solution
05/06/2020:
class Solution {
public:
int majorityElement(vector<int>& nums) {
int n = nums.size();
if (n == 0) return -1;
unordered_map<int, int> s;
int major = nums[0], cnt = 1;
for (auto& i : nums) {
if (++s[i] > cnt) {
cnt = s[i];
major = i;
}
}
return cnt > n / 2 ? major : -1;
}
};
Implement an iterator over a binary search tree (BST). Your iterator will be
initialized with the root node of a BST.
Calling next() will return the next smallest number in the BST.
Example:
Note:
next() and hasNext() should run in average O(1) time and uses O(h) memory, where
h is the height of the tree.
You may assume that next() call will always be valid, that is, there will be at
least a next smallest number in the BST when next() is called.
Solution
05/24/2020:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left),
right(right) {}
* };
*/
class BSTIterator {
private:
stack<TreeNode*> st;
TreeNode* cur;
public:
BSTIterator(TreeNode* root) {
cur = root;
}
/**
* Your BSTIterator object will be instantiated and called as such:
* BSTIterator* obj = new BSTIterator(root);
* int param_1 = obj->next();
* bool param_2 = obj->hasNext();
*/
class BSTIterator {
private:
vector<TreeNode*> inorder;
vector<TreeNode*> inorderTraversal(TreeNode* root) {
if (root == nullptr) return {};
vector<TreeNode*> leftTraversal = inorderTraversal(root->left);
vector<TreeNode*> rightTraversal = inorderTraversal(root->right);
leftTraversal.push_back(root);
leftTraversal.insert(leftTraversal.end(), rightTraversal.begin(),
rightTraversal.end());
return leftTraversal;
}
public:
BSTIterator(TreeNode* root) {
inorder = inorderTraversal(root);
reverse(inorder.begin(), inorder.end());
}
The demons had captured the princess (P) and imprisoned her in the bottom-right
corner of a dungeon. The dungeon consists of M x N rooms laid out in a 2D grid.
Our valiant knight (K) was initially positioned in the top-left room and must
fight his way through the dungeon to rescue the princess.
Some of the rooms are guarded by demons, so the knight loses health (negative
integers) upon entering these rooms; other rooms are either empty (0's) or
contain magic orbs that increase the knight's health (positive integers).
In order to reach the princess as quickly as possible, the knight decides to
move only rightward or downward in each step.
For example, given the dungeon below, the initial health of the knight must be
at least 7 if he follows the optimal path RIGHT-> RIGHT -> DOWN -> DOWN.
-2 (K) -3 3
-5 -10 1
10 30 -5 (P)
Note:
Solution
06/21/2020:
class Solution {
public:
const int inf = numeric_limits<int>::max();
vector<vector<int>> dp;
int rows, cols;
You are a professional robber planning to rob houses along a street. Each house
has a certain amount of money stashed, the only constraint stopping you from
robbing each of them is that adjacent houses have security system connected and
it will automatically contact the police if two adjacent houses were broken into
on the same night.
Example 1:
Input: [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
Total amount you can rob = 1 + 3 = 4.
Example 2:
Input: [2,7,9,3,1]
Output: 12
Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5
(money = 1).
Total amount you can rob = 2 + 9 + 1 = 12.
Solution
Given a 2d grid map of '1's (land) and '0's (water), count the number of
islands. An island is surrounded by water and is formed by connecting adjacent
lands horizontally or vertically. You may assume all four edges of the grid are
all surrounded by water.
Example 1:
Input:
11110
11010
11000
00000
Output: 1
Example 2:
Input:
11000
11000
00100
00011
Output: 3
Solution
05/08/2020 (Union-Find):
class UnionFind {
private:
vector<int> id;
vector<int> sz;
public:
UnionFind(int n) {
id.resize(n);
iota(id.begin(), id.end(), 0);
sz.resize(n, 1);
}
int find(int x) {
if (x == id[x]) return x;
return id[x] = find(id[x]);
}
class Solution {
public:
int numIslands(vector<vector<char>>& grid) {
if (grid.empty() || grid[0].empty()) return 0;
int m = grid.size(), n = grid[0].size();
UnionFind uf(m * n);
int dir[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (grid[i][j] == '0') continue;
for (int d = 0; d < 4; ++d) {
int ni = i + dir[d][0], nj = j + dir[d][1];
if (ni >= 0 && ni < m && nj >= 0 && nj < n && grid[ni][nj] == '1') {
uf.merge(i * n + j, ni * n + nj);
}
}
}
}
unordered_set<int> components;
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
if (grid[i][j] == '1')
components.insert(uf.find(i * n + j));
return components.size();
}
};
class Solution {
public:
int numIslands(vector<vector<char>>& grid) {
int m = grid.size();
if (m == 0) return 0;
int n = grid[0].size(), ret = 0;
stack<pair<int, int>> st;
int d[4][2] = { {0, -1}, {0, 1}, {-1, 0}, {1, 0} };
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (grid[i][j] == '1') {
++ret;
st.emplace(i, j);
while (!st.empty()) {
pair<int, int> cur = st.top(); st.pop();
grid[cur.first][cur.second] = '0';
for (int k = 0; k < 4; ++k) {
int ni = cur.first + d[k][0], nj = cur.second + d[k][1];
if (ni > -1 && ni < m && nj > -1 && nj < n && grid[ni][nj] == '1')
st.emplace(ni, nj);
}
}
}
}
}
return ret;
}
};
Iterative DFS:
class Solution {
public:
int numIslands(vector<vector<char>>& grid) {
int m = grid.size();
if (m == 0) return 0;
int n = grid[0].size(), ret = 0;
stack<pair<int, int>> st;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (grid[i][j] == '1') {
++ret;
st.emplace(i, j);
while (!st.empty()) {
pair<int, int> cur = st.top(); st.pop();
int ni = cur.first, nj = cur.second;
grid[ni][nj] = '0';
if (ni + 1 < m && grid[ni + 1][nj] == '1') st.emplace(ni + 1, nj);
if (ni - 1 >= 0 && grid[ni - 1][nj] == '1') st.emplace(ni - 1, nj);
if (nj + 1 < n && grid[ni][nj + 1] == '1') st.emplace(ni, nj + 1);
if (nj - 1 >= 0 && grid[ni][nj - 1] == '1') st.emplace(ni, nj - 1);
}
}
}
}
return ret;
}
};
Recursive DFS:
class Solution {
public:
int numIslands(vector<vector<char>>& grid) {
int m = grid.size();
if (m == 0) return 0;
int n = grid[0].size();
int ret = 0;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (grid[i][j] == '1') {
++ret;
dfs(grid, i, j, m, n);
}
}
}
return ret;
}
Example 1:
Solution
05/20/2020:
class Solution {
public:
bool isIsomorphic(string s, string t) {
unordered_map<char, unordered_set<char>> mpST, mpTS;
for (int i = 0; i < (int)s.size(); ++i) {
mpST[s[i]].insert(t[i]);
mpTS[t[i]].insert(s[i]);
}
for (auto& m : mpST)
if (m.second.size() > 1)
return false;
for (auto& m : mpTS)
if (m.second.size() > 1)
return false;
return true;
}
};
There are a total of numCourses courses you have to take, labeled from 0 to
numCourses-1.
Some courses may have prerequisites, for example to take course 0 you have to
first take course 1, which is expressed as a pair: [0,1]
Example 1:
Constraints:
Solution
05/29/2020:
class Solution {
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
vector<vector<int>> adj(numCourses);
for (auto& p : prerequisites) adj[p[1]].push_back(p[0]);
vector<bool> path(numCourses);
for (int i = 0; i < numCourses; ++i)
if (isCyclic(i, adj, path))
return false;
return true;
}
Example:
trie.insert("apple");
trie.search("apple"); // returns true
trie.search("app"); // returns false
trie.startsWith("app"); // returns true
trie.insert("app");
trie.search("app"); // returns true
Note:
You may assume that all inputs are consist of lowercase letters a-z.
All inputs are guaranteed to be non-empty strings.
Solution
05/13/2020:
class Trie {
public:
/** Initialize your data structure here. */
Trie() {
root = new Node();
}
/** Returns if there is any word in the trie that starts with the given
prefix. */
bool startsWith(string prefix) {
Node* cur = find(prefix);
return cur != nullptr;
}
private:
struct Node {
bool isWord;
unordered_map<char, Node*> mp;
Node() : isWord(false) {}
};
Node* root;
Node* find(const string& word) {
Node* cur = root;
for (auto& c : word) {
cur = cur->mp[c];
if (!cur) break;
}
return cur;
}
};
/**
* Your Trie object will be instantiated and called as such:
* Trie* obj = new Trie();
* obj->insert(word);
* bool param_2 = obj->search(word);
* bool param_3 = obj->startsWith(prefix);
*/
class Trie {
private:
struct Node {
bool isWord;
vector<Node*> children;
Node() { isWord = false; children.resize(26, nullptr); }
~Node() { for(auto& c : children) delete c; }
};
Node* root;
public:
/** Initialize your data structure here. */
Trie() {
root = new Node();
}
/** Returns if there is any word in the trie that starts with the given
prefix. */
bool startsWith(string prefix) {
Node* cur = find(prefix);
return cur;
}
};
/**
* Your Trie object will be instantiated and called as such:
* Trie* obj = new Trie();
* obj->insert(word);
* bool param_2 = obj->search(word);
* bool param_3 = obj->startsWith(prefix);
*/
struct Node {
char character;
bool isWord;
vector<Node*> children;
Node(char c, bool i) : character(c), isWord(i) {}
~Node() {
for (auto& c : children) delete c;
}
};
class Trie {
private:
Node *root;
public:
/** Initialize your data structure here. */
Trie() {
root = new Node('r', false);
}
/** Inserts a word into the trie. */
void insert(string word) {
int n = word.size();
Node* cur = root;
for (int i = 0; i < n; ++i) {
bool foundCharacter = false;
for (auto& c : cur->children) {
if (word[i] == c->character) {
cur = c;
foundCharacter = true;
break;
}
}
if (!foundCharacter) {
Node* c = new Node(word[i], false);
cur->children.push_back(c);
cur = c;
}
}
cur->isWord = true;
}
/** Returns if there is any word in the trie that starts with the given
prefix. */
bool startsWith(string prefix) {
Node* cur = root;
int n = prefix.size();
for (int i = 0; i < n; ++i) {
bool foundCharacter = false;
for (auto& c : cur->children) {
if (c->character == prefix[i]) {
foundCharacter = true;
cur = c;
break;
}
}
if (!foundCharacter) return false;
}
return true;
}
};
/**
* Your Trie object will be instantiated and called as such:
* Trie* obj = new Trie();
* obj->insert(word);
* bool param_2 = obj->search(word);
* bool param_3 = obj->startsWith(prefix);
*/
Given an array of integers and an integer k, find out whether there are two
distinct indices i and j in the array such that nums[i] = nums[j] and the
absolute difference between i and j is at most k.
Example 1:
Solution
05/20/2020:
class Solution {
public:
bool containsNearbyDuplicate(vector<int>& nums, int k) {
unordered_map<int, int> mp;
int n = nums.size();
for (int i = 0; i < n; ++i) {
if (mp.count(nums[i]) > 0) {
if (i - mp[nums[i]] <= k) {
return true;
}
}
mp[nums[i]] = i;
}
return false;
}
};
class Solution {
public:
bool containsNearbyDuplicate(vector<int>& nums, int k) {
unordered_set<int> visited;
for (int i = 0; i < (int)nums.size(); ++i) {
if (visited.count(nums[i]) > 0) return true;
visited.insert(nums[i]);
if (i - k >= 0) visited.erase(nums[i - k]);
}
return false;
}
};
Example:
Input:
1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
Output: 4
Solution
class Solution {
public:
int maximalSquare(vector<vector<char>>& matrix) {
int m = matrix.size();
if (m == 0) return 0;
int n = matrix[0].size();
int ret = 0;
vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
dp[i + 1][j + 1] = matrix[i][j] - '0';
if (dp[i + 1][j + 1] > 0) {
dp[i + 1][j + 1] = min(dp[i][j], min(dp[i][j + 1], dp[i + 1][j])) + 1;
ret = max(ret, dp[i + 1][j + 1]);
}
}
}
return ret * ret;
}
};
class Solution {
public:
int maximalSquare(vector<vector<char>>& matrix) {
if (matrix.size() == 0 || matrix[0].size() == 0) return 0;
int m = matrix.size(), n = matrix[0].size();
int ret = 0;
vector<int> dp(n + 1, 0);
for (int i = 0; i < m; ++i) {
vector<int> tmp(dp);
for (int j = 0; j < n; ++j) {
dp[j + 1] = matrix[i][j] - '0';
if (dp[j + 1] > 0) {
dp[j + 1] = min(tmp[j], min(tmp[j + 1], dp[j])) + 1;
ret = max(ret, dp[j + 1]);
}
}
}
return ret * ret;
}
};
Note:
Example:
Input:
1
/ \
2 3
/ \ /
4 5 6
Output: 6
Solution
06/23/2020:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int countNodes(TreeNode* root) {
if (!root) return 0;
queue<TreeNode*> q;
q.push(root);
int ret = 0;
while (!q.empty()) {
int sz = q.size();
ret += sz;
for (int i = 0; i < sz; ++i) {
TreeNode* cur = q.front(); q.pop();
if (cur->right) q.push(cur->right);
if (cur->left) q.push(cur->left);
}
}
return ret;
}
};
Example:
Input:
4
/ \
2 7
/ \ / \
1 3 6 9
Output:
4
/ \
7 2
/ \ / \
9 6 3 1
Trivia:
This problem was inspired by this original tweet by Max Howell:
Google: 90% of our engineers use the software you wrote (Homebrew), but you
can’t invert a binary tree on a whiteboard so f*** off.
Solution
06/01/2020:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left),
right(right) {}
* };
*/
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if (root == nullptr) return nullptr;
swap(root->left, root->right);
invertTree(root->left);
invertTree(root->right);
return root;
}
};
Given a binary search tree, write a function kthSmallest to find the kth
smallest element in it.
Example 1:
Constraints:
Solution
05/20/2020:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left),
right(right) {}
* };
*/
class Solution {
public:
int kthSmallest(TreeNode* root, int k) {
stack<TreeNode*> st;
TreeNode* cur = root;
while (cur || !st.empty()) {
while (cur) {
st.push(cur);
cur = cur->left;
}
cur = st.top(); st.pop();
if (--k == 0) return cur->val;
cur = cur->right;
}
return 0;
}
};
class Solution {
public:
int kthSmallest(TreeNode* root, int k) {
stack<TreeNode*> st;
st.push(root);
unordered_set<TreeNode*> visited;
while (!st.empty()) {
TreeNode* cur = st.top(); st.pop();
if (cur->left && visited.count(cur->left) == 0) {
if (cur->right) st.push(cur->right);
st.push(cur);
st.push(cur->left);
} else {
if (!cur->left && cur->right) st.push(cur->right);
visited.insert(cur);
if (--k == 0) return cur->val;
}
}
return 0;
}
};
class Solution {
public:
int n, ans;
int kthSmallest(TreeNode* root, int k) {
n = k;
inorder(root);
return ans;
}
class Solution {
public:
int kthSmallest(TreeNode* root, int k) {
vector<int> list = BST2vector(root);
return list[k - 1];
}
Example 1:
Input: 1
Output: true
Explanation: 20 = 1
Example 2:
Input: 16
Output: true
Explanation: 24 = 16
Example 3:
Input: 218
Output: false
Solution
06/07/2020:
class Solution {
public:
bool isPowerOfTwo(int n) {
return n > 0 && __builtin_popcount(n) == 1;
}
};
Write a function to delete a node (except the tail) in a singly linked list,
given only access to that node.
Example 1:
Note:
Solution
05/10/2020:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
void deleteNode(ListNode* node) {
if (node == nullptr) return;
if (node->next == nullptr) {
node = node->next;
} else {
node->val = node->next->val;
node->next = node->next->next;
node = node->next;
}
}
};
06/02/2020:
class Solution {
public:
void deleteNode(ListNode* node) {
*node = *(node->next);
}
};
class Solution {
public:
void deleteNode(ListNode* node) {
node->val = node->next->val;
node->next = node->next->next;
}
};
242. Valid Anagram
Description
Example 1:
Follow up:
What if the inputs contain unicode characters? How would you adapt your solution
to such case?
Solution
05/17/2020:
class Solution {
public:
bool isAnagram(string s, string t) {
vector<int> cntS(26, 0), cntT(26, 0);
for (int i = 0; i < (int)s.size(); ++i) ++cntS[s[i] - 'a'];
for (int i = 0; i < (int)t.size(); ++i) ++cntT[t[i] - 'a'];
for (int i = 0; i < 26; ++i) {
if (cntS[i] != cntT[i]) {
return false;
}
}
return true;
}
};
class Solution {
public:
bool isAnagram(string s, string t) {
sort(s.begin(), s.end());
sort(t.begin(), t.end());
return s == t;
}
};
A strobogrammatic number is a number that looks the same when rotated 180
degrees (looked at upside down).
Example 1:
Input: "69"
Output: true
Example 2:
Input: "88"
Output: true
Example 3:
Input: "962"
Output: false
Solution
05/18/2020:
class Solution {
public:
bool isStrobogrammatic(string num) {
unordered_map<char, char> mp{ {'0', '0'}, {'1', '1'}, {'6', '9'}, {'8',
'8'}, {'9', '6'} };
string stro = "";
for (auto& n : num) {
if (mp.count(n) == 0) return false;
stro = mp[n] + stro;
}
return stro == num;
}
};
Given a string, we can "shift" each of its letter to its successive letter, for
example: "abc" -> "bcd". We can keep "shifting" which forms the sequence:
Example:
Solution
05/25/2020:
class Solution {
public:
vector<vector<string>> groupStrings(vector<string>& strings) {
vector<vector<string>> ret;
unordered_map<string, vector<string>> shiftedStrings;
for (auto& s : strings) shiftedStrings[base(s)].push_back(s);
for (auto& [key, val] : shiftedStrings) ret.push_back(val);
return ret;
}
class Solution {
public:
vector<vector<string>> groupStrings(vector<string>& strings) {
unordered_map<int, vector<string>> shiftedStrings;
for (auto& s : strings) shiftedStrings[hash(s)].push_back(s);
vector<vector<string>> ret;
for (auto& m : shiftedStrings) ret.push_back(m.second);
return ret;
}
A Uni-value subtree means all nodes of the subtree have the same value.
Example :
Output: 4
Solution
05/25/2020:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left),
right(right) {}
* };
*/
class Solution {
public:
int countUnivalSubtrees(TreeNode* root) {
pair<int, bool> ret = dfs(root);
return ret.first;
}
class Solution {
public:
int countUnivalSubtrees(TreeNode* root) {
int cnt = 0;
dfs(root, cnt);
return cnt;
}
Example:
iterator.next(); // return 1
iterator.next(); // return 2
iterator.next(); // return 3
iterator.hasNext(); // return true
iterator.hasNext(); // return true
iterator.next(); // return 4
iterator.hasNext(); // return false
Notes:
Follow up:
Solution
05/25/2020:
class Vector2D {
private:
vector<vector<int>> v;
int i, j;
public:
Vector2D(vector<vector<int>>& v) {
this->v = v;
i = j = 0;
while (i < (int)v.size() && v[i].empty()) ++i;
}
int next() {
int ret = v[i][j];
if (i < (int)v.size() && ++j >= (int)v[i].size()) {
j = 0, ++i;
while (i < (int)v.size() && v[i].empty()) ++i;
}
return ret;
}
bool hasNext() {
return i < (int)v.size() && j < (int)v[i].size();
}
};
/**
* Your Vector2D object will be instantiated and called as such:
* Vector2D* obj = new Vector2D(v);
* int param_1 = obj->next();
* bool param_2 = obj->hasNext();
*/
class Vector2D {
private:
vector<int> flattenedVector;
public:
Vector2D(vector<vector<int>>& v) {
flattenedVector.clear();
for (auto& nums : v) {
for (auto& i : nums) {
flattenedVector.push_back(i);
}
}
reverse(flattenedVector.begin(), flattenedVector.end());
}
int next() {
int ret = flattenedVector.back();
flattenedVector.pop_back();
return ret;
}
bool hasNext() {
return !flattenedVector.empty();
}
};
Example 1:
Input: [[0,30],[5,10],[15,20]]
Output: false
Example 2:
Input: [[7,10],[2,4]]
Output: true
NOTE: input types have been changed on April 15, 2019. Please reset to default
code definition to get new method signature.
Solution
05/26/2020:
class Solution {
public:
bool canAttendMeetings(vector<vector<int>>& intervals) {
if (intervals.empty()) return true;
sort(intervals.begin(), intervals.end());
for (int i = 1; i < (int)intervals.size(); ++i)
if (intervals[i - 1][1] > intervals[i][0])
return false;
return true;
}
};
Example 1:
Input: [[7,10],[2,4]]
Output: 1
NOTE: input types have been changed on April 15, 2019. Please reset to default
code definition to get new method signature.
Solution
05/27/2020:
class Solution {
public:
int minMeetingRooms(vector<vector<int>>& intervals) {
vector<int> startTime, endTime;
for (auto& i : intervals) {
startTime.push_back(i[0]);
endTime.push_back(i[1]);
}
sort(startTime.begin(), startTime.end());
sort(endTime.begin(), endTime.end());
int ret = 0, cnt = 0;
auto startIt = startTime.begin();
auto endIt = endTime.begin();
for (; startIt != startTime.end() || endIt != endTime.end(); ) {
if (endIt == endTime.end() || (startIt != startTime.end() && *startIt <
*endIt)) {
ret = max(ret, ++cnt);
++startIt;
} else {
--cnt;
++endIt;
}
}
return ret;
}
};
257. Binary Tree Paths
Description
Example:
Input:
1
/ \
2 3
\
5
Solution
05/26/2020:
class Solution {
public:
vector<string> binaryTreePaths(TreeNode* root) {
string path;
vector<string> ret;
backtrack(root, path, ret);
return ret;
}
class Solution {
public:
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> ret;
string p = "";
dfs(root, p, ret);
return ret;
}
Note:
All costs are positive integers.
Example:
Input: [[1,5,3],[2,9,4]]
Output: 5
Explanation: Paint house 0 into color 0, paint house 1 into color 2. Minimum
cost: 1 + 4 = 5;
Or paint house 0 into color 2, paint house 1 into color 0. Minimum
cost: 3 + 2 = 5.
Follow up:
Could you solve it in O(nk) runtime?
Solution
05/28/2020:
class Solution {
public:
int minCostII(vector<vector<int>>& costs) {
if (costs.empty() || costs[0].empty()) return 0;
int m = costs.size(), n = costs[0].size();
for (int i = 1; i < m; ++i) {
for (int j = 0; j < n; ++j) {
int prevMinCost = INT_MAX;
for (int k = 0; k < n; ++k)
if (k != j)
prevMinCost = min(prevMinCost, costs[i - 1][k]);
costs[i][j] += prevMinCost;
}
}
return *min_element(costs.back().begin(), costs.back().end());
}
};
267. Palindrome Permutation II
Description
Example 1:
Input: "aabb"
Output: ["abba", "baab"]
Example 2:
Input: "abc"
Output: []
Solution
05/28/2020:
class Solution {
public:
unordered_map<char, int> cnt;
vector<string> generatePalindromes(string s) {
if (!isPalindromic(s)) return {};
unordered_set<string> permutation;
string prefix, oddChar;
for (auto& [k, v] : cnt) {
prefix += string(v / 2, k);
if (v % 2 == 1) oddChar = string(1, k);
}
sort(prefix.begin(), prefix.end());
do {
string suffix(prefix);
reverse(suffix.begin(), suffix.end());
permutation.insert(prefix + oddChar + suffix);
} while (next_permutation(prefix.begin(), prefix.end()));
return vector<string>(permutation.begin(), permutation.end());
}
Example 1:
Input: [3,0,1]
Output: 2
Example 2:
Input: [9,6,4,2,3,5,7,0,1]
Output: 8
Note:
Your algorithm should run in linear runtime complexity. Could you implement it
using only constant extra space complexity?
Solution
05/27/2020:
class Solution {
public:
int missingNumber(vector<int>& nums) {
sort(nums.begin(), nums.end());
int n = nums.size();
for (int i = 0; i < n; ++i) {
if (nums[i] != i) {
return i;
}
}
return n;
}
};
class Solution {
public:
int missingNumber(vector<int>& nums) {
unordered_set<int> seen;
for (auto& i : nums) seen.insert(i);
for (int i = 0; i <= (int)nums.size(); ++i)
if (seen.count(i) == 0)
return i;
return -1;
}
};
class Solution {
public:
int missingNumber(vector<int>& nums) {
int n = nums.size();
bitset<200000000> s;
for (auto& i : nums) s[i] = 1;
for (int i = 0; i <= n; ++i)
if (s[i] == 0)
return i;
return -1;
}
};
Given a non-empty binary search tree and a target value, find the value in the
BST that is closest to the target.
Note:
4
/ \
2 5
/ \
1 3
Output: 4
Solution
04/28/2020:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int closestValue(TreeNode* root, double target) {
if (root == nullptr) return INT_MAX;
int n = root->val;
int n_left = closestValue(root->left, target);
int n_right = closestValue(root->right, target);
n = !root->left || fabs(n - target) < fabs(n_left - target) ? n : n_left;
n = !root->right || fabs(n - target) < fabs(n_right - target) ? n : n_right;
return n;
}
};
class Solution {
public:
int closestValue(TreeNode* root, double target) {
int n = root->val;
double d = fabs(root->val - target);
if (root->left && target < root->val) {
int n_left = closestValue(root->left, target);
double d_left = fabs(n_left - target);
if (d_left < d) {
n = n_left;
d = d_left;
}
}
if (root->right && target > root->val) {
int n_right = closestValue(root->right, target);
double d_right = fabs(n_right - target);
if (d_right < d) {
n = n_right;
d = d_right;
}
}
return n;
}
};
class Solution {
public:
int closestValue(TreeNode* root, double target) {
int n = root->val;
double d = fabs(root->val - target);
if (root->left && target < root->val) {
int n_left = closestValue(root->left, target);
double d_left = fabs(n_left - target);
if (d_left < d) {
n = n_left;
d = d_left;
}
}
if (root->right && target > root->val) {
int n_right = closestValue(root->right, target);
double d_right = fabs(n_right - target);
if (d_right < d) {
n = n_right;
d = d_right;
}
}
return n;
}
};
274. H-Index
Description
Given an array of citations (each citation is a non-negative integer) of a
researcher, write a function to compute the researcher's h-index.
Example:
Solution
05/30/2020:
class Solution {
public:
int hIndex(vector<int>& citations) {
sort(citations.rbegin(), citations.rend());
int lo = 0, hi = citations.size() - 1;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
if (citations[mid] >= mid + 1) {
lo = mid + 1;
} else {
hi = mid - 1;
}
}
return lo;
}
};
You have to paint all the posts such that no more than two adjacent fence posts
have the same color.
Return the total number of ways you can paint the fence.
Note:
n and k are non-negative integers.
Example:
Input: n = 3, k = 2
Output: 6
Explanation: Take c1 as color 1, c2 as color 2. All possible ways are:
Solution
class Solution {
public:
int numWays(int n, int k) {
if (n == 0 || k == 0) return 0;
vector<vector<int>> dp(n, vector<int>(2, 0));
dp[0][0] = k;
for (int i = 1; i < n; ++i) {
dp[i][0] = (dp[i - 1][0] + dp[i - 1][1]) * (k - 1);
dp[i][1] = dp[i - 1][0];
}
return dp.back()[0] + dp.back()[1];
}
};
class Solution {
public:
int numWays(int n, int k) {
if (n == 0 || k == 0) return 0;
vector<int> dp(2, 0);
dp[0] = k;
for (int i = 1; i < n; ++i) {
int tmp = dp[0];
dp[0] = (dp[0] + dp[1]) * (k - 1);
dp[1] = tmp;
}
return dp[0] + dp[1];
}
};
You are a product manager and currently leading a team to develop a new product.
Unfortunately, the latest version of your product fails the quality check. Since
each version is developed based on the previous version, all the versions after
a bad version are also bad.
Suppose you have n versions [1, 2, ..., n] and you want to find out the first
bad one, which causes all the following ones to be bad.
You are given an API bool isBadVersion(version) which will return whether
version is bad. Implement a function to find the first bad version. You should
minimize the number of calls to the API.
Example:
Solution
04/23/2020:
class Solution {
public:
int firstBadVersion(int n) {
int lo = 1, hi = n;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
if (isBadVersion(mid) == true) {
hi = mid - 1;
} else {
lo = mid + 1;
}
}
return lo;
}
};
Given a binary search tree and a node in it, find the in-order successor of that
node in the BST.
The successor of a node p is the node with the smallest key greater than p.val.
Example 1:
Note:
If the given node has no in-order successor in the tree, return null.
It's guaranteed that the values of the tree are unique.
Solution
05/24/2020:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
stack<TreeNode*> st;
TreeNode* cur = root;
while (cur || !st.empty()) {
while (cur) {
st.push(cur);
cur = cur->left;
}
cur = st.top(); st.pop();
if (cur->val > p->val) return cur;
cur = cur->right;
}
return nullptr;
}
};
class Solution {
public:
TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
vector<TreeNode*> inorder = inorderTraversal(root);
for (auto& i : inorder) {
if (i->val > p->val) {
return i;
}
}
return nullptr;
}
vector<TreeNode*> inorderTraversal(TreeNode* root) {
if (root == nullptr) return {};
vector<TreeNode*> leftTraversal = inorderTraversal(root->left);
vector<TreeNode*> rightTraversal = inorderTraversal(root->right);
leftTraversal.push_back(root);
leftTraversal.insert(leftTraversal.end(), rightTraversal.begin(),
rightTraversal.end());
return leftTraversal;
}
};
You are given a m x n 2D grid initialized with these three possible values.
-1 - A wall or an obstacle.
0 - A gate.
INF - Infinity means an empty room. We use the value 231 - 1 = 2147483647 to
represent INF as you may assume that the distance to a gate is less than
2147483647.
Fill each empty room with the distance to its nearest gate. If it is impossible
to reach a gate, it should be filled with INF.
Example:
INF -1 0 INF
INF INF INF -1
INF -1 INF -1
0 -1 INF INF
After running your function, the 2D grid should be:
3 -1 0 1
2 2 1 -1
1 -1 2 -1
0 -1 3 4
Solution
05/08/2020 (DFS):
class Solution {
public:
void wallsAndGates(vector<vector<int>>& rooms) {
if (rooms.empty() || rooms[0].empty()) return;
for (int i = 0; i < rooms.size(); ++i) {
for (int j = 0; j < rooms[0].size(); ++j) {
if (rooms[i][j] == 0) {
dfs(rooms, i, j, rooms[i][j]);
}
}
}
}
05/08/2020 (BFS):
class Solution {
public:
void wallsAndGates(vector<vector<int>>& rooms) {
if (rooms.empty() || rooms[0].empty()) return;
Example 1:
Input: [1,3,4,2,2]
Output: 2
Example 2:
Input: [3,1,3,4,2]
Output: 3
Note:
You must not modify the array (assume the array is read only).
You must use only constant, O(1) extra space.
Your runtime complexity should be less than O(n2).
There is only one duplicate number in the array, but it could be repeated more
than once.
Solution
04/28/2020:
class Solution {
public:
int findDuplicate(vector<int>& nums) {
sort(nums.begin(), nums.end());
for (int i = 0; i < nums.size(); ++i) {
auto p = equal_range(nums.begin() + i, nums.end(), nums[i]);
if (p.second - p.first >= 2) return *p.first;
}
return -1;
}
};
class Solution {
public:
int findDuplicate(vector<int>& nums) {
unordered_map<int, int> mp;
for (auto& n : nums) {
if (++mp[n] > 1) {
return n;
}
}
return -1;
}
};
Given a pattern and a string str, find if str follows the same pattern.
Here follow means a full match, such that there is a bijection between a letter
in pattern and a non-empty word in str.
Example 1:
Solution
05/20/2020:
class Solution {
public:
bool wordPattern(string pattern, string str) {
istringstream iss(str);
string s;
vector<string> words;
while (iss >> s) words.push_back(s);
if (words.size() != pattern.size()) return false;
unordered_map<char, unordered_set<string>> mp1;
unordered_map<string, unordered_set<char>> mp2;
for (int i = 0; i < (int)pattern.size(); ++i) {
mp1[pattern[i]].insert(words[i]);
mp2[words[i]].insert(pattern[i]);
}
for (auto& m : mp1) if (m.second.size() > 1) return false;
for (auto& m : mp2) if (m.second.size() > 1) return false;
return true;
}
};
You are playing the following Bulls and Cows game with your friend: You write
down a number and ask your friend to guess what the number is. Each time your
friend makes a guess, you provide a hint that indicates how many digits in said
guess match your secret number exactly in both digit and position (called
"bulls") and how many digits match the secret number but locate in the wrong
position (called "cows"). Your friend will use successive guesses and hints to
eventually derive the secret number.
Write a function to return a hint according to the secret number and friend's
guess, use A to indicate the bulls and B to indicate the cows.
Please note that both secret number and friend's guess may contain duplicate
digits.
Example 1:
Output: "1A3B"
Explanation: 1 bull and 3 cows. The bull is 8, the cows are 0, 1 and 7.
Example 2:
Output: "1A1B"
Explanation: The 1st 1 in friend's guess is a bull, the 2nd or 3rd 1 is a cow.
Note: You may assume that the secret number and your friend's guess only contain
digits, and their lengths are always equal.
Solution
02/05/2020:
class Solution {
public:
string getHint(string secret, string guess) {
vector<int> arr1(10, 0), arr2(10, 0);
for (auto& n : secret) {
++arr1[n - '0'];
}
for (auto& n : guess) {
++arr2[n - '0'];
}
int match = 0, bull = 0;
for (int i = 0; i < 10; ++i) {
match += min(arr1[i], arr2[i]);
}
for (int i = 0; i < (int)secret.size(); ++i) {
if (secret[i] == guess[i]) {
++bull;
}
}
string ret;
ret += to_string(bull) + "A" + to_string(match - bull) + "B";
return ret;
}
};
Given an integer array nums, find the sum of the elements between indices i and
j (i ≤ j), inclusive.
Example:
sumRange(0, 2) -> 1
sumRange(2, 5) -> -1
sumRange(0, 5) -> -3
Note:
Solution
/**
* Your NumArray object will be instantiated and called as such:
* NumArray* obj = new NumArray(nums);
* int param_1 = obj->sumRange(i,j);
*/
A 2d grid map of m rows and n columns is initially filled with water. We may
perform an addLand operation which turns the water at position (row, col) into a
land. Given a list of positions to operate, count the number of islands after
each addLand operation. An island is surrounded by water and is formed by
connecting adjacent lands horizontally or vertically. You may assume all four
edges of the grid are all surrounded by water.
Example:
Initially, the 2d grid grid is filled with water. (Assume 0 represents water and
1 represents land).
0 0 0
0 0 0
0 0 0
Operation #1: addLand(0, 0) turns the water at grid[0][0] into a land.
1 0 0
0 0 0 Number of islands = 1
0 0 0
Operation #2: addLand(0, 1) turns the water at grid[0][1] into a land.
1 1 0
0 0 0 Number of islands = 1
0 0 0
Operation #3: addLand(1, 2) turns the water at grid[1][2] into a land.
1 1 0
0 0 1 Number of islands = 2
0 0 0
Operation #4: addLand(2, 1) turns the water at grid[2][1] into a land.
1 1 0
0 0 1 Number of islands = 3
0 1 0
Follow up:
Can you do it in time complexity O(k log mn), where k is the length of the
positions?
Solution
1. Use a set islands to store all the islands being added so far.
2. Use a set components to keep track of roots of current connected components (the size of components
is the desired number of islands).
3. Whenever a new island is added, check whether the neighboring islands (in all four directions) exist.
If there is a such neighbor, remove its root from the components and merge current island with that
neighbor.
4. Then insert the root of island into components.
5. Store the size of components.
class UnionFind {
private:
vector<int> id;
vector<int> sz;
public:
UnionFind(int n) {
id.resize(n);
iota(id.begin(), id.end(), 0);
sz.resize(n, 1);
}
int find(int x) {
while(x != id[x]) {
id[x] = id[id[x]];
x = id[x];
}
return x;
}
class Solution {
public:
vector<int> numIslands2(int m, int n, vector<vector<int>>& positions) {
if (m == 0 || n == 0 || positions.empty() || positions[0].empty()) return
{};
int dir[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
UnionFind uf(m * n);
unordered_set<int> islands;
unordered_set<int> components;
vector<int> ret;
for (auto& p : positions) {
int i = p[0], j = p[1], island = i * n + j;
islands.insert(island);
for (int d = 0; d < 4; ++d) {
int ni = i + dir[d][0], nj = j + dir[d][1], neighbor = ni * n + nj;
if (ni >= 0 && ni < m && nj >= 0 && nj < n && islands.count(neighbor) >
0) {
if (components.count(uf.find(neighbor))) {
components.erase(uf.find(neighbor));
}
uf.merge(island, neighbor);
}
}
components.insert(uf.find(island));
ret.push_back(components.size());
}
return ret;
}
};
You may assume that A's column number is equal to B's row number.
Example:
Input:
A = [
[ 1, 0, 0],
[-1, 0, 3]
]
B = [
[ 7, 0, 0 ],
[ 0, 0, 0 ],
[ 0, 0, 1 ]
]
Output:
| 1 0 0 | | 7 0 0 | | 7 0 0 |
AB = | -1 0 3 | x | 0 0 0 | = | -7 0 3 |
| 0 0 1 |
Solution
05/20/2020:
class Solution {
public:
vector<vector<int>> multiply(vector<vector<int>>& A, vector<vector<int>>& B) {
if (A.empty() || A[0].empty()) return {};
int nrowA = A.size(), ncolA = A[0].size(), ncolB = B[0].size();
vector<vector<int>> ret(nrowA, vector<int>(ncolB, 0));
for (int i = 0; i < nrowA; ++i) {
for (int k = 0; k < ncolA; ++k) {
if (A[i][k] == 0) continue;
for (int j = 0; j < ncolB; ++j) {
if (B[k][j] == 0) continue;
ret[i][j] += A[i][k] * B[k][j];
}
}
}
return ret;
}
};
class Solution {
public:
vector<vector<int>> multiply(vector<vector<int>>& A, vector<vector<int>>& B) {
unordered_map<int, unordered_set<int>> matA, matB;
int nrowA = A.size(), ncolA = A[0].size(), ncolB = B[0].size();
for (int i = 0; i < nrowA; ++i)
for (int j = 0; j < ncolA; ++j)
if (A[i][j] != 0) matA[i].insert(j);
for (int i = 0; i < ncolA; ++i)
for (int j = 0; j < ncolB; ++j)
if (B[i][j] != 0) matB[i].insert(j);
vector<vector<int>> ret(nrowA, vector<int>(ncolB, 0));
for (auto& mA : matA) {
int i = mA.first;
for (auto& k : mA.second)
if (matB.count(k) > 0)
for (auto& j : matB[k])
ret[i][j] += A[i][k] * B[k][j];
}
return ret;
}
};
Given a binary tree, return the vertical order traversal of its nodes' values.
(ie, from top to bottom, column by column).
If two nodes are in the same row and column, the order should be from left to
right.
Examples 1:
Input: [3,9,20,null,null,15,7]
3
/\
/ \
9 20
/\
/ \
15 7
Output:
[
[9],
[3,15],
[20],
[7]
]
Examples 2:
Input: [3,9,8,4,0,1,7]
3
/\
/ \
9 8
/\ /\
/ \/ \
4 01 7
Output:
[
[4],
[9],
[3,0,1],
[8],
[7]
]
Examples 3:
3
/\
/ \
9 8
/\ /\
/ \/ \
4 01 7
/\
/ \
5 2
Output:
[
[4],
[9,5],
[3,0,1],
[8,2],
[7]
]
Solution
04/26/2020:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<vector<int>> verticalOrder(TreeNode* root) {
map<int, vector<int>> mp;
queue<pair<TreeNode*, int>> q;
q.emplace(root, 0);
while (!q.empty()) {
int n = q.size();
for (int i = 0; i < n; ++i) {
pair<TreeNode*, int> cur = q.front(); q.pop();
mp[cur.second].push_back(cur.first->val);
if (cur.first->left) q.emplace(cur.first->left, cur.second - 1);
if (cur.first->right) q.emplace(cur.first->right, cur.second + 1);
}
}
vector<vector<int>> ret;
for (auto& m : mp) ret.push_back(m.second);
return ret;
}
};
Using unordered_map:
class Solution {
public:
vector<vector<int>> verticalOrder(TreeNode* root) {
if (root == nullptr) return {};
int minCol = 0, maxCol = 0;
unordered_map<int, vector<int>> mp;
queue<pair<TreeNode*, int>> q;
q.emplace(root, 0);
while (!q.empty()) {
int n = q.size();
for (int i = 0; i < n; ++i) {
pair<TreeNode*, int> cur = q.front(); q.pop();
mp[cur.second].push_back(cur.first->val);
minCol = min(minCol, cur.second);
maxCol = max(maxCol, cur.second);
if (cur.first->left) q.emplace(cur.first->left, cur.second - 1);
if (cur.first->right) q.emplace(cur.first->right, cur.second + 1);
}
}
vector<vector<int>> ret;
for (int i = minCol; i <= maxCol; ++i)
if (mp.count(i) > 0)
ret.push_back(mp[i]);
return ret;
}
};
Example 1:
Solution
05/27/2020:
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
vector<int> dp(amount + 1, INT_MAX);
dp[0] = 0;
for (int i = 1; i <= amount; ++i)
for (auto& c : coins)
if (i - c >= 0 && dp[i - c] != INT_MAX)
dp[i] = min(dp[i - c] + 1, dp[i]);
return dp.back() == INT_MAX ? -1 : dp.back();
}
};
Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge
is a pair of nodes), write a function to find the number of connected components
in an undirected graph.
Example 1:
Input: n = 5 and edges = [[0, 1], [1, 2], [3, 4]]
0 3
| |
1 --- 2 4
Output: 2
Example 2:
Input: n = 5 and edges = [[0, 1], [1, 2], [2, 3], [3, 4]]
0 4
| |
1 --- 2 --- 3
Output: 1
Note:
You can assume that no duplicate edges will appear in edges. Since all edges are
undirected, [0, 1] is the same as [1, 0] and thus will not appear together in
edges.
Solution
05/05/2020 (BFS):
class Solution {
public:
int countComponents(int n, vector<vector<int>>& edges) {
if (n == 0) return 0;
unordered_map<int, unordered_set<int>> next;
for (auto& e : edges) {
next[e[0]].insert(e[1]);
next[e[1]].insert(e[0]);
}
unordered_set<int> visited;
int ret = 0;
for (int i = 0; i < n; ++i) {
if (visited.count(i) > 0) continue;
queue<int> q;
q.push(i);
visited.insert(i);
while (!q.empty()) {
int cur = q.front(); q.pop();
for (auto& c : next[cur]) {
if (visited.count(c) == 0) q.push(c);
visited.insert(c);
}
}
++ret;
}
return ret;
}
};
class UnionFind {
private:
vector<int> id;
vector<int> sz;
public:
UnionFind(int n) {
id.resize(n);
iota(id.begin(), id.end(), 0);
sz.resize(n, 1);
}
int find(int x) {
while (x != id[x]) {
id[x] = id[id[x]];
x = id[x];
}
return x;
// if (x == id[x]) return x;
// return id[x] = find(id[x]);
}
unordered_set<int> roots;
for (int i = 0; i < n; ++i) {
roots.insert(uf.find(i));
}
return roots.size();
}
};
Example 1:
Input: 27
Output: true
Example 2:
Input: 0
Output: false
Example 3:
Input: 9
Output: true
Example 4:
Input: 45
Output: false
Follow up:
Could you do it without using any loop / recursion?
Solution
06/10/2020:
class Solution {
public:
bool isPowerOfThree(int n) {
return n > 0 && (1162261467 % n == 0);
}
};
class Solution {
public:
bool isPowerOfThree(int n) {
if (n <= 0) return false;
for (; n != 1 && n % 3 == 0; n /= 3);
return n == 1;
}
};
Given a singly linked list, group all odd nodes together followed by the even
nodes. Please note here we are talking about the node number and not the value
in the nodes.
You should try to do it in place. The program should run in O(1) space
complexity and O(nodes) time complexity.
Example 1:
Input: 1->2->3->4->5->NULL
Output: 1->3->5->2->4->NULL
Example 2:
Input: 2->1->3->5->6->4->7->NULL
Output: 2->3->6->7->1->5->4->NULL
Note:
The relative order inside both the even and odd groups should remain as it was
in the input.
The first node is considered odd, the second node even and so on ...
Solution
05/14/2020:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* oddEvenList(ListNode* head) {
if (!head || !head->next) return head;
ListNode *oddHead = head, *evenHead = head->next;
ListNode *cur = evenHead, *oddCur = oddHead, *evenCur = evenHead;
while (cur->next) {
if (cur) {
oddCur->next = cur->next;
oddCur = oddCur->next;
cur = cur->next;
}
if (cur) {
evenCur->next = cur->next;
evenCur = evenCur->next;
cur = cur->next;
}
if (!cur) break;
}
oddCur->next = evenHead;
return oddHead;
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* oddEvenList(ListNode* head) {
if (!head || !head->next) return head;
ListNode *evenHead = head->next, *evenCur = evenHead, *cur = head;
while (cur->next && evenCur->next) {
cur->next = cur->next->next;
cur = cur->next;
evenCur->next = evenCur->next->next;
evenCur = cur->next;
}
cur->next = evenHead;
return head;
}
};
Write a function that reverses a string. The input string is given as an array
of characters char[].
Do not allocate extra space for another array, you must do this by modifying the
input array in-place with O(1) extra memory.
You may assume all the characters consist of printable ascii characters.
Example 1:
Input: ["h","e","l","l","o"]
Output: ["o","l","l","e","h"]
Example 2:
Input: ["H","a","n","n","a","h"]
Output: ["h","a","n","n","a","H"]
Solution
05/30/2020:
class Solution {
public:
void reverseString(vector<char>& s) {
for (int lo = 0, hi = s.size() - 1; lo < hi; ++lo, --hi) swap(s[lo], s[hi]);
}
};
Write a function that takes a string as input and reverse only the vowels of a
string.
Example 1:
Input: "hello"
Output: "holle"
Example 2:
Input: "leetcode"
Output: "leotcede"
Note:
The vowels does not include the letter "y".
Solution
06/16/2020:
class Solution {
public:
string reverseVowels(string s) {
unordered_set<char> vowels{'a', 'e', 'i', 'o', 'u'};
int n = s.size(), l = 0, r = n - 1;
while (l < r) {
while (!isalpha(s[l]) && l < n - 1) ++l;
while (!isalpha(s[l]) && r > 0) --r;
while (l < n - 1 && vowels.count(tolower(s[l])) == 0) ++l;
while (r > 0 && vowels.count(tolower(s[r])) == 0) --r;
if (l < r)
if (vowels.count(tolower(s[l])) > 0 && vowels.count(tolower(s[r])) > 0)
swap(s[l++], s[r--]);
}
return s;
}
};
Example 1:
Solution
05/20/2020:
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> cnt;
for (auto& n : nums) ++cnt[n];
priority_queue<pair<int, int>, vector<pair<int, int>>, less<pair<int, int>>>
q;
for (auto m : cnt) q.emplace(m.second, m.first);
vector<int> ret;
while (k-- > 0) {
ret.push_back(q.top().second);
q.pop();
}
return ret;
}
};
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> cnt;
for (auto& n : nums) ++cnt[n];
vector<pair<int, int>> freq;
for (auto& m : cnt) freq.emplace_back(m.second, m.first);
sort(freq.begin(), freq.end(), greater<pair<int, int>>());
vector<int> ret;
for (auto& f : freq) {
if (k-- > 0) {
ret.push_back(f.second);
} else {
break;
}
}
return ret;
}
};
Solution
06/15/2020:
class TicTacToe {
vector<vector<int>> board;
vector<int> rows;
vector<int> cols;
int diag;
int antiDiag;
int n;
public:
/** Initialize your data structure here. */
TicTacToe(int n) {
board.assign(n, vector<int>(n, -1));
rows.assign(n, 0);
cols.assign(n, 0);
diag = 0;
antiDiag = 0;
this->n = n;
}
/**
* Your TicTacToe object will be instantiated and called as such:
* TicTacToe* obj = new TicTacToe(n);
* int param_1 = obj->move(row,col,player);
*/
367. Valid Perfect Square
Description
Given a positive integer num, write a function which returns True if num is a
perfect square else False.
Example 1:
Input: 16
Output: true
Example 2:
Input: 14
Output: false
Solution
05/08/2020:
class Solution {
public:
bool isPerfectSquare(int num) {
int lo = 0, hi = num;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
long long s = (long long)mid * mid;
if (s == num) {
return true;
} else if (s > num) {
hi = mid - 1;
} else {
lo = mid + 1;
}
}
return (long long)hi * hi == num;
}
};
Si % Sj = 0 or Sj % Si = 0.
Example 1:
Input: [1,2,3]
Output: [1,2] (of course, [1,3] will also be ok)
Example 2:
Input: [1,2,4,8]
Output: [1,2,4,8]
Solution
06/13/2020:
Dynamic Programming:
class Solution {
public:
vector<int> largestDivisibleSubset(vector<int>& nums) {
if (nums.empty()) return nums;
sort(nums.begin(), nums.end());
unordered_map<int, int> dp;
unordered_map<int, int> pre;
for (auto& n : nums) {
dp[n] = 1;
pre[n] = n;
}
int n = nums.size(), max_count = 1, max_num = nums[0];
for (int i = 0; i < n; ++i) {
for (int j = 0; j < i; ++j) {
if (nums[i] % nums[j] == 0) {
if (dp[nums[j]] + 1 > dp[nums[i]]) {
pre[nums[i]] = nums[j];
dp[nums[i]] = dp[nums[j]] + 1;
if (dp[nums[i]] > max_count) {
max_count = dp[nums[i]];
max_num = nums[i];
}
}
}
}
}
vector<int> ret(1, max_num);
while (max_num != pre[max_num]) {
max_num = pre[max_num];
ret.push_back(max_num);
}
return ret;
}
};
Backtracking (TLE):
class Solution {
public:
vector<int> ret;
vector<int> largestDivisibleSubset(vector<int>& nums) {
sort(nums.begin(), nums.end());
int n = nums.size();
vector<int> s;
backtrack(0, n, s, nums);
return ret;
}
Every time you guess wrong, I'll tell you whether the number is higher or lower.
You call a pre-defined API guess(int num) which returns 3 possible results (-1,
1, or 0):
-1 : My number is lower
1 : My number is higher
0 : Congrats! You got it!
Example :
Solution
04/23/2020:
/**
* Forward declaration of guess API.
* @param num your guess
* @return -1 if num is lower than the guess number
* 1 if num is higher than the guess number
* otherwise return 0
* int guess(int num);
*/
class Solution {
public:
int guessNumber(int n) {
int lo = 1, hi = n;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
int ans = guess(mid);
if (ans == 0) {
return mid;
} else if (ans == 1) {
lo = mid + 1;
} else {
hi = mid - 1;
}
}
return lo;
}
};
379. Design Phone Directory
Description
Example:
// Assume it returns 1.
directory.get();
Constraints:
Solution
06/15/2020:
class PhoneDirectory {
private:
vector<bool> numbers;
int p, maxNumbers;
stack<int> st;
public:
/** Initialize your data structure here
@param maxNumbers - The maximum numbers that can be stored in the phone
directory. */
PhoneDirectory(int maxNumbers) {
numbers.assign(maxNumbers, true);
this->maxNumbers = maxNumbers;
p = 0;
}
class PhoneDirectory {
private:
vector<bool> numbers;
int p, maxNumbers;
public:
/** Initialize your data structure here
@param maxNumbers - The maximum numbers that can be stored in the phone
directory. */
PhoneDirectory(int maxNumbers) {
numbers.assign(maxNumbers, true);
this->maxNumbers = maxNumbers;
p = 0;
}
Design a data structure that supports all following operations in average O(1)
time.
// Removes 1 from the set, returns true. Set now contains [2].
randomSet.remove(1);
06/12/2020:
class RandomizedSet {
private:
unordered_map<int, int> cnt;
vector<int> nums;
int n;
public:
/** Initialize your data structure here. */
RandomizedSet() {
nums.clear();
cnt.clear();
n = 0;
}
/** Inserts a value to the set. Returns true if the set did not already
contain the specified element. */
bool insert(int val) {
if (cnt.count(val) > 0) return false;
nums.push_back(val);
cnt[val] = n++;
return true;
}
/** Removes a value from the set. Returns true if the set contained the
specified element. */
bool remove(int val) {
if (cnt.count(val) == 0) return false;
cnt[nums[n - 1]] = cnt[val];
swap(nums[cnt[val]], nums[n - 1]);
cnt.erase(val);
nums.pop_back();
--n;
return true;
}
/**
* Your RandomizedSet object will be instantiated and called as such:
* RandomizedSet* obj = new RandomizedSet();
* bool param_1 = obj->insert(val);
* bool param_2 = obj->remove(val);
* int param_3 = obj->getRandom();
*/
class RandomizedSet {
private:
unordered_set<int> cnt;
vector<int> nums;
bool ok = false;
public:
/** Initialize your data structure here. */
RandomizedSet() {
nums.clear();
cnt.clear();
}
/** Inserts a value to the set. Returns true if the set did not already
contain the specified element. */
bool insert(int val) {
if (cnt.count(val) > 0) return false;
cnt.insert(val);
nums.push_back(val);
return true;
}
/** Removes a value from the set. Returns true if the set contained the
specified element. */
bool remove(int val) {
if (cnt.count(val) == 0) return false;
cnt.erase(val);
return true;
}
/**
* Your RandomizedSet object will be instantiated and called as such:
* RandomizedSet* obj = new RandomizedSet();
* bool param_1 = obj->insert(val);
* bool param_2 = obj->remove(val);
* int param_3 = obj->getRandom();
*/
Example:
// Shuffle the array [1,2,3] and return its result. Any permutation of [1,2,3]
must equally likely to be returned.
solution.shuffle();
Solution
05/25/2020:
class Solution {
private:
vector<int> nums;
std::function<int()> mt19937_rand;
public:
Solution(vector<int>& nums) {
this->nums = nums;
mt19937_rand = bind(uniform_int_distribution<int>(0, INT_MAX),
mt19937(time(0)));
}
/** Resets the array to its original configuration and return it. */
vector<int> reset() {
return nums;
}
/**
* Your Solution object will be instantiated and called as such:
* Solution* obj = new Solution(nums);
* vector<int> param_1 = obj->reset();
* vector<int> param_2 = obj->shuffle();
*/
class Solution {
private:
vector<int> nums;
mt19937 mt19937_rand;
unsigned seed;
public:
Solution(vector<int>& nums) {
this->nums = nums;
seed = std::chrono::system_clock::now().time_since_epoch().count();
mt19937_rand.seed(seed);
}
/** Resets the array to its original configuration and return it. */
vector<int> reset() {
seed = std::chrono::system_clock::now().time_since_epoch().count();
mt19937_rand.seed(seed);
return nums;
}
Given a string, find the first non-repeating character in it and return it's
index. If it doesn't exist, return -1.
Examples:
s = "leetcode"
return 0.
s = "loveleetcode",
return 2.
Note: You may assume the string contain only lowercase letters.
Solution
05/05/2020:
class Solution {
public:
int firstUniqChar(string s) {
unordered_map<char, int> mp;
for (auto& c : s) ++mp[c];
int n = s.size();
for (int i = 0; i < n; ++i)
if (mp[s[i]] == 1)
return i;
return -1;
}
};
String t is generated by random shuffling string s and then add one more letter
at a random position.
Example:
Input:
s = "abcd"
t = "abcde"
Output:
e
Explanation:
'e' is the letter that was added.
Solution
05/17/2020:
class Solution {
public:
char findTheDifference(string s, string t) {
vector<int> cntS(26, 0);
vector<int> cntT(26, 0);
for (auto& c : s) {
++cntS[c - 'a'];
}
for (auto& c : t) {
++cntT[c - 'a'];
}
for (int i = 0; i < 26; ++i) {
if (cntS[i] < cntT[i]) {
return i + 'a';
}
}
return 'a';
}
};
392. Is Subsequence
Description
You may assume that there is only lower case English letters in both s and t. t
is potentially a very long (length ~= 500,000) string, and s is a short string
(<=100).
Example 1:
s = "abc", t = "ahbgdc"
Return true.
Example 2:
s = "axc", t = "ahbgdc"
Return false.
Follow up:
If there are lots of incoming S, say S1, S2, ... , Sk where k >= 1B, and you
want to check one by one to see if T has its subsequence. In this scenario, how
would you change your code?
Credits:
Special thanks to @pbrother for adding this problem and creating all test cases.
Solution
class Solution {
public:
bool isSubsequence(string s, string t) {
if (s.size() >= t.size()) return s == t;
return s.back() == t.back() ? isSubsequence(s.substr(0, s.size() - 1),
t.substr(0, t.size() - 1)) :
isSubsequence(s, t.substr(0, t.size() - 1));
}
};
06/09/2020:
class Solution {
public:
bool isSubsequence(string s, string t) {
auto sit = s.begin(), tit = t.begin();
for (; sit != s.end() && tit != t.end(); ++tit)
if (*sit == *tit) ++sit;
return sit == s.end();
}
};
Note:
The length of num is less than 10002 and will be ≥ k.
The given num does not contain any leading zero.
Example 1:
Solution
05/12/2020:
class Solution {
public:
string removeKdigits(string num, int k) {
deque<char> q;
string ret;
for (int i = 0; i < num.size(); ++i) {
while (!q.empty() && q.back() > num[i] && k-- > 0) q.pop_back();
q.push_back(num[i]);
}
while (!q.empty() && k-- > 0) q.pop_back();
while (!q.empty() && q.front() == '0') q.pop_front();
while (!q.empty()) ret += q.front(), q.pop_front();
return ret.empty() ? string(1, '0') : ret;
}
};
class Solution {
public:
string removeKdigits(string num, int k) {
string ret;
for (int i = 0; i < num.size(); ++i) {
while (!ret.empty() && ret.back() > num[i] && k-- > 0)
ret.pop_back();
if (!ret.empty() || num[i] != '0')
ret += num[i];
}
while (!ret.empty() && k-- > 0)
ret.pop_back();
return ret.empty() ? "0" : ret;
}
};
Example:
3
/ \
9 20
/ \
15 7
There are two left leaves in the binary tree, with values 9 and 15 respectively.
Return 24.
Solution
Discussion
Recursive:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root, bool isLeft = false) {
if (root == nullptr) return 0;
int s = !root->left && !root->right && isLeft ? root->val : 0;
return s + sumOfLeftLeaves(root->left, true) + sumOfLeftLeaves(root->right,
false);
}
};
Iterative:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
if (root == nullptr) return 0;
int s = 0;
stack<pair<TreeNode*, bool>> st;
st.emplace(root, false);
while (!st.empty()) {
pair<TreeNode*, bool> cur = st.top(); st.pop();
s += cur.first->left == nullptr && cur.first->right == nullptr &&
cur.second ? cur.first->val : 0;
if (cur.first->left) st.emplace(cur.first->left, true);
if (cur.first->right) st.emplace(cur.first->right, false);
}
return s;
}
};
Suppose you have a random list of people standing in a queue. Each person is
described by a pair of integers (h, k), where h is the height of the person and
k is the number of people in front of this person who have a height greater than
or equal to h. Write an algorithm to reconstruct the queue.
Note:
The number of people is less than 1,100.
Example
Input:
[[7,0], [4,4], [7,1], [5,0], [6,1], [5,2]]
Output:
[[5,0], [7,0], [5,2], [6,1], [4,4], [7,1]]
Solution
06/06/2020:
class Solution {
public:
vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
if (people.empty() || people[0].empty()) return people;
sort(people.begin(), people.end(), [](vector<int>& p1, vector<int>& p2) {
if (p1[0] == p2[0]) return p1[1] < p2[1];
return p1[0] > p2[0];
});
list<vector<int>> ret;
for (int i = 0; i < (int)people.size(); ++i)
ret.insert(next(ret.begin(), people[i][1]), people[i]);
return vector<vector<int>>(ret.begin(), ret.end());
}
};
class Solution {
public:
vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
if (people.empty() || people[0].empty()) return people;
sort(people.begin(), people.end(), [](vector<int>& p1, vector<int>& p2) {
if (p1[0] == p2[0]) return p1[1] < p2[1];
return p1[0] > p2[0];
});
vector<vector<int>> ret;
for (int i = 0; i < (int)people.size(); ++i)
ret.insert(ret.begin() + people[i][1], people[i]);
return ret;
}
};
Given a string which consists of lowercase or uppercase letters, find the length
of the longest palindromes that can be built with those letters.
This is case sensitive, for example "Aa" is not considered a palindrome here.
Note:
Assume the length of given string will not exceed 1,010.
Example:
Input:
"abccccdd"
Output:
7
Explanation:
One longest palindrome that can be built is "dccaccd", whose length is 7.
Solution
05/18/2020:
class Solution {
public:
int longestPalindrome(string s) {
vector<int> cnt(128, 0);
for (auto& c : s) {
++cnt[c];
}
bool odd = false;
int even = 0;
for (int i = 0; i < 128; ++i) {
if (cnt[i] % 2 == 0) {
even += cnt[i];
} else {
odd = true;
even += max(cnt[i] - 1, 0);
}
}
return odd ? even + 1 : even;
}
};
Note:
Solution
06/09/2020:
class Solution {
public:
string addStrings(string num1, string num2) {
int carry = 0;
int n1 = num1.size(), n2 = num2.size();
string ret;
for (int i1 = n1 - 1, i2 = n2 - 1; i1 >= 0 || i2 >= 0 || carry > 0; --i1, --
i2) {
if (i1 >= 0) carry += num1[i1] - '0';
if (i2 >= 0) carry += num2[i2] - '0';
ret.push_back(carry % 10 + '0');
carry /= 10;
}
reverse(ret.begin(), ret.end());
return ret;
}
};
Given an n-ary tree, return the level order traversal of its nodes' values.
Example 1:
Input: root = [1,null,3,2,4,null,5,6]
Output: [[1],[3,2,4],[5,6]]
Example 2:
Input: root =
[1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null
,null,14]
Output: [[1],[2,3,4,5],[6,7,8,9,10],[11,12,13],[14]]
Constraints:
Solution
04/26/2020:
/*
// Definition for a Node.
class Node {
public:
int val;
vector<Node*> children;
Node() {}
Node(int _val) {
val = _val;
}
class Solution {
public:
vector<vector<int>> levelOrder(Node* root) {
if (root == nullptr) return {};
queue<Node*> q;
q.push(root);
vector<vector<int>> ret;
ret.push_back({root->val});
while (!q.empty()) {
int n = q.size();
vector<int> level;
for (int i = 0; i < n; ++i) {
Node* cur = q.front(); q.pop();
for (auto& c : cur->children) {
level.push_back(c->val);
q.push(c);
}
}
if (!level.empty()) ret.push_back(level);
}
return ret;
}
};
Given a string s and a non-empty string p, find all the start indices of p's
anagrams in s.
Strings consists of lowercase English letters only and the length of both
strings s and p will not be larger than 20,100.
Example 1:
Input:
s: "cbaebabacd" p: "abc"
Output:
[0, 6]
Explanation:
The substring with start index = 0 is "cba", which is an anagram of "abc".
The substring with start index = 6 is "bac", which is an anagram of "abc".
Example 2:
Input:
s: "abab" p: "ab"
Output:
[0, 1, 2]
Explanation:
The substring with start index = 0 is "ab", which is an anagram of "ab".
The substring with start index = 1 is "ba", which is an anagram of "ab".
The substring with start index = 2 is "ab", which is an anagram of "ab".
Solution
05/16/2020:
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
vector<int> sch(26, 0), pch(26, 0), ret;
for (auto& c : p) ++pch[c - 'a'];
int m = p.size(), n = s.size();
if (m > n) return {};
for (int i = 0; i < m - 1; ++i) ++sch[s[i] - 'a'];
bool ok = false;
for (int i = m - 1; i < n; ++i) {
if (ok) {
if (s[i] == s[i - m]) {
ret.push_back(i - m + 1);
} else {
--sch[s[i - m] - 'a'];
++sch[s[i] - 'a'];
ok = false;
}
} else {
if (i >= m) --sch[s[i - m] - 'a'];
++sch[s[i] - 'a'];
ok = true;
for (int j = 0; j < 26; ++j) {
if (pch[j] != sch[j]) {
ok = false;
break;
}
}
if (ok) ret.push_back(i - m + 1);
}
}
return ret;
}
};
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
vector<int> sch(26, 0), pch(26, 0), ret;
for (auto& c : p) ++pch[c - 'a'];
int m = p.size(), n = s.size();
for (int i = 0; i < n; ++i) {
if (i - m >= 0) --sch[s[i - m] - 'a'];
++sch[s[i] - 'a'];
bool ok = true;
for (int j = 0; j < 26; ++j) {
if (pch[j] != sch[j]) {
ok = false;
break;
}
}
if (ok) ret.push_back(i - m + 1);
}
return ret;
}
};
Given n points in the plane that are all pairwise distinct, a "boomerang" is a
tuple of points (i, j, k) such that the distance between i and j equals the
distance between i and k (the order of the tuple matters).
Find the number of boomerangs. You may assume that n will be at most 500 and
coordinates of points are all in the range [-10000, 10000] (inclusive).
Example:
Input:
[[0,0],[1,0],[2,0]]
Output:
2
Explanation:
The two boomerangs are [[1,0],[0,0],[2,0]] and [[1,0],[2,0],[0,0]]
Solution
05/20/2020:
class Solution {
public:
int numberOfBoomerangs(vector<vector<int>>& points) {
if (points.empty() || points[0].empty()) return 0;
int n = points.size(), cnt = 0;
vector<unordered_map<double, int>> mp(n);
for (int i = 0; i < n - 1; ++i) {
for (int j = i + 1; j < n; ++j) {
int x1 = points[i][0], x2 = points[j][0];
int y1 = points[i][1], y2 = points[j][1];
double d = hypot(x1 - x2, y1 - y2);
++mp[i][d];
++mp[j][d];
}
}
for (int i = 0; i < n; ++i)
for (auto& m : mp[i])
cnt += nchoosek(m.second, 2) * 2;
return cnt;
}
Example 1:
Input:
"tree"
Output:
"eert"
Explanation:
'e' appears twice while 'r' and 't' both appear once.
So 'e' must appear before both 'r' and 't'. Therefore "eetr" is also a valid
answer.
Example 2:
Input:
"cccaaa"
Output:
"cccaaa"
Explanation:
Both 'c' and 'a' appear three times, so "aaaccc" is also a valid answer.
Note that "cacaca" is incorrect, as the same characters must be together.
Example 3:
Input:
"Aabb"
Output:
"bbAa"
Explanation:
"bbaA" is also a valid answer, but "Aabb" is incorrect.
Note that 'A' and 'a' are treated as two different characters.
Solution
05/20/2020:
class Solution {
public:
string frequencySort(string s) {
unordered_map<char, int> mp;
for (auto& c : s) ++mp[c];
vector<pair<int, char>> str;
for (auto& m : mp) str.emplace_back(m.second, m.first);
sort(str.begin(), str.end(), greater<pair<int, char>>());
string ret = "";
for (auto& s : str) ret += string(s.first, s.second);
return ret;
}
};
Besides, leading zeros in the IPv4 is invalid. For example, the address
172.16.254.01 is invalid.
IPv6 addresses are represented as eight groups of four hexadecimal digits, each
group representing 16 bits. The groups are separated by colons (":"). For
example, the address 2001:0db8:85a3:0000:0000:8a2e:0370:7334 is a valid one.
Also, we could omit some leading zeros among four hexadecimal digits and some
low-case characters in the address to upper-case ones, so
2001:db8:85a3:0:0:8A2E:0370:7334 is also a valid IPv6 address(Omit leading zeros
and using upper cases).
However, we don't replace a consecutive group of zero value with a single empty
group using two consecutive colons (::) to pursue simplicity. For example,
2001:0db8:85a3::8A2E:0370:7334 is an invalid IPv6 address.
Besides, extra leading zeros in the IPv6 is also invalid. For example, the
address 02001:0db8:85a3:0000:0000:8a2e:0370:7334 is invalid.
Note: You may assume there is no extra space or special characters in the input
string.
Example 1:
Input: "172.16.254.1"
Output: "IPv4"
Output: "IPv6"
Output: "Neither"
Solution
06/16/2020:
class Solution {
public:
string validIPAddress(string IP) {
int n = IP.size();
vector<string> ipv4 = split(IP, '.');
vector<string> ipv6 = split(IP, ':');
bool isIpv4 = ipv4.size() == 4 && isdigit(IP.front()) && isdigit(IP.back());
bool isIpv6 = ipv6.size() == 8 && (isalpha(IP.front()) ||
isdigit(IP.front())) && (isalpha(IP.back()) || isdigit(IP.back()));
bool hasLeadingZero = false;
if (isIpv4) {
for (auto& s : ipv4) {
isIpv4 = isIpv4 && s.size() <= 3 && s.size() > 0;
for (auto& c : s) isIpv4 = isIpv4 && isdigit(c);
if (!isIpv4) break;
int n = stoi(s);
isIpv4 = isIpv4 && (0 <= n && n <= 255 && to_string(n) == s);
}
} else if (isIpv6) {
for (auto& s : ipv6) {
isIpv6 = isIpv6 && s.size() > 0 && s.size() < 5;
for (auto& c : s) isIpv6 = isIpv6 && (('0' <= c && c <= '9') || ('a' <=
c && c <= 'f') || ('A' <= c && c <= 'F'));
if (!isIpv6) break;
}
}
return isIpv4 ? "IPv4" : isIpv6 ? "IPv6" : "Neither";
}
Given a function rand7 which generates a uniform random integer in the range 1
to 7, write a function rand10 which generates a uniform random integer in the
range 1 to 10.
Example 1:
Input: 1
Output: [7]
Example 2:
Input: 2
Output: [8,4]
Example 3:
Input: 3
Output: [8,1,10]
Note:
rand7 is predefined.
Each testcase has one argument: n, the number of times that rand10 is called.
Follow up:
What is the expected value for the number of calls to rand7() function?
Could you minimize the number of calls to rand7()?
Solution
05/27/2020:
class Solution {
public:
int rand10() {
int s = 41;
while (s > 40) s = (rand7() - 1) * 7 + rand7();
return (s - 1) % 10 + 1;
}
};
475. Heaters
Description
Winter is coming! Your first job during the contest is to design a standard
heater with fixed warm radius to warm all the houses.
Now, you are given positions of houses and heaters on a horizontal line, find
out minimum radius of heaters so that all houses could be covered by those
heaters.
So, your input will be the positions of houses and heaters seperately, and your
expected output will be the minimum radius standard of heaters.
Note:
Numbers of houses and heaters you are given are non-negative and will not exceed
25000.
Positions of houses and heaters you are given are non-negative and will not
exceed 10^9.
As long as a house is in the heaters' warm radius range, it can be warmed.
All the heaters follow your radius standard and the warm radius will the same.
Example 1:
Input: [1,2,3],[2]
Output: 1
Explanation: The only heater was placed in the position 2, and if we use the
radius 1 standard, then all the houses can be warmed.
Example 2:
Input: [1,2,3,4],[1,4]
Output: 1
Explanation: The two heater was placed in the position 1 and 4. We need to use
radius 1 standard, then all the houses can be warmed.
Solution
04/23/2020:
class Solution {
public:
int findRadius(vector<int>& houses, vector<int>& heaters) {
if ((int)houses.size() <= 0) return 0;
int n = heaters.size();
if (n <= 0) return INT_MAX;
sort(heaters.begin(), heaters.end());
for (auto& h : houses) {
int lo = 0, hi = n - 1;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
if (heaters[mid] <= h) {
lo = mid + 1;
} else {
hi = mid - 1;
}
}
int left = INT_MAX, right = INT_MAX;
if (lo - 1 >= 0) left = min(right, h - heaters[lo - 1]);
if (lo < n) right = min(left, heaters[lo] - h);
h = min(left, right);
}
return *max_element(houses.begin(), houses.end());
}
};
482. License Key Formatting
Description
You are given a license key represented as a string S which consists only
alphanumeric character and dashes. The string is separated into N+1 groups by N
dashes.
Given a number K, we would want to reformat the strings such that each group
contains exactly K characters, except for the first group which could be shorter
than K, but still must contain at least one character. Furthermore, there must
be a dash inserted between two groups and all lowercase letters should be
converted to uppercase.
Given a non-empty string S and a number K, format the string according to the
rules described above.
Example 1:
Input: S = "5F3Z-2e-9-w", K = 4
Output: "5F3Z-2E9W"
Explanation: The string S has been split into two parts, each part has 4
characters.
Note that the two extra dashes are not needed and can be removed.
Example 2:
Input: S = "2-5g-3-J", K = 2
Output: "2-5G-3J"
Explanation: The string S has been split into three parts, each part has 2
characters except the first part as it could be shorter as mentioned above.
Note:
The length of string S will not exceed 12,000, and K is a positive integer.
String S consists only of alphanumerical characters (a-z and/or A-Z and/or 0-9)
and dashes(-).
String S is non-empty.
Solution
02/05/2020:
class Solution {
public:
string licenseKeyFormatting(string S, int K) {
string ret;
int cnt = 0;
for (auto it = S.rbegin(); it != S.rend(); ++it) {
if (*it == '-') {
continue;
} else {
ret += toupper(*it);
}
if (++cnt % K == 0) {
cnt == 0;
ret += '-';
}
}
if (ret.back() == '-') {
ret.pop_back();
}
reverse(ret.begin(), ret.end());
return ret;
}
};
Example:
Input:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
Output: [1,2,4,7,5,3,6,8,9]
Explanation:
Note:
The total number of elements of the given matrix will not exceed 10,000.
Solution
05/20/2020:
class Solution {
public:
vector<int> findDiagonalOrder(vector<vector<int>>& matrix) {
if (matrix.empty() || matrix[0].empty()) return {};
int m = matrix.size(), n = matrix[0].size();
vector<int> ret;
bool ascending = false;
for (int k = 0; k < m + n; ++k) {
if (ascending)
for (int i = max(0, k - n + 1); i <= min(m - 1, k); ++i)
ret.push_back(matrix[i][k - i]);
else
for (int i = min(m - 1, k); i >= max(0, k - n + 1); --i)
ret.push_back(matrix[i][k - i]);
ascending = !ascending;
}
return ret;
}
};
Given a node in a binary search tree, find the in-order successor of that node
in the BST.
The successor of a node is the node with the smallest key greater than node.val.
You will have direct access to the node but not to the root of the tree. Each
node will have a reference to its parent node. Below is the definition for Node:
class Node {
public int val;
public Node left;
public Node right;
public Node parent;
}
Follow up:
Example 1:
Input: tree =
[15,6,18,3,7,17,20,2,4,null,13,null,null,null,null,null,null,null,null,9], node
= 15
Output: 17
Example 4:
Input: tree =
[15,6,18,3,7,17,20,2,4,null,13,null,null,null,null,null,null,null,null,9], node
= 13
Output: 15
Example 5:
Constraints:
Solution
05/24/2020:
/*
// Definition for a Node.
class Node {
public:
int val;
Node* left;
Node* right;
Node* parent;
};
*/
class Solution {
public:
Node* inorderSuccessor(Node* node) {
if (node->right != nullptr) return leftmostChild(node->right);
Node* parent = smallestParentGreaterThanNode(node);
return parent == nullptr || parent->val < node->val ? nullptr : parent;
}
class Solution {
public:
Node* inorderSuccessor(Node* node) {
if (node->right != nullptr) return leftmost(node->right);
Node* parent = node->parent;
while (true) {
if (parent != nullptr && parent->val < node->val && parent->parent !=
nullptr) {
parent = parent->parent;
} else {
break;
}
}
return parent != nullptr && parent->val < node->val ? nullptr : parent;
}
class Solution {
public:
Node* inorderSuccessor(Node* node) {
Node* root = node;
while (true) {
if (root->parent != nullptr)
root = root->parent;
else
break;
}
vector<Node*> inorder = inorderTraversal(root);
auto it = find(inorder.begin(), inorder.end(), node);
return it != inorder.end() && it + 1 != inorder.end() ? *(it + 1) : nullptr;
}
Example 1:
Note:
Solution
05/27/2020:
class Solution {
public:
int change(int amount, vector<int>& coins) {
vector<int> dp(amount + 1, 0);
dp[0] = 1;
for (auto& c : coins) {
for (int i = c; i <= amount; ++i) {
if (i - c >= 0) {
dp[i] += dp[i - c];
}
}
}
return dp.back();
}
};
Given a binary array, find the maximum length of a contiguous subarray with
equal number of 0 and 1.
Example 1:
Input: [0,1]
Output: 2
Explanation: [0, 1] is the longest contiguous subarray with equal number of 0
and 1.
Example 2:
Input: [0,1,0]
Output: 2
Explanation: [0, 1] (or [1, 0]) is a longest contiguous subarray with equal
number of 0 and 1.
Note: The length of the given binary array will not exceed 50,000.
Solution
05/26/2020:
class Solution {
public:
int findMaxLength(vector<int>& nums) {
if (nums.empty()) return 0;
unordered_map<int, int> firstOccurence{ {0, -1} };
int n = nums.size(), ret = 0, prefix = 0;
for (int i = 0; i < n; ++i) {
prefix = prefix + (nums[i] == 0 ? 1 : -1);
if (firstOccurence.count(prefix) == 0)
firstOccurence[prefix] = i;
else
ret = max(ret, i - firstOccurence[prefix]);
}
return ret;
}
};
Given an array w of positive integers, where w[i] describes the weight of index
i, write a function pickIndex which randomly picks an index in proportion to its
weight.
Note:
Input:
["Solution","pickIndex"]
[[[1]],[]]
Output: [null,0]
Example 2:
Input:
["Solution","pickIndex","pickIndex","pickIndex","pickIndex","pickIndex"]
[[[1,3]],[],[],[],[],[]]
Output: [null,0,1,1,1,0]
Explanation of Input Syntax:
The input is two lists: the subroutines called and their arguments. Solution's
constructor has one argument, the array w. pickIndex has no arguments. Arguments
are always wrapped with a list, even if there aren't any.
Solution
06/05/2020:
class Solution {
private:
vector<int> weights;
mt19937 rand;
public:
Solution(vector<int>& w) {
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
rand.seed(seed);
weights.resize(w.size());
partial_sum(w.begin(), w.end(), weights.begin(), plus<int>());
}
int pickIndex() {
long long n = (double) rand() / rand.max() * weights.back();
return upper_bound(weights.begin(), weights.end(), n) - weights.begin();
}
};
/**
* Your Solution object will be instantiated and called as such:
* Solution* obj = new Solution(w);
* int param_1 = obj->pickIndex();
*/
Note: This is a companion problem to the System Design problem: Design TinyURL
(https://leetcode.com/discuss/interview-question/124658/Design-a-URL-Shortener-
(-TinyURL-)-System/).
TinyURL is a URL shortening service where you enter a URL such as
https://leetcode.com/problems/design-tinyurl and it returns a short URL such as
http://tinyurl.com/4e9iAk.
Design the encode and decode methods for the TinyURL service. There is no
restriction on how your encode/decode algorithm should work. You just need to
ensure that a URL can be encoded to a tiny URL and the tiny URL can be decoded
to the original URL.
Solution
05/20/2020:
class Solution {
private:
unordered_map<string, string> decodeTable;
unordered_map<string, string> encodeTable;
string base = "http://tinyurl.com/";
const int MOD = 1e9 + 7;
int hash(string s) {
long long h = 1;
for (auto& c : s) h = (h * 131 + c) % MOD;
return h;
}
public:
You are given a sorted array consisting of only integers where every element
appears exactly twice, except for one element which appears exactly once. Find
this single element that appears only once.
Follow up: Your solution should run in O(log n) time and O(1) space.
Example 1:
Constraints:
Solution
05/12/2020:
class Solution {
public:
int singleNonDuplicate(vector<int>& nums) {
int lo = 0, hi = nums.size() - 1;
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (mid % 2 == 0) {
if (nums[mid] != nums[mid + 1]) {
hi = mid;
} else {
lo = mid + 1;
}
} else {
if (nums[mid] != nums[mid - 1]) {
hi = mid;
} else {
lo = mid + 1;
}
}
}
return nums[lo];
}
};
class Solution {
public:
int singleNonDuplicate(vector<int>& nums) {
int lo = 0, hi = nums.size() - 1;
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if ((!(mid & 1) && nums[mid] != nums[mid + 1]) || ((mid & 1) && nums[mid]
!= nums[mid - 1])) {
hi = mid;
} else {
lo = mid + 1;
}
}
return nums[lo];
}
};
class Solution {
public:
int singleNonDuplicate(vector<int>& nums) {
int ret = 0;
for (auto& n : nums) {
ret ^= n;
}
return ret;
}
};
542. 01 Matrix
Description
Given a matrix consists of 0 and 1, find the distance of the nearest 0 for each
cell.
Example 1:
Input:
[[0,0,0],
[0,1,0],
[0,0,0]]
Output:
[[0,0,0],
[0,1,0],
[0,0,0]]
Example 2:
Input:
[[0,0,0],
[0,1,0],
[1,1,1]]
Output:
[[0,0,0],
[0,1,0],
[1,2,1]]
Note:
The number of elements of the given matrix will not exceed 10,000.
There are at least one 0 in the given matrix.
The cells are adjacent in only four directions: up, down, left and right.
Solution
06/09/2020: BFS:
class Solution {
public:
vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) {
if (matrix.empty() || matrix[0].empty()) return matrix;
int m = matrix.size(), n = matrix[0].size();
int dir[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
queue<pair<int, int >> q;
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
if (matrix[i][j] == 0)
q.emplace(i, j);
else
matrix[i][j] = INT_MAX;
while (!q.empty()) {
pair<int, int> cur = q.front(); q.pop();
int i = cur.first, j = cur.second;
for (int d = 0; d < 4; ++d) {
int ni = i + dir[d][0], nj = j + dir[d][1];
if (ni < 0 || ni >= m || nj < 0 || nj >=n) continue;
if (matrix[ni][nj] > matrix[i][j] + 1) {
matrix[ni][nj] = matrix[i][j] + 1;
q.emplace(ni, nj);
}
}
}
return matrix;
}
};
class Solution {
public:
vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) {
if (matrix.empty() || matrix[0].empty()) return matrix;
int m = matrix.size(), n = matrix[0].size();
int dir[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (matrix[i][j] == 0) continue;
int cur_min = INT_MAX;
queue<pair<int, int>> q;
q.emplace(i, j);
bool found = false;
unordered_set<string> visited;
while (!q.empty() && !found) {
int sz = q.size();
for (int s = 0; s < sz && !found; ++s) {
pair<int, int> cur = q.front(); q.pop();
string key = to_string(cur.first) + "," + to_string(cur.second);
if (visited.count(key) > 0) continue;
for (int d = 0; d < 4; ++d) {
int ni = cur.first + dir[d][0], nj = cur.second + dir[d][1];
string key = to_string(i) + "," + to_string(j);
if (ni < 0 || ni >= m || nj < 0 || nj >= n) continue;
if (matrix[ni][nj] == 0) {
found = true;
matrix[i][j] = (abs(i - ni) + abs(j - nj));
break;
} else {
q.emplace(ni, nj);
}
}
visited.insert(key);
}
}
}
}
return matrix;
}
};
Dynamic Programming:
class Solution {
public:
vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) {
if (matrix.empty() || matrix[0].empty()) return matrix;
int m = matrix.size(), n = matrix[0].size();
int dir[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
queue<pair<int, int >> q;
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
if (matrix[i][j] != 0)
matrix[i][j] = INT_MAX;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (i > 0 && matrix[i - 1][j] != INT_MAX) matrix[i][j] = min(matrix[i]
[j], matrix[i - 1][j] + 1);
if (j > 0 && matrix[i][j - 1] != INT_MAX) matrix[i][j] = min(matrix[i]
[j], matrix[i][j - 1] + 1);
}
}
for (int i = m - 1; i >= 0; --i) {
for (int j = n - 1; j >= 0; --j) {
if (i < m - 1 && matrix[i + 1][j] != INT_MAX) matrix[i][j] =
min(matrix[i][j], matrix[i + 1][j] + 1);
if (j < n - 1 && matrix[i][j + 1] != INT_MAX) matrix[i][j] =
min(matrix[i][j], matrix[i][j + 1] + 1);
}
}
return matrix;
}
};
You are given a string representing an attendance record for a student. The
record only contains the following three characters:
'A' : Absent.
'L' : Late.
'P' : Present.
A student could be rewarded if his attendance record doesn't contain more than
one 'A' (absent) or more than two continuous 'L' (late).
You need to return whether the student could be rewarded according to his
attendance record.
Example 1:
Input: "PPALLP"
Output: True
;xample 2:
Input: "PPALLL"
Output: False
Solution
02/05/2020:
class Solution {
public:
bool checkRecord(string s) {
int cntA = 0, cntLL = 0;
for (auto i = 0; i < s.size(); ++i) {
if (s[i] == 'A') {
++cntA;
} else if (s[i] == 'L') {
if (i > 0 && s[i - 1] == 'L') {
++cntLL;
} else {
cntLL = 1;
}
}
if (cntA > 1 || cntLL > 2) {
return false;
}
}
return true;
}
};
Given two strings s1 and s2, write a function to return true if s2 contains the
permutation of s1. In other words, one of the first string's permutations is the
substring of the second string.
Example 1:
Note:
Solution
05/18/2020:
class Solution {
public:
bool checkInclusion(string s, string t) {
vector<int> cntS(26, 0), cntT(26, 0);
int n = s.size(), m = t.size();
for (auto& c : s) ++cntS[c - 'a'];
for (int i = 0; i < m; ++i) {
++cntT[t[i] - 'a'];
bool ok = true;
if (i - n >= 0) --cntT[t[i - n] - 'a'];
for (int j = 0; j < 26; ++j)
if (cntS[j] != cntT[j]) ok = false;
if (ok) return true;
}
return false;
}
};
Given a list of directory info including directory path, and all the files with
contents in this directory, you need to find out all the groups of duplicate
files in the file system in terms of their paths.
A group of duplicate files consists of at least two files that have exactly the
same content.
A single directory info string in the input list has the following format:
"root/d1/d2/.../dm f1.txt(f1_content) f2.txt(f2_content) ... fn.txt(fn_content)"
It means there are n files (f1.txt, f2.txt ... fn.txt with content f1_content,
f2_content ... fn_content, respectively) in directory root/d1/d2/.../dm. Note
that n >= 1 and m >= 0. If m = 0, it means the directory is just the root
directory.
The output is a list of group of duplicate file paths. For each group, it
contains all the file paths of the files that have the same content. A file path
is a string that has the following format:
"directory_path/file_name.txt"
Example 1:
Input:
["root/a 1.txt(abcd) 2.txt(efgh)", "root/c 3.txt(abcd)", "root/c/d 4.txt(efgh)",
"root 4.txt(efgh)"]
Output:
[["root/a/2.txt","root/c/d/4.txt","root/4.txt"],["root/a/1.txt","root/c/3.txt"]]
Note:
Solution
05/20/2020:
class Solution {
public:
vector<vector<string>> findDuplicate(vector<string>& paths) {
unordered_map<string, vector<string>> files;
for (auto& p : paths) {
istringstream iss(p);
string base, file_content;
iss >> base;
while (iss >> file_content) {
int i = 0, n = file_content.size();
for (; file_content[i] != '(' && i < n; ++i);
string filename = file_content.substr(0, i);
string content = file_content.substr(i, n - i);
files[content].push_back(base + "/" + filename);
}
}
vector<vector<string>> ret;
for (auto& f : files)
if (f.second.size() > 1)
ret.push_back(f.second);
return ret;
}
};
Given a string s and a list of strings dict, you need to add a closed pair of
bold tag <b> and </b> to wrap the substrings in s that exist in dict. If two
such substrings overlap, you need to wrap them together by only one pair of
closed bold tag. Also, if two substrings wrapped by bold tags are consecutive,
you need to combine them.
Example 1:
Input:
s = "abcxyz123"
dict = ["abc","123"]
Output:
"<b>abc</b>xyz<b>123</b>"
Example 2:
Input:
s = "aaabbcc"
dict = ["aaa","aab","bc"]
Output:
"<b>aaabbc</b>c"
Constraints:
The given dict won't contain duplicates, and its length won't exceed 100.
All the strings in input have length in range [1, 1000].
Note: This question is the same as 758: https://leetcode.com/problems/bold-
words-in-string/
Solution
06/09/2020:
class Solution {
public:
string addBoldTag(string s, vector<string>& dict) {
unordered_set<string> dicts(dict.begin(), dict.end());
vector<int> lengths;
for (auto& d : dict) lengths.push_back(d.size());
sort(lengths.rbegin(), lengths.rend());
int n = s.size();
vector<bool> isBold(n, false);
for (int i = 0; i < n; ++i) {
bool wrap = false;
int wrapLength = 0;
for (auto& len : lengths) {
if (i + len <= n && dicts.count(s.substr(i, len)) > 0) {
wrap = true;
wrapLength = len;
break;
}
}
if (wrap) {
for (int j = i; j < i + wrapLength; ++j)
isBold[j] = true;
}
}
string ret;
int last = 0;
for (int i = 0; i < n;) {
if (isBold[i]) {
while (i + 1 < n && isBold[i + 1]) ++i;
ret += "<b>";
ret += s.substr(last, i - last + 1);
ret += "</b>";
last = ++i;
} else {
ret += s[i];
last = ++i;
}
}
return ret;
}
};
Given a sorted array, two integers k and x, find the k closest elements to x in
the array. The result should also be sorted in ascending order. If there is a
tie, the smaller elements are always preferred.
Example 1:
The value k is positive and will always be smaller than the length of the sorted
array.
Length of the given array is positive and will not exceed 104
Absolute value of elements in the array and x will not exceed 104
Solution
04/28/2020:
class Solution {
public:
vector<int> findClosestElements(vector<int>& arr, int k, int x) {
if (arr.empty()) return {};
int n = arr.size();
int lo = 0, hi = n - 1;
int l, r;
if (x < arr.front()) {
l = 0;
r = 0;
} else if (x > arr.back()) {
l = n - 1;
r = n - 1;
} else {
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
if (arr[mid] == x) {
l = mid;
r = mid;
break;
} else if (arr[mid] > x) {
hi = mid - 1;
r = hi;
} else {
lo = mid + 1;
l = lo;
}
}
if (abs(arr[l] - x) < abs(arr[r] - x)) {
r = l;
} else {
l = r;
}
}
deque<int> q;
if (k-- > 0) {
q.push_front(arr[l]);
l--;
r++;
}
while (k > 0) {
if (l < 0) {
q.push_back(arr[r++]);
} else if (r > n - 1) {
q.push_front(arr[l--]);
} else if (abs(arr[l] - x) <= abs(arr[r] - x)) {
q.push_front(arr[l--]);
} else if (abs(arr[l] - x) > abs(arr[r] - x)) {
q.push_back(arr[r++]);
}
--k;
}
return vector<int>(q.begin(), q.end());
}
};
669. Trim a Binary Search Tree
Description
Given a binary search tree and the lowest and highest boundaries as L and R,
trim the tree so that all its elements lies in [L, R] (R >= L). You might need
to change the root of the tree, so the result should return the new root of the
trimmed binary search tree.
Example 1:
Input:
1
/ \
0 2
L = 1
R = 2
Output:
1
\
2
Example 2:
Input:
3
/ \
0 4
\
2
/
1
L = 1
R = 3
Output:
3
/
2
/
1
Solution
05/10/2020:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* trimBST(TreeNode* root, int L, int R) {
if (root == nullptr) return root;
if (root->val < L) return trimBST(root->right, L, R);
if (root->val > R) return trimBST(root->left, L, R);
root->left = trimBST(root->left, L, R);
root->right = trimBST(root->right, L, R);
return root;
}
};
The given input is a graph that started as a tree with N nodes (with distinct
values 1, 2, ..., N), with one additional edge added. The added edge has two
different vertices chosen from 1 to N, and was not an edge that already existed.
Return an edge that can be removed so that the resulting graph is a tree of N
nodes. If there are multiple answers, return the answer that occurs last in the
given 2D-array. The answer edge [u, v] should be in the same format, with u < v.
Example 1:
Input: [[1,2], [1,3], [2,3]]
Output: [2,3]
Explanation: The given undirected graph will be like this:
1
/ \
2 - 3
Example 2:
Input: [[1,2], [2,3], [3,4], [1,4], [1,5]]
Output: [1,4]
Explanation: The given undirected graph will be like this:
5 - 1 - 2
| |
4 - 3
Note:
The size of the input 2D-array will be between 3 and 1000.
Every integer represented in the 2D-array will be between 1 and N, where N is
the size of the input array.
Solution
06/10/2020:
class UnionFind {
private:
vector<int> id;
vector<int> sz;
public:
UnionFind(int n) {
id.resize(n);
iota(id.begin(), id.end(), 0);
sz.resize(n, 1);
}
int find(int x) {
if (x == id[x]) return x;
return id[x] = find(id[x]);
}
class Solution {
public:
vector<int> findRedundantConnection(vector<vector<int>>& edges) {
int n = edges.size();
UnionFind uf(n + 1);
vector<int> ret;
for (auto& e : edges)
if (uf.connected(e[0], e[1]))
ret = e;
else
uf.merge(e[0], e[1]);
return ret;
}
};
679. 24 Game
Description
You have 4 cards each containing a number from 1 to 9. You need to judge whether
they could operated through *, /, +, -, (, ) to get the value of 24.
Example 1:
Input: [4, 1, 8, 7]
Output: True
Explanation: (8-4) * (7-1) = 24
Example 2:
Input: [1, 2, 1, 2]
Output: False
Note:
The division operator / represents real division, not integer division. For
example, 4 / (1 - 2/3) = 12.
Every operation done is between two numbers. In particular, we cannot use - as a
unary operator. For example, with [1, 1, 1, 1] as input, the expression -1 - 1 -
1 - 1 is not allowed.
You cannot concatenate numbers together. For example, if the input is [1, 2, 1,
2], we cannot write this as 12 + 12.
Solution
06/10/2020:
class Solution {
public:
bool judgePoint24(vector<int>& nums) {
unordered_set<string> seen;
string operators = "+-*/";
sort(nums.begin(), nums.end());
do {
int a = nums[0], b = nums[1], c = nums[2], d = nums[3];
string key = to_string(a) + "," + to_string(b) + "," + to_string(c) + ","
+ to_string(d);
if (seen.count(key) > 0) continue;
seen.insert(key);
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
for (int k = 0; k < 4; ++k) {
vector<double> results;
results.push_back(op(op(op(a, b, operators[i]), c, operators[j]), d,
operators[k]));
results.push_back(op(op(a, b, operators[i]), op(c, d, operators[k]),
operators[j]));
results.push_back(op(op(a, op(b, c, operators[j]), operators[i]), d,
operators[k]));
results.push_back(op(a, op(op(b, c, operators[j]), d, operators[k]),
operators[i]));
results.push_back(op(a, op(b, op(c, d, operators[k]),
operators[j]),operators[i]));
for (auto& r : results)
if (fabs(r - 24) < 1e-6)
return true;
}
}
}
} while (next_permutation(nums.begin(), nums.end()));
return false;
}
Given a positive integer, check whether it has alternating bits: namely, if two
adjacent bits will always have different values.
Example 1:
Input: 5
Output: True
Explanation:
The binary representation of 5 is: 101
Example 2:
Input: 7
Output: False
Explanation:
The binary representation of 7 is: 111.
Example 3:
Input: 11
Output: False
Explanation:
The binary representation of 11 is: 1011.
Example 4:
Input: 10
Output: True
Explanation:
The binary representation of 10 is: 1010.
Solution
05/10/2020:
class Solution {
public:
bool hasAlternatingBits(int n) {
int cnt = n & 1 ? 1 : 0;
while (n != 0) {
n >>= 1;
if (n & 1) {
++cnt;
} else {
--cnt;
}
if (cnt < 0 || cnt > 1) return false;
}
return true;
}
};
Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's
(representing land) connected 4-directionally (horizontal or vertical.) You may
assume all four edges of the grid are surrounded by water.
Example 1:
11000
11000
00011
00011
Given the above grid map, return 1.
Example 2:
11011
10000
00001
11011
Given the above grid map, return 3.
Notice that:
11
1
and
1
11
are considered different island shapes, because we do not consider reflection /
rotation.
Note: The length of each dimension in the given grid does not exceed 50.
Solution
05/08/2020 Discussion:
class UnionFind {
private:
vector<int> id;
vector<int> sz;
public:
UnionFind(int n) {
id.resize(n);
iota(id.begin(), id.end(), 0);
sz.resize(n, 1);
}
int find(int x) {
while (x != id[x]) {
id[x] = id[id[x]];
x = id[x];
}
return x;
}
class Solution {
public:
int numDistinctIslands(vector<vector<int>>& grid) {
if (grid.empty() || grid[0].empty()) return 0;
int m = grid.size(), n = grid[0].size();
unordered_set<int> islands;
for (auto& c : components) {
sort(c.second.begin(), c.second.end());
int mini = c.second.front() / n, minj = n;
for (auto& i : c.second) minj = min(minj, i % n);
int offset = mini * n + minj;
long long hash = 1;
const int MOD = 1e9 + 7;
for (auto& i : c.second) hash = (hash * 31 + i - offset) % MOD;
islands.insert(hash);
}
return islands.size();
}
};
class UnionFind {
private:
vector<int> id;
vector<int> sz;
public:
UnionFind(int n) {
id.resize(n);
iota(id.begin(), id.end(), 0);
sz.resize(n, 1);
}
int find(int x) {
if (x == id[x]) return x;
return id[x] = find(id[x]);
}
class Solution {
private:
int m, n;
public:
int numDistinctIslands(vector<vector<int>>& grid) {
if (grid.empty() || grid[0].empty()) return 0;
m = grid.size(), n = grid[0].size();
UnionFind uf(m * n);
int dir[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (grid[i][j] == 0) continue;
int island = i * n + j;
for (int d = 0; d < 4; ++d) {
int ni = i + dir[d][0], nj = j + dir[d][1], neighbor = ni * n + nj;
if (ni >= 0 && ni < m && nj >= 0 && nj < n && grid[ni][nj] == 1) {
uf.merge(island, neighbor);
}
}
}
}
unordered_set<int> seen;
int cnt = 0;
for (auto& c : components) {
vector<int> hashes = hash(c.second);
bool exists = false;
for (auto& h : hashes) {
if (seen.count(h)) {
exists = true;
break;
}
}
for (auto& h : hashes) seen.insert(h);
if (!exists) ++cnt;
}
return cnt;
}
Given the root node of a binary search tree (BST) and a value. You need to find
the node in the BST that the node's value equals the given value. Return the
subtree rooted with that node. If such node doesn't exist, you should return
NULL.
For example,
2
/ \
1 3
In the example above, if we want to search the value 5, since there is no node
with value 5, we should return NULL.
Note that an empty tree is represented by NULL, therefore you would see the
expected output (serialized tree format) as [], not null.
Solution
06/15/2020:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left),
right(right) {}
* };
*/
class Solution {
public:
TreeNode* searchBST(TreeNode* root, int val) {
if (!root) return nullptr;
if (root->val == val) return root;
if (root->val > val) return searchBST(root->left, val);
if (root->val < val) return searchBST(root->right, val);
return nullptr;
}
};
702. Search in a Sorted Array of Unknown Size
Description
You may assume all integers in the array are less than 10000, and if you access
the array out of bounds, ArrayReader.get will return 2147483647.
Example 1:
Note:
You may assume that all elements in the array are unique.
The value of each element in the array will be in the range [-9999, 9999].
Solution
04/26/2020:
/**
* // This is the ArrayReader's API interface.
* // You should not implement it, or speculate about its implementation
* class ArrayReader {
* public:
* int get(int index);
* };
*/
class Solution {
public:
int search(const ArrayReader& reader, int target) {
int lo = 0, hi = INT_MAX;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
int val = reader.get(mid);
if (val == target) {
return mid;
} else if (val == INT_MAX || val > target) {
hi = mid - 1;
} else {
lo = mid + 1;
}
}
return -1;
}
};
Example:
Note:
Solution
05/10/2020:
struct Node {
int key;
Node* next;
Node (int k) : key(k), next(nullptr) {}
};
class MyHashSet {
private:
vector<Node*> hashset;
int N;
public:
/** Initialize your data structure here. */
MyHashSet() {
N = 100003;
hashset.resize(N, nullptr);
}
/**
* Your MyHashSet object will be instantiated and called as such:
* MyHashSet* obj = new MyHashSet();
* obj->add(key);
* obj->remove(key);
* bool param_3 = obj->contains(key);
*/
put(key, value) : Insert a (key, value) pair into the HashMap. If the value
already exists in the HashMap, update the value.
get(key): Returns the value to which the specified key is mapped, or -1 if this
map contains no mapping for the key.
remove(key) : Remove the mapping for the value key if this map contains the
mapping for the key.
Example:
Note:
Solution
05/10/2020:
struct Node {
int key, val;
Node* next;
Node (int k, int v) : key(k), val(v), next(nullptr) {}
};
class MyHashMap {
private:
vector<Node*> hashmap;
int N, n;
public:
/** Initialize your data structure here. */
MyHashMap() {
N = 100003;
n = 0;
hashmap.resize(N, nullptr);
}
/** Returns the value to which the specified key is mapped, or -1 if this map
contains no mapping for the key */
int get(int key) {
Node* cur = hashmap[key % N];
if (cur == nullptr) {
return -1;
} else if (cur->key == key) {
return cur->val;
} else {
while (cur->key != key && cur->next != nullptr) {
cur = cur->next;
}
return cur->key == key ? cur->val : -1;
}
}
/** Removes the mapping of the specified value key if this map contains a
mapping for the key */
void remove(int key) {
Node* cur = hashmap[key % N];
if (cur == nullptr) return;
if (cur->key == key) {
hashmap[key % N] = cur->next;
} else {
while (cur->next != nullptr && cur->next->key != key) {
cur = cur->next;
}
if (cur->next != nullptr && cur->next->key == key) {
cur->next = cur->next->next;
}
}
}
};
/**
* Your MyHashMap object will be instantiated and called as such:
* MyHashMap* obj = new MyHashMap();
* obj->put(key,value);
* int param_2 = obj->get(key);
* obj->remove(key);
*/
711. Number of Distinct Islands II
Description
Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's
(representing land) connected 4-directionally (horizontal or vertical.) You may
assume all four edges of the grid are surrounded by water.
Example 1:
11000
10000
00001
00011
Given the above grid map, return 1.
Notice that:
11
1
and
1
11
are considered same island shapes. Because if we make a 180 degrees clockwise
rotation on the first island, then two islands will have the same shapes.
Example 2:
11100
10001
01001
01110
Given the above grid map, return 2.
Notice that:
111
1
and
1
111
are considered same island shapes. Because if we flip the first array in the
up/down direction, then they have the same shapes.
Note: The length of each dimension in the given grid does not exceed 50.
Solution
05/08/2020 Discussion:
class UnionFind {
private:
vector<int> id;
vector<int> sz;
public:
UnionFind(int n) {
id.resize(n);
iota(id.begin(), id.end(), 0);
sz.resize(n, 1);
}
int find(int x) {
if (x == id[x]) return x;
return id[x] = find(id[x]);
}
class Solution {
private:
int m, n;
public:
int numDistinctIslands2(vector<vector<int>>& grid) {
if (grid.empty() || grid[0].empty()) return 0;
m = grid.size(), n = grid[0].size();
UnionFind uf(m * n);
int dir[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (grid[i][j] == 0) continue;
int island = i * n + j;
for (int d = 0; d < 4; ++d) {
int ni = i + dir[d][0], nj = j + dir[d][1], neighbor = ni * n + nj;
if (ni >= 0 && ni < m && nj >= 0 && nj < n && grid[ni][nj] == 1) {
uf.merge(island, neighbor);
}
}
}
}
unordered_set<int> seen;
int cnt = 0;
for (auto& c : components) {
vector<int> hashes = hash(c.second);
bool exists = false;
for (auto& h : hashes) {
if (seen.count(h)) {
exists = true;
break;
}
}
for (auto& h : hashes) seen.insert(h);
if (!exists) ++cnt;
}
return cnt;
}
We have two special characters. The first character can be represented by one
bit 0. The second character can be represented by two bits (10 or 11).
Now given a string represented by several bits. Return whether the last
character must be a one-bit character or not. The given string will always end
with a zero.
Example 1:
Input:
bits = [1, 0, 0]
Output: True
Explanation:
The only way to decode it is two-bit character and one-bit character. So the
last character is one-bit character.
Example 2:
Input:
bits = [1, 1, 1, 0]
Output: False
Explanation:
The only way to decode it is two-bit character and two-bit character. So the
last character is NOT one-bit character.
Note:
Solution
06/09/2020:
class Solution {
public:
bool isOneBitCharacter(vector<int>& bits) {
int i = 0, n = bits.size();
for (; i < n - 1; ++i) {
if (bits[i] == 1) {
++i;
}
}
return i == n - 1;
}
};
All the strings in the input will only contain lowercase letters.
The length of words will be in the range [1, 1000].
The length of words[i] will be in the range [1, 30].
Solution
05/18/2020:
class Solution {
public:
string longestWord(vector<string>& words) {
unordered_set<string> s(words.begin(), words.end());
sort(words.begin(), words.end(), [](const string& s1, const string& s2) {
if (s1.size() == s2.size()) {
return s1 < s2;
}
return s1.size() > s2.size();
});
for (auto& w : words) {
bool ok = true;
for (int i = 1; i < (int)w.size(); ++i) {
if (s.count(w.substr(0, i)) == 0) {
ok = false;
break;
}
}
if (ok) return w;
}
return "";
}
};
Now, we would like to merge these accounts. Two accounts definitely belong to
the same person if there is some email that is common to both accounts. Note
that even if two accounts have the same name, they may belong to different
people as people could have the same name. A person can have any number of
accounts initially, but all of their accounts definitely have the same name.
After merging the accounts, return the accounts in the following format: the
first element of each account is the name, and the rest of the elements are
emails in sorted order. The accounts themselves can be returned in any order.
Example 1:
Input:
accounts = [["John", "johnsmith@mail.com", "john00@mail.com"], ["John",
"johnnybravo@mail.com"], ["John", "johnsmith@mail.com",
"john_newyork@mail.com"], ["Mary", "mary@mail.com"]]
Output: [["John", 'john00@mail.com', 'john_newyork@mail.com',
'johnsmith@mail.com'], ["John", "johnnybravo@mail.com"], ["Mary",
"mary@mail.com"]]
Explanation:
The first and third John's are the same person as they have the common email
"johnsmith@mail.com".
The second John and Mary are different people as none of their email addresses
are used by other accounts.
We could return these lists in any order, for example the answer [['Mary',
'mary@mail.com'], ['John', 'johnnybravo@mail.com'],
['John', 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com']]
would still be accepted.
Note:
Solution
06/10/2020:
Define UnionFind:
class UnionFind {
private:
vector<int> id;
vector<int> sz;
public:
UnionFind(int n) {
id.resize(n);
iota(id.begin(), id.end(), 0);
sz.resize(n, 1);
}
int find(int x) {
if (x == id[x]) return x;
return id[x] = find(id[x]);
}
class Solution {
public:
vector<vector<string>> accountsMerge(vector<vector<string>>& accounts) {
int id = 0;
UnionFind uf(10000);
unordered_map<string, string> email_user;
unordered_map<string, int> email_id;
unordered_map<int, string> id_email;
for (auto& emails : accounts) {
for (int i = 1; i < (int)emails.size(); ++i) {
email_user[emails[i]] = emails[0];
if (email_id.count(emails[i]) == 0) {
email_id[emails[i]] = id++;
id_email[id - 1] = emails[i];
}
if (i > 1) uf.merge(email_id[emails[i - 1]], email_id[emails[i]]);
}
}
unordered_map<int, vector<int>> connected_components;
for (int i = 0; i < id; ++i) connected_components[uf.find(i)].push_back(i);
vector<vector<string>> ret;
for (auto& c : connected_components) {
vector<string> account;
account.push_back(email_user[id_email[c.first]]);
for (auto& i : c.second) account.push_back(id_email[i]);
sort(account.begin() + 1, account.end());
ret.push_back(account);
}
return ret;
}
};
class Solution {
public:
vector<vector<string>> accountsMerge(vector<vector<string>>& accounts) {
int n = accounts.size();
UnionFind uf(n);
for (int i = 0; i < n; ++i) {
unordered_set<string> accounts_set(accounts[i].begin() + 1,
accounts[i].end());
for (int j = i + 1; j < n; ++j)
if (accounts[i][0] == accounts[j][0])
for (int k = 1; !uf.connected(i, j) && k < (int)accounts[j].size();
++k)
if (accounts_set.count(accounts[j][k]) > 0)
uf.merge(i, j);
}
vector<vector<string>> ret;
for (auto& c : connected_components) {
unordered_set<string> acct;
for (auto i : c.second)
for (int j = 1; j < (int)accounts[i].size(); ++j)
acct.insert(accounts[i][j]);
vector<string> sorted_acct(acct.begin(), acct.end());
sort(sorted_acct.rbegin(), sorted_acct.rend());
sorted_acct.push_back(accounts[c.first][0]);
reverse(sorted_acct.begin(), sorted_acct.end());
ret.push_back(sorted_acct);
}
return ret;
}
};
Given a coordinate (sr, sc) representing the starting pixel (row and column) of
the flood fill, and a pixel value newColor, "flood fill" the image.
To perform a "flood fill", consider the starting pixel, plus any pixels
connected 4-directionally to the starting pixel of the same color as the
starting pixel, plus any pixels connected 4-directionally to those pixels (also
with the same color as the starting pixel), and so on. Replace the color of all
of the aforementioned pixels with the newColor.
Example 1:
Input:
image = [[1,1,1],[1,1,0],[1,0,1]]
sr = 1, sc = 1, newColor = 2
Output: [[2,2,2],[2,2,0],[2,0,1]]
Explanation:
From the center of the image (with position (sr, sc) = (1, 1)), all pixels
connected
by a path of the same color as the starting pixel are colored with the new
color.
Note the bottom corner is not colored 2, because it is not 4-directionally
connected
to the starting pixel.
Note:
The length of image and image[0] will be in the range [1, 50].
The given starting pixel will satisfy 0 <= sr < image.length and 0 <= sc <
image[0].length.
The value of each color in image[i][j] and newColor will be an integer in [0,
65535].
Solution
05/11/2020:
class Solution {
public:
vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int
newColor) {
if (image.empty() || image[0].empty()) return image;
if (image[sr][sc] == newColor) return image;
int m = image.size(), n = image[0].size();
int oldColor = image[sr][sc];
image[sr][sc] = newColor;
queue<pair<int, int>> q;
q.emplace(sr, sc);
int dir[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
while (!q.empty()) {
int sz = q.size();
for (int s = 0; s < sz; ++s) {
pair<int, int> cur = q.front(); q.pop();
int i = cur.first, j = cur.second;
for (int d = 0; d < 4; ++d) {
int ni = i + dir[d][0], nj = j + dir[d][1];
if (ni >= 0 && ni < m && nj >= 0 && nj < n && image[ni][nj] ==
oldColor) {
image[ni][nj] = newColor;
q.emplace(ni, nj);
}
}
}
}
return image;
}
};
For example, "great acting skills" and "fine drama talent" are similar, if the
similar word pairs are pairs = [["great", "fine"], ["acting","drama"],
["skills","talent"]].
Note that the similarity relation is not transitive. For example, if "great" and
"fine" are similar, and "fine" and "good" are similar, "great" and "good" are
not necessarily similar.
However, similarity is symmetric. For example, "great" and "fine" being similar
is the same as "fine" and "great" being similar.
Also, a word is always similar with itself. For example, the sentences words1 =
["great"], words2 = ["great"], pairs = [] are similar, even though there are no
specified similar word pairs.
Finally, sentences can only be similar if they have the same number of words. So
a sentence like words1 = ["great"] can never be similar to words2 =
["doubleplus","good"].
Note:
Solution
06/10/2020:
class Solution {
public:
bool areSentencesSimilar(vector<string>& words1, vector<string>& words2,
vector<vector<string>>& pairs) {
if (words1.size() != words2.size()) return false;
bool isSimilar = true;
unordered_map<string, unordered_set<string>> similarWords;
for (auto& p : pairs) {
similarWords[p[0]].insert(p[1]);
similarWords[p[1]].insert(p[0]);
}
for (int i = 0; i < words1.size(); ++i)
if (words1[i] != words2[i])
if (similarWords[words1[i]].count(words2[i]) == 0 &&
similarWords[words2[i]].count(words1[i]) == 0)
return false;
return true;
}
};
05/20/2020:
class Solution {
public:
bool areSentencesSimilar(vector<string>& words1, vector<string>& words2,
vector<vector<string>>& pairs) {
if (words1.empty() && words2.empty()) return true;
if (words1.size() != words2.size()) return false;
unordered_map<string, unordered_set<string>> similarWords;
for (auto& p : pairs) {
if (p.empty()) continue;
similarWords[p[0]].insert(p[1]);
similarWords[p[1]].insert(p[0]);
}
int n = words1.size();
for (int i = 0; i < n; ++i) {
bool isSimilar = false;
if (words1[i] == words2[i]) {
isSimilar = true;
} else {
if (similarWords[words1[i]].count(words2[i]) > 0)
isSimilar = true;
}
if (isSimilar == false) return false;
}
return true;
}
};
Note that the similarity relation is transitive. For example, if "great" and
"good" are similar, and "fine" and "good" are similar, then "great" and "fine"
are similar.
Similarity is also symmetric. For example, "great" and "fine" being similar is
the same as "fine" and "great" being similar.
Also, a word is always similar with itself. For example, the sentences words1 =
["great"], words2 = ["great"], pairs = [] are similar, even though there are no
specified similar word pairs.
Finally, sentences can only be similar if they have the same number of words. So
a sentence like words1 = ["great"] can never be similar to words2 =
["doubleplus","good"].
Note:
Solution
06/10/2020:
class UnionFind {
private:
vector<int> id;
vector<int> sz;
public:
UnionFind(int n) {
id.resize(n);
iota(id.begin(), id.end(), 0);
sz.resize(n, 1);
}
int find(int x) {
if (x == id[x]) return x;
return id[x] = find(id[x]);
}
class Solution {
public:
bool areSentencesSimilarTwo(vector<string>& words1, vector<string>& words2,
vector<vector<string>>& pairs) {
if (words1.size() != words2.size()) return false;
UnionFind uf(6000);
unordered_map<string, int> word_id;
int id = 0;
for (auto& w : words1) assign_id(w, id, word_id);
for (auto& w : words2) assign_id(w, id, word_id);
for (auto& p : pairs) {
assign_id(p[0], id, word_id);
assign_id(p[1], id, word_id);
uf.merge(word_id[p[0]], word_id[p[1]]);
}
for (int i = 0; i < (int)words1.size(); ++i)
if (words1[i] != words2[i] && !uf.connected(word_id[words1[i]],
word_id[words2[i]]))
return false;
return true;
}
Find the minimum length word from a given dictionary words, which has all the
letters from the string licensePlate. Such a word is said to complete the given
string licensePlate
Here, for letters we ignore case. For example, "P" on the licensePlate still
matches "p" on the word.
It is guaranteed an answer exists. If there are multiple answers, return the one
that occurs first in the array.
The license plate might have the same letter occurring multiple times. For
example, given a licensePlate of "PP", the word "pair" does not complete the
licensePlate, but the word "supper" does.
Example 1:
Input: licensePlate = "1s3 PSt", words = ["step", "steps", "stripe", "stepple"]
Output: "steps"
Explanation: The smallest length word that contains the letters "S", "P", "S",
and "T".
Note that the answer is not "step", because the letter "s" must occur in the
word twice.
Also note that we ignored case for the purposes of comparing whether a letter
exists in the word.
Example 2:
Input: licensePlate = "1s3 456", words = ["looks", "pest", "stew", "show"]
Output: "pest"
Explanation: There are 3 smallest length words that contains the letters "s".
We return the one that occurred first.
Note:
licensePlate will be a string with length in range [1, 7].
licensePlate will contain digits, spaces, or letters (uppercase or lowercase).
words will have a length in the range [10, 1000].
Every words[i] will consist of lowercase letters, and have length in range [1,
15].
Solution
05/17/2020:
class Solution {
public:
string shortestCompletingWord(string licensePlate, vector<string>& words) {
vector<int> trimmedLicensePlate(26, 0);
for (auto& l : licensePlate) {
if (isalpha(l)) {
++trimmedLicensePlate[tolower(l) - 'a'];
}
}
vector<pair<string, int>> validWords;
for (int k = 0; k < (int)words.size(); ++k) {
string w = words[k];
vector<int> cnt(26, 0);
for (auto& c : w) {
++cnt[c - 'a'];
}
bool isComplete = true;
for (int i = 0; i < 26; ++i) {
if (cnt[i] < trimmedLicensePlate[i]) {
isComplete = false;
break;
}
}
if (isComplete) validWords.emplace_back(w, k);
}
sort(validWords.begin(), validWords.end(), [](pair<string, int>& p1,
pair<string, int>& p2) {
if (p1.first.size() == p2.first.size()) {
return p1.second < p2.second;
}
return p1.first.size() < p2.first.size();
});
return validWords.front().first;
}
};
Given a set of keywords words and a string S, make all appearances of all
keywords in S bold. Any letters between <b> and </b> tags become bold.
The returned string should use the least number of tags possible, and of course
the tags should form a valid combination.
For example, given that words = ["ab", "bc"] and S = "aabcd", we should return
"a<b>abc</b>d". Note that returning "a<b>a<b>b</b>c</b>d" would use more tags,
so it is incorrect.
Constraints:
Solution
06/09/2020:
class Solution {
public:
string boldWords(vector<string>& dict, string s) {
unordered_set<string> dicts(dict.begin(), dict.end());
vector<int> lengths;
for (auto& d : dict) lengths.push_back(d.size());
sort(lengths.rbegin(), lengths.rend());
int n = s.size();
vector<bool> isBold(n, false);
for (int i = 0; i < n; ++i) {
bool wrap = false;
int wrapLength = 0;
for (auto& len : lengths) {
if (i + len <= n && dicts.count(s.substr(i, len)) > 0) {
wrap = true;
wrapLength = len;
break;
}
}
if (wrap) {
for (int j = i; j < i + wrapLength; ++j)
isBold[j] = true;
}
}
string ret;
int last = 0;
for (int i = 0; i < n;) {
if (isBold[i]) {
while (i + 1 < n && isBold[i + 1]) ++i;
ret += "<b>";
ret += s.substr(last, i - last + 1);
ret += "</b>";
last = ++i;
} else {
ret += s[i];
last = ++i;
}
}
return ret;
}
};
773. Sliding Puzzle
Description
On a 2x3 board, there are 5 tiles represented by the integers 1 through 5, and
an empty square represented by 0.
The state of the board is solved if and only if the board is [[1,2,3],[4,5,0]].
Given a puzzle board, return the least number of moves required so that the
state of the board is solved. If it is impossible for the state of the board to
be solved, return -1.
Examples:
Solution
05/08/2020 Discussion:
This is the C++ version solution for one of the assignments of the course Algorithms (Part 1):
class Board {
public:
vector<vector<int>> board;
pair<int, int> zeroTile;
int rows, cols, manhattanDist, moves, priority;
int manhattan() {
int d = 0;
for (int i = 0; i < rows; ++i)
for (int j = 0; j < cols; ++j)
if (board[i][j] != 0)
d += abs((board[i][j] - 1) / cols - i) + abs((board[i][j] - 1) % cols
- j);
return d;
}
vector<Board> neighbor() {
int dir[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
int i = zeroTile.first, j = zeroTile.second;
vector<Board> neighborBoards;
for (int d = 0; d < 4; ++d) {
int ni = dir[d][0] + i, nj = dir[d][1] + j;
vector<vector<int>> newBoard(board);
if (ni >= 0 && ni < rows && nj >= 0 && nj < cols) {
swap(newBoard[i][j], newBoard[ni][nj]);
neighborBoards.push_back(Board(newBoard));
neighborBoards.back().updateMoves(moves + 1);
}
}
return neighborBoards;
}
Board twin () {
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols - 1; ++j) {
if (board[i][j] != 0 && board[i][j + 1] != 0) {
vector<vector<int>> twinBoard(board);
swap(twinBoard[i][j], twinBoard[i][j + 1]);
return Board(twinBoard);
}
}
}
return Board(board);
}
};
class Solution {
public:
int slidingPuzzle(vector<vector<int>>& board) {
priority_queue<pair<Board, Board>, vector<pair<Board, Board>>,
greater<pair<Board, Board>>> pq, pqTwin;
Board initialBoard(board), twinBoard = initialBoard.twin();
pq.emplace(initialBoard, initialBoard);
pqTwin.emplace(twinBoard, twinBoard);
while (!pq.empty() && pq.top().first.manhattanDist > 0 && !pqTwin.empty() &&
pqTwin.top().first.manhattanDist > 0) {
pair<Board, Board> cur = pq.top(); pq.pop();
for(auto& p : cur.first.neighbor())
if (p != cur.second) pq.emplace(p, cur.first);
cur = pqTwin.top(); pqTwin.pop();
for(auto& p : cur.first.neighbor())
if (p != cur.second) pqTwin.emplace(p, cur.first);
}
return pqTwin.top().first.manhattanDist == 0 ? -1 : pq.top().first.moves;
}
};
There are n cities connected by m flights. Each flight starts from city u and
arrives at v with a price w.
Now given all the cities and flights, together with starting city src and the
destination dst, your task is to find the cheapest price from src to dst with up
to k stops. If there is no such route, output -1.
Example 1:
Input:
n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]]
src = 0, dst = 2, k = 1
Output: 200
Explanation:
The graph looks like this:
The cheapest price from city 0 to city 2 with at most 1 stop costs 200, as
marked red in the picture.
Example 2:
Input:
n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]]
src = 0, dst = 2, k = 0
Output: 500
Explanation:
The graph looks like this:
The cheapest price from city 0 to city 2 with at most 0 stop costs 500, as
marked blue in the picture.
Constraints:
The number of nodes n will be in range [1, 100], with nodes labeled from 0 to n
- 1.
The size of flights will be in range [0, n * (n - 1) / 2].
The format of each flight will be (src, dst, price).
The price of each flight will be in the range [1, 10000].
k is in the range of [0, n - 1].
There will not be any duplicated flights or self cycles.
Solution
06/14/2020:
Given a paragraph and a list of banned words, return the most frequent word that
is not in the list of banned words. It is guaranteed there is at least one word
that isn't banned, and that the answer is unique.
Words in the list of banned words are given in lowercase, and free of
punctuation. Words in the paragraph are not case sensitive. The answer is in
lowercase.
Example:
Input:
paragraph = "Bob hit a ball, the hit BALL flew far after it was hit."
banned = ["hit"]
Output: "ball"
Explanation:
"hit" occurs 3 times, but it is a banned word.
"ball" occurs twice (and no other word does), so it is the most frequent non-
banned word in the paragraph.
Note that words in the paragraph are not case sensitive,
that punctuation is ignored (even if adjacent to words, such as "ball,"),
and that "hit" isn't the answer even though it occurs more because it is banned.
Note:
Solution
05/10/2020:
class Solution {
public:
string mostCommonWord(string paragraph, vector<string>& banned) {
for (auto& c : paragraph) c = isalpha(c) ? tolower(c) : ' ';
unordered_set<string> b(banned.begin(), banned.end());
unordered_map<string, int> mp;
string ret, s;
int freq = 0;
istringstream iss(paragraph);
while (iss >> s) {
if (b.count(s) == 0 && ++mp[s] > freq) {
freq = mp[s];
ret = s;
}
}
return ret;
}
};
844. Backspace String Compare
Description
Given two strings S and T, return if they are equal when both are typed into
empty text editors. # means a backspace character.
Example 1:
Solution
02/05/2020:
class Solution {
public:
bool backspaceCompare(string S, string T) {
string s, t;
for (auto& c : S) {
if (c == '#') {
if (!s.empty()) {
s.pop_back();
}
} else {
s.push_back(c);
}
}
for (auto& c : T) {
if (c == '#') {
if (!t.empty()) {
t.pop_back();
}
} else {
t.push_back(c);
}
}
return s == t;
}
};
Given a positive integer N, find and return the longest distance between two
consecutive 1's in the binary representation of N.
Example 1:
Input: 22
Output: 2
Explanation:
22 in binary is 0b10110.
In the binary representation of 22, there are three ones, and two consecutive
pairs of 1's.
The first consecutive pair of 1's have distance 2.
The second consecutive pair of 1's have distance 1.
The answer is the largest of these two distances, which is 2.
Example 2:
Input: 5
Output: 2
Explanation:
5 in binary is 0b101.
Example 3:
Input: 6
Output: 1
Explanation:
6 in binary is 0b110.
Example 4:
Input: 8
Output: 0
Explanation:
8 in binary is 0b1000.
There aren't any consecutive pairs of 1's in the binary representation of 8, so
we return 0.
Note:
Solution
05/10/2020:
class Solution {
public:
int binaryGap(int N) {
if (N == 0) return 0;
int ret = INT_MIN;
while ((N & 1) == 0) {
N >>= 1;
}
int cnt = 0;
while (N != 0) {
N >>= 1;
if ((N & 1) == 1) {
ret = max(ret, cnt);
cnt = 0;
} else {
++cnt;
}
}
return ret == INT_MIN ? 0 : ret + 1;
}
};
917. Reverse Only Letters
Description
Given a string S, return the "reversed" string where all characters that are not
a letter stay in the same place, and all letters reverse their positions.
Example 1:
Input: "ab-cd"
Output: "dc-ba"
Example 2:
Input: "a-bC-dEf-ghIj"
Output: "j-Ih-gfE-dCba"
Example 3:
Input: "Test1ng-Leet=code-Q!"
Output: "Qedo1ct-eeLg=ntse-T!"
Note:
Solution
05/11/2020:
class Solution {
public:
string reverseOnlyLetters(string S) {
int n = S.size(), l = 0, r = n - 1;
while (l < r) {
if (isalpha(S[l]) && isalpha(S[r])) {
swap(S[l++], S[r--]);
} else if (!isalpha(S[l])) {
++l;
} else { // if (!isalpha(S[r]))
--r;
}
}
return S;
}
};
class Solution {
public:
string reverseOnlyLetters(string S) {
int n = S.size(), l = 0, r = n - 1;
string ret(S);
while (l < n && r >= 0) {
for (; l < n && !isalpha(ret[l]); ++l);
for (; r >= 0 && !isalpha(S[r]); --r);
if (l < n && r >= 0) ret[l++] = S[r--];
}
return ret;
}
};
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:
Note:
Solution
05/28/2020:
class Solution {
public:
vector<vector<int>> kClosest(vector<vector<int>>& points, int K) {
priority_queue<pair<double, vector<int>>, vector<pair<double, vector<int>>>,
greater<pair<double, vector<int>>>> q;
for (auto& p : points) q.push({hypot(p[0], p[1]), p});
vector<vector<int>> ret;
while (K-- > 0) {
pair<double, vector<int>> cur = q.top(); q.pop();
ret.push_back(cur.second);
}
return ret;
}
};
Given two lists of closed intervals, each list of intervals is pairwise disjoint
and in sorted order.
(Formally, a closed interval [a, b] (with a <= b) denotes the set of real
numbers x with a <= x <= b. The intersection of two closed intervals is a set
of real numbers that is either empty, or can be represented as a closed
interval. For example, the intersection of [1, 3] and [2, 4] is [2, 3].)
Example 1:
Input: A = [[0,2],[5,10],[13,23],[24,25]], B = [[1,5],[8,12],[15,24],[25,26]]
Output: [[1,2],[5,5],[8,10],[15,23],[24,24],[25,25]]
Reminder: The inputs and the desired output are lists of Interval objects, and
not arrays or lists.
Note:
Solution
05/23/2020:
class Solution {
public:
vector<vector<int>> intervalIntersection(vector<vector<int>>& A,
vector<vector<int>>& B) {
auto ia = A.begin();
auto ib = B.begin();
vector<vector<int>> ret;
for (; ia != A.end() && ib != B.end();) {
if ((*ia)[1] <= (*ib)[1]) {
if ((*ib)[0] <= (*ia)[1]) {
ret.push_back({max((*ia)[0], (*ib)[0]), (*ia)[1]});
}
++ia;
} else {
if ((*ib)[1] >= (*ia)[0]) {
ret.push_back({max((*ia)[0], (*ib)[0]), (*ib)[1]});
}
++ib;
}
}
return ret;
}
};
988. Smallest String Starting From Leaf
Description
Given the root of a binary tree, each node has a value from 0 to 25 representing
the letters 'a' to 'z': a value of 0 represents 'a', a value of 1 represents
'b', and so on.
Find the lexicographically smallest string that starts at a leaf of this tree
and ends at the root.
Example 1:
Input: [0,1,2,3,4,3,4]
Output: "dba"
Example 2:
Input: [25,1,3,1,3,0,2]
Output: "adz"
Example 3:
Input: [2,2,1,null,1,0,null,0]
Output: "abc"
Note:
The number of nodes in the given tree will be between 1 and 8500.
Each node in the tree will have a value between 0 and 25.
Solution
06/15/2020:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left),
right(right) {}
* };
*/
class Solution {
public:
string smallestFromLeaf(TreeNode* root) {
if (!root) return "";
string ret(8500, 'z'), s;
backtrack(s, ret, root);
return ret;
}
In a town, there are N people labelled from 1 to N. There is a rumor that one
of these people is secretly the town judge.
Example 1:
Note:
Solution
05/10/2020:
class Solution {
public:
int findJudge(int N, vector<vector<int>>& trust) {
if (N == 1 && trust.empty()) return 1;
if (trust.empty() || trust[0].empty()) return -1;
unordered_map<int, vector<int>> r;
unordered_set<int> truster;
for (auto& t : trust) {
r[t[1]].push_back(t[0]);
truster.insert(t[0]);
}
int judge = -1;
int cnt = 0;
for (auto& s : r) {
if ((int)s.second.size() == N - 1 && truster.count(s.first) == 0) {
++cnt;
judge = s.first;
}
}
return cnt == 1 ? judge : -1;
}
};
There are 2N people a company is planning to interview. The cost of flying the
i-th person to city A is costs[i][0], and the cost of flying the i-th person to
city B is costs[i][1].
Return the minimum cost to fly every person to a city such that exactly N people
arrive in each city.
Example 1:
Input: [[10,20],[30,200],[400,50],[30,20]]
Output: 110
Explanation:
The first person goes to city A for a cost of 10.
The second person goes to city A for a cost of 30.
The third person goes to city B for a cost of 50.
The fourth person goes to city B for a cost of 20.
Note:
06/03/2020:
Backtracking (TLE):
class Solution {
public:
int ret, numOfCityA;
int twoCitySchedCost(vector<vector<int>>& costs) {
int n = costs.size(), totalCost = 0;
ret = INT_MAX, numOfCityA = 0;
backtrack(0, n, numOfCityA, totalCost, costs);
return ret;
}
Dynamic Programming:
class Solution {
public:
int twoCitySchedCost(vector<vector<int>>& costs) {
int n = costs.size() / 2;
vector<vector<int>> dp(2 * n + 1, vector<int>(n + 1, INT_MAX));
dp[0][0] = 0;
// dp[i][j]: the total cost among costs[0..i - 1]: pick j to city A.
// dp[i][j] = min(dp[i - 1][j - 1] + costs[i - 1][0], dp[i - 1][j] + costs[i
- 1][1])
for (int i = 1; i <= 2 * n; ++i) {
for (int j = 0; j <= i && j <= n; ++j) {
if (i - j > n) continue;
if (dp[i - 1][j] != INT_MAX) {
dp[i][j] = min(dp[i][j], dp[i - 1][j] + costs[i - 1][1]);
}
if (j > 0 && dp[i - 1][j - 1] != INT_MAX) {
dp[i][j] = min(dp[i][j], dp[i - 1][j - 1] + costs[i - 1][0]);
}
}
}
return dp[2 * n][n];
}
};
Greedy:
class Solution {
public:
int twoCitySchedCost(vector<vector<int>>& costs) {
sort(costs.begin(), costs.end(), [](vector<int>& nums1, vector<int>& nums2)
{
return nums1[0] - nums1[1] < nums2[0] - nums2[1];
});
int n = costs.size(), ret = 0;
for (int i = 0; i < n; ++i) ret += i < n / 2 ? costs[i][0] : costs[i][1];
return ret;
}
};
On a campus represented as a 2D grid, there are N workers and M bikes, with N <=
M. Each worker and bike is a 2D coordinate on this grid.
Our goal is to assign a bike to each worker. Among the available bikes and
workers, we choose the (worker, bike) pair with the shortest Manhattan distance
between each other, and assign the bike to that worker. (If there are multiple
(worker, bike) pairs with the same shortest Manhattan distance, we choose the
pair with the smallest worker index; if there are multiple ways to do that, we
choose the pair with the smallest bike index). We repeat this process until
there are no available workers.
The Manhattan distance between two points p1 and p2 is Manhattan(p1, p2) = |p1.x
- p2.x| + |p1.y - p2.y|.
Return a vector ans of length N, where ans[i] is the index (0-indexed) of the
bike that the i-th worker is assigned to.
Example 1:
Note:
Solution
class Solution {
public:
vector<int> assignBikes(vector<vector<int>>& workers, vector<vector<int>>&
bikes) {
vector<vector<pair<int, int>>> bucket(2001);
int m = workers.size(), n = bikes.size();
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
bucket[abs(workers[i][0] - bikes[j][0]) + abs(workers[i][1] - bikes[j]
[1])].emplace_back(i, j);
vector<bool> chosen_workers(m, false), chosen_bikes(n, false);
vector<int> ret(m, -1);
for (int i = 0; i < 2001; ++i) {
for (int j = 0; j < (int)bucket[i].size(); ++j) {
int w = bucket[i][j].first, b = bucket[i][j].second;
if (!chosen_workers[w] && !chosen_bikes[b]) {
ret[w] = b;
chosen_workers[w] = chosen_bikes[b] = true;
}
}
}
return ret;
}
};
Using sort:
class Solution {
public:
vector<int> assignBikes(vector<vector<int>>& workers, vector<vector<int>>&
bikes) {
int m = workers.size(), n = bikes.size();
vector<pair<int, pair<int, int>>> dist;
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
dist.push_back({abs(workers[i][0] - bikes[j][0]) + abs(workers[i][1] -
bikes[j][1]), {i, j}});
sort(dist.begin(), dist.end());
vector<bool> chosen_workers(m, false), chosen_bikes(n, false);
vector<int> ret(m, -1);
for (auto& d : dist) {
int i = d.second.first, j = d.second.second;
if (!chosen_workers[i] && !chosen_bikes[j]) {
ret[i] = j;
chosen_workers[i] = chosen_bikes[j] = true;
}
}
return ret;
}
};
class Solution {
public:
vector<int> assignBikes(vector<vector<int>>& workers, vector<vector<int>>&
bikes) {
int m = workers.size(), n = bikes.size();
priority_queue<pair<int, pair<int, int>>, vector<pair<int, pair<int, int>>>,
greater<pair<int, pair<int, int>>>> pq;
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
pq.push({abs(workers[i][0] - bikes[j][0]) + abs(workers[i][1] - bikes[j]
[1]), {i, j}});
vector<bool> chosen_workers(m, false), chosen_bikes(n, false);
vector<int> ret(m, -1);
while (!pq.empty()) {
pair<int, pair<int, int>> p = pq.top(); pq.pop();
int i = p.second.first, j = p.second.second;
if (!chosen_workers[i] && !chosen_bikes[j]) {
ret[i] = j;
chosen_workers[i] = chosen_bikes[j] = true;
}
}
return ret;
}
};
Given a text string and words (a list of strings), return all index pairs [i, j]
so that the substring text[i]...text[j] is in the list of words.
Example 1:
Note:
05/10/2020:
class Solution {
public:
vector<vector<int>> indexPairs(string text, vector<string>& words) {
vector<vector<int>> ret;
int n = text.size();
for (auto& w : words) {
int m = w.size();
if (m > n) continue;
for (int i = 0; i < n - m + 1; ++i) {
if (text.substr(i, m) == w) {
ret.push_back({i, i + m - 1});
}
}
}
sort(ret.begin(), ret.end());
return ret;
}
};
On a campus represented as a 2D grid, there are N workers and M bikes, with N <=
M. Each worker and bike is a 2D coordinate on this grid.
We assign one unique bike to each worker so that the sum of the Manhattan
distances between each worker and their assigned bike is minimized.
The Manhattan distance between two points p1 and p2 is Manhattan(p1, p2) = |p1.x
- p2.x| + |p1.y - p2.y|.
Return the minimum possible sum of Manhattan distances between each worker and
their assigned bike.
Example 1:
Note:
Solution
06/11/2020:
class Solution {
public:
int assignBikes(vector<vector<int>>& workers, vector<vector<int>>& bikes) {
function dist = [](vector<int>& worker, vector<int>& bike) {
return abs(worker[0] - bike[0]) + abs(worker[1] - bike[1]);
};
int m = workers.size(), n = bikes.size();
vector<vector<int>> dp(m + 1, vector<int>(1 << n, INT_MAX - 4000));
dp[0][0] = 0;
int minDist = INT_MAX;
for (int i = 1; i <= m; ++i) {
for (int s = 1; s < (1 << n); ++s) {
for (int j = 0; j < n; ++j) {
if ((s & (1 << j)) != 0) {
int prev = s ^ (1 << j);
dp[i][s] = min(dp[i][s], dp[i - 1][prev] + dist(workers[i - 1],
bikes[j]));
minDist = i == m ? min(minDist, dp[i][s]) : minDist;
}
}
}
}
return minDist;
}
};
class Solution {
public:
int minDist = INT_MAX;
vector<bool> chosen_bikes;
int assignBikes(vector<vector<int>>& workers, vector<vector<int>>& bikes) {
int m = workers.size(), n = bikes.size(), dist = 0;
chosen_bikes.assign(1000, false);
backtrack(0, dist, workers, bikes);
return minDist;
}
void backtrack(int i, int dist, vector<vector<int>>& workers,
vector<vector<int>>& bikes) {
if (i == workers.size()) {
minDist = min(dist, minDist);
return;
}
if (dist > minDist) return; // pruning
for (int j = 0; j < (int)bikes.size(); ++j) {
if (chosen_bikes[j] == false) {
chosen_bikes[j] = true;
backtrack(i + 1, dist + abs(workers[i][0] - bikes[j][0]) +
abs(workers[i][1] - bikes[j][1]), workers, bikes);
chosen_bikes[j] = false;
}
}
}
};
Given two strings text1 and text2, return the length of their longest common
subsequence.
A subsequence of a string is a new string generated from the original string
with some characters(can be none) deleted without changing the relative order of
the remaining characters. (eg, "ace" is a subsequence of "abcde" while "aec" is
not). A common subsequence of two strings is a subsequence that is common to
both strings.
Example 1:
Constraints:
Solution
Discussion:
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
int m = text1.size(), n = text2.size();
vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
dp[i + 1][j + 1] = text1[i] == text2[j] ? dp[i][j] + 1 : max(dp[i][j +
1], dp[i + 1][j]);
return dp.back().back();
}
};
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
int m = text1.size(), n = text2.size();
vector<int> dp(n + 1, 0);
for (int i = 0; i < m; ++i) {
vector<int> tmp(dp);
for (int j = 0; j < n; ++j) {
dp[j + 1] = text1[i] == text2[j] ? tmp[j] + 1 : max(dp[j + 1], dp[j]);
}
}
return dp.back();
}
};
Let's define a function f(s) over a non-empty string s, which calculates the
frequency of the smallest character in s. For example, if s = "dcce" then f(s) =
2 because the smallest character is "c" and its frequency is 2.
Now, given string arrays queries and words, return an integer array answer,
where each answer[i] is the number of words such that f(queries[i]) < f(W),
where W is a word in words.
Example 1:
Constraints:
Solution
02/05/2020:
class Solution {
public:
vector<int> numSmallerByFrequency(vector<string>& queries, vector<string>&
words) {
int n = queries.size(), N = 11;
vector<int> ret(n, 0), cnt(N, 0);
for (auto& w : words) ++cnt[f(w) - 1];
for (int i = N - 2; i > -1; --i) cnt[i] += cnt[i + 1];
for (int i = 0; i < n; ++i) ret[i] = cnt[f(queries[i])];
return ret;
}
int f(string& s) {
char ch = *min_element(s.begin(), s.end());
return count(s.begin(), s.end(), ch);
}
};
Given a m * n matrix of ones and zeros, return how many square submatrices have
all ones.
Example 1:
Input: matrix =
[
[0,1,1,1],
[1,1,1,1],
[0,1,1,1]
]
Output: 15
Explanation:
There are 10 squares of side 1.
There are 4 squares of side 2.
There is 1 square of side 3.
Total number of squares = 10 + 4 + 1 = 15.
Example 2:
Input: matrix =
[
[1,0,1],
[1,1,0],
[1,1,0]
]
Output: 7
Explanation:
There are 6 squares of side 1.
There is 1 square of side 2.
Total number of squares = 6 + 1 = 7.
Constraints:
Solution
class Solution {
public:
int countSquares(vector<vector<int>>& matrix) {
int m = matrix.size(), n = matrix[0].size(), ret = 0;;
vector<vector<int>> dp(m, vector<int>(n, 0));
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (i == 0 || j == 0)
dp[i][j] = matrix[i][j];
else
dp[i][j] = matrix[i][j] == 0 ? 0 : min(min(dp[i - 1][j - 1], dp[i - 1]
[j]), dp[i][j - 1]) + 1;
ret += dp[i][j];
}
}
return ret;
}
};
class Solution {
public:
int countSquares(vector<vector<int>>& matrix) {
if (matrix.empty() || matrix[0].empty()) return 0;
int m = matrix.size(), n = matrix[0].size();
int ret = 0;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (i >= 1 && j >= 1 && matrix[i][j] == 1)
matrix[i][j] = min(min(matrix[i - 1][j], matrix[i][j - 1]), matrix[i -
1][j - 1]) + 1;
ret += matrix[i][j];
}
}
return ret;
}
};
Constraints:
Solution
05/10/2020:
class Solution {
public:
int findSpecialInteger(vector<int>& arr) {
int n = arr.size();
int m = (n + 1) / 4;
for (int i = 0; i < n - m; ++i) {
if (arr[i] == arr[i + m]) {
return arr[i];
}
}
return -1;
}
};
Given a m * n matrix mat and an integer K, return a matrix answer where each
answer[i][j] is the sum of all elements mat[r][c] for i - K <= r <= i + K, j - K
<= c <= j + K, and (r, c) is a valid position in the matrix.
Example 1:
Constraints:
m == mat.length
n == mat[i].length
1 <= m, n, K <= 100
1 <= mat[i][j] <= 100
Solution
01/14/2020 (Definition):
class Solution {
public:
vector<vector<int>> matrixBlockSum(vector<vector<int>>& mat, int K) {
int m = mat.size(), n = mat[0].size();
vector<vector<int>> ret(m, vector<int>(n, 0));
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
for (int k = -K; k <= K; ++k) {
for (int l = -K; l <= K; ++l) {
if (i + k >= 0 && i + k < m && j + l >= 0 && j + l < n) {
ret[i][j] += mat[i + k][j + l];
}
}
}
}
}
return ret;
}
};
class Solution {
public:
vector<vector<int>> matrixBlockSum(vector<vector<int>>& mat, int K) {
int m = mat.size(), n = mat[0].size();
vector<vector<int>> dp(m, vector<int>(n, 0));
vector<vector<int>> ret(m, vector<int>(n, 0));
dp[0][0] = mat[0][0];
for (int i = 1; i < m; ++i) dp[i][0] += dp[i - 1][0] + mat[i][0];
for (int j = 1; j < n; ++j) dp[0][j] += dp[0][j - 1] + mat[0][j];
for (int i = 1; i < m; ++i)
for (int j = 1; j < n; ++j)
dp[i][j] = mat[i][j] + dp[i][j - 1] + dp[i - 1][j] - dp[i - 1][j - 1];
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
int r1 = max(i - K, 0);
int c1 = max(j - K, 0);
int r2 = min(i + K, m - 1);
int c2 = min(j + K, n - 1);
ret[i][j] = dp[r2][c2];
if (r1 > 0) ret[i][j] -= dp[r1 - 1][c2];
if (c1 > 0) ret[i][j] -= dp[r2][c1 - 1];
if (r1 > 0 && c1 > 0) ret[i][j] += dp[r1 - 1][c1 - 1];
}
}
return ret;
}
};
Given an array of integers arr, replace each element with its rank.
The rank represents how large the element is. The rank has the following rules:
Example 1:
Constraints:
Solution
05/10/2020:
class Solution {
public:
vector<int> arrayRankTransform(vector<int>& arr) {
if (arr.empty()) return {};
set<int> keys(arr.begin(), arr.end());
unordered_map<int, int> mp;
int i = 1;
for (auto& k : keys) {
mp[k] = i++;
}
vector<int> ret;
for (auto& a : arr) {
ret.push_back(mp[a]);
}
return ret;
}
};
Given a string s of zeros and ones, return the maximum score after splitting the
string into two non-empty substrings (i.e. left substring and right substring).
The score after splitting a string is the number of zeros in the left substring
plus the number of ones in the right substring.
Example 1:
Input: s = "011101"
Output: 5
Explanation:
All possible ways of splitting s into two non-empty substrings are:
left = "0" and right = "11101", score = 1 + 4 = 5
left = "01" and right = "1101", score = 1 + 3 = 4
left = "011" and right = "101", score = 1 + 2 = 3
left = "0111" and right = "01", score = 1 + 1 = 2
left = "01110" and right = "1", score = 2 + 1 = 3
Example 2:
Input: s = "00111"
Output: 5
Explanation: When left = "00" and right = "111", we get the maximum score = 2 +
3 = 5
Example 3:
Input: s = "1111"
Output: 3
Constraints:
Solution
04/25/2020:
class Solution {
public:
int maxScore(string s) {
int zeros = 0, ones = 0;
for (auto& c : s) {
if (c == '0') {
++zeros;
} else {
++ones;
}
}
int n = s.size();
int cur_zeros = 0;
int ret = 0;
for (int i = 0; i < n - 1; ++i) {
if (s[i] == '0') {
++cur_zeros;
}
ret = max(ret, cur_zeros + (n - (i + 1) - (zeros - cur_zeros)));
}
return ret;
}
};
Given a list of lists of integers, nums, return all elements of nums in diagonal
order as shown in the below images.
Example 1:
Constraints:
Solution
04/25/2020:
class Solution {
public:
vector<int> findDiagonalOrder(vector<vector<int>>& nums) {
int m = nums.size();
if (m <= 0) return {};
map<int, vector<int>> mp;
for (int i = 0; i < m; ++i) {
int n = nums[i].size();
for (int j = 0; j < n; ++j) {
mp[i + j].push_back(nums[i][j]);
}
}
vector<int> ret;
for (auto& m : mp) {
ret.insert(ret.end(), m.second.rbegin(), m.second.rend());
}
return ret;
}
};
Given an array of integers nums and an integer limit, return the size of the
longest continuous subarray such that the absolute difference between any two
elements is less than or equal to limit.
Example 1:
Constraints:
Solution
05/03/2020:
class Solution {
public:
int longestSubarray(vector<int>& nums, int limit, int start = 0, int stop =
INT_MAX) {
if (stop == INT_MAX) stop = nums.size() - 1;
if (start > stop) return 0;
auto min_it = min_element(nums.begin() + start, nums.begin() + stop + 1);
auto max_it = max_element(nums.begin() + start, nums.begin() + stop + 1);
if (*max_it - *min_it <= limit) return stop - start + 1;
auto lo = min_it, hi = min_it;
for (; lo - nums.begin() > start && *(lo - 1) - *min_it <= limit; --lo);
for (; hi - nums.begin() < stop && *(hi + 1) - *min_it <= limit; ++hi);
int left = int(min_it - nums.begin() - 1) - start + 1 >= hi - lo + 1 ?
longestSubarray(nums, limit, start, int(min_it - nums.begin() - 1)) : 0;
int right = stop - int(min_it - nums.begin() - 1) + 1 >= hi - lo + 1 ?
longestSubarray(nums, limit, int(min_it - nums.begin() + 1), stop) : 0;
return max(int(hi - lo + 1), max(left, right));
}
};
1441. Build an Array With Stack Operations
Description
Given an array target and an integer n. In each iteration, you will read a
number from list = {1,2,3..., n}.
Push: Read a new element from the beginning list, and push it in the array.
Pop: delete the last element of the array.
If the target array is already built, stop reading more elements.
You are guaranteed that the target array is strictly increasing, only containing
numbers between 1 to n inclusive.
Example 1:
Constraints:
Solution
05/10/2020:
class Solution {
public:
vector<string> buildArray(vector<int>& target, int n) {
int m = *max_element(target.begin(), target.end());
unordered_set<int> s(target.begin(), target.end());
vector<string> ret;
for (int i = 1; i <= m; ++i) {
ret.push_back("Push");
if (s.count(i) == 0) {
ret.push_back("Pop");
}
}
return ret;
}
};
Example 1:
Input: n = 2
Output: ["1/2"]
Explanation: "1/2" is the only unique fraction with a denominator less-than-or-
equal-to 2.
Example 2:
Input: n = 3
Output: ["1/2","1/3","2/3"]
Example 3:
Input: n = 4
Output: ["1/2","1/3","1/4","2/3","3/4"]
Explanation: "2/4" is not a simplified fraction because it can be simplified to
"1/2".
Example 4:
Input: n = 1
Output: []
Constraints:
Solution
05/16/2020:
class Solution {
public:
vector<string> simplifiedFractions(int n) {
unordered_set<string> ret;
for (int i = 1; i < n; ++i) {
for (int j = i + 1; j <= n; ++j) {
int gcd = __gcd(i, j);
int numerator = i / gcd;
int denominator = j / gcd;
ret.insert(to_string(numerator) + "/" + to_string(denominator));
}
}
return vector<string>(ret.begin(), ret.end());
}
};
Example 1:
Constraints:
Solution
05/16/2020:
class Solution {
public:
vector<int> peopleIndexes(vector<vector<string>>& favoriteCompanies) {
vector<pair<unordered_set<string>, int>> companies;
int n = favoriteCompanies.size();
for (int i = 0; i < n; ++i) {
companies.emplace_back(unordered_set<string>(favoriteCompanies[i].begin(),
favoriteCompanies[i].end()), i);
}
sort(companies.begin(), companies.end(), [](pair<unordered_set<string>,
int>& p1, pair<unordered_set<string>, int>& p2) {
return p1.first.size() > p2.first.size();
});
vector<int> ret;
ret.push_back(companies[0].second);
for (int i = 1; i < n; ++i) {
int cnt = 0;
for (int j = 0; j < i; ++j) {
bool isSubset = true;
for (auto& s : companies[i].first) {
if (companies[j].first.count(s) == 0) {
isSubset = false;
break;
}
}
if (!isSubset) {
++cnt;
}
}
if (cnt == i) ret.push_back(companies[i].second);
}
sort(ret.begin(), ret.end());
return ret;
}
};
Input: s = "00110110", k = 2
Output: true
Explanation: The binary codes of length 2 are "00", "01", "10" and "11". They
can be all found as substrings at indicies 0, 1, 3 and 2 respectively.
Example 2:
Input: s = "00110", k = 2
Output: true
Example 3:
Input: s = "0110", k = 1
Output: true
Explanation: The binary codes of length 1 are "0" and "1", it is clear that both
exist as a substring.
Example 4:
Input: s = "0110", k = 2
Output: false
Explanation: The binary code "00" is of length 2 and doesn't exist in the array.
Example 5:
Input: s = "0000000001011100", k = 4
Output: false
Constraints:
Solution
05/30/2020:
class Solution {
public:
bool hasAllCodes(string s, int k) {
bool ret = true;
int n = 1 << k;
int sz = s.size() - k;
unordered_set<string> required;
for (int i = 0; i <= sz; ++i) {
string sub = s.substr(i, k);
required.insert(sub);
}
return required.size() == n;
}
};
Given a rows x cols matrix grid representing a field of cherries. Each cell in
grid represents the number of cherries that you can collect.
You have two robots that can collect cherries for you, Robot #1 is located at
the top-left corner (0,0) , and Robot #2 is located at the top-right corner (0,
cols-1) of the grid.
Return the maximum number of cherries collection using both robots by following
the rules below:
From a cell (i,j), robots can move to cell (i+1, j-1) , (i+1, j) or (i+1, j+1).
When any robot is passing through a cell, It picks it up all cherries, and the
cell becomes an empty cell (0).
When both robots stay on the same cell, only one of them takes the cherries.
Both robots cannot move outside of the grid at any moment.
Both robots should reach the bottom row in the grid.
Example 1:
Constraints:
rows == grid.length
cols == grid[i].length
2 <= rows, cols <= 70
0 <= grid[i][j] <= 100
Solution
06/07/2020:
int dp[71][71][71];
class Solution {
public:
int cherryPickup(vector<vector<int>>& grid) {
fill_n(dp[0][0], 71 * 71 * 71, -1);
int m = grid.size(), n = grid[0].size();
dp[0][0][n - 1] = grid[0][0] + grid[0][n - 1];
for (int i = 1; i < m; ++i) {
for (int j = 0; j < n; ++j) {
for (int k = 0; k < n; ++k) {
int cur = -1;
for (int u = -1; u <= 1; ++u) {
int nj = j + u;
for (int v = -1; v <= 1; ++v) {
int nk = k + v;
if (nj >= 0 && nj < n && nk >= 0 && nk < n && dp[i - 1][nj][nk] !=
-1)
cur = max(cur, dp[i - 1][nj][nk] + grid[i][j] + grid[i][k]);
}
}
if (j == k) cur -= grid[i][j];
dp[i][j][k] = max(dp[i][j][k], cur);
}
}
}
int ret = -1;
for (int j = 0; j < n; ++j) ret = max(ret, *max_element(dp[m - 1][j], dp[m -
1][j] + n));
return ret;
}
};
Return a list of the strongest k values in the array. return the answer in any
arbitrary order.
Median is the middle value in an ordered integer list. More formally, if the
length of the list is n, the median is the element in position ((n - 1) / 2) in
the sorted list (0-indexed).
For arr = [6, -3, 7, 2, 11], n = 5 and the median is obtained by sorting the
array arr = [-3, 2, 6, 7, 11] and the median is arr[m] where m = ((5 - 1) / 2) =
2. The median is 6.
For arr = [-7, 22, 17, 3], n = 4 and the median is obtained by sorting the array
arr = [-7, 3, 17, 22] and the median is arr[m] where m = ((4 - 1) / 2) = 1. The
median is 3.
Example 1:
Constraints:
Solution
06/06/2020:
int m;
class Solution {
public:
vector<int> getStrongest(vector<int>& arr, int k) {
int n = arr.size();
sort(arr.begin(), arr.end());
m = arr[(n - 1) / 2];
sort(arr.begin(), arr.end(), [](int a, int b) {
if (abs(a - m) == abs(b - m)) return a > b;
return abs(a - m) > abs(b - m);
});
vector<int> ret;
for (int i = 0; i < k; ++i)
ret.push_back(arr[i]);
return ret;
}
};
Given a binary tree where each path going from the root to any leaf form a valid
sequence, check if a given string is a valid sequence in such binary tree.
We get the given string from the concatenation of an array of integers arr and
the concatenation of all values of the nodes along a path results in a sequence
in the given binary tree.
Example 1:
Solution
Discussion
Using unordered_map is straightforward: convert numbers visited to a string and store seen strings in
an unordered_map. Then just check whether the target string generated by the arr is in the
unordered_map or not.
Time complexity: O(n)
Space complexity: O(n^2)
class Solution {
private:
unordered_set<string> s;
string target;
public:
bool isValidSequence(TreeNode* root, vector<int>& arr) {
for (auto& n : arr) target += to_string(n);
dfs(root);
return s.count(target);
}
Another way is more straightforward, we check the elements in the arr while traversing the nodes in
the tree:
Time complexity: O(n)
Space complexity: O(n)
class Solution {
public:
bool isValidSequence(TreeNode* root, vector<int>& arr, int i = 0) {
if (root == nullptr) return false;
if (i >= (int)arr.size()) return false;
if (root->left == nullptr && root->right == nullptr && i == (int)arr.size()
- 1) return arr.back() == root->val;
return root->val == arr[i] && (isValidSequence(root->left, arr, i + 1) ||
isValidSequence(root->right, arr, i + 1));
}
};
You have to find two non-overlapping sub-arrays of arr each with sum equal
target. There can be multiple answers so you have to find an answer where the
sum of the lengths of the two sub-arrays is minimum.
Return the minimum sum of the lengths of the two required sub-arrays, or return
-1 if you cannot find such two sub-arrays.
Example 1:
Constraints:
Solution
06/13/2020:
class Solution {
public:
int minSumOfLengths(vector<int>& arr, int target) {
queue<pair<int, int>> q;
int ret = INT_MAX, preMin = INT_MAX;
int lo = 0, hi = 0, cur = 0;
while (hi < arr.size()) {
cur += arr[hi];
++hi;
while (cur > target && lo < hi) {
cur -= arr[lo];
++lo;
}
while (!q.empty() && q.front().second <= lo) {
preMin = min(preMin, q.front().second - q.front().first);
q.pop();
}
if (cur == target) {
if (preMin != INT_MAX) {
ret = min(ret, preMin + hi - lo);
}
q.emplace(lo, hi);
}
}
return ret == INT_MAX ? -1 : ret;
}
};
class Solution {
public:
int minSumOfLengths(vector<int>& arr, int target) {
vector<int> lhs, rhs;
solve(arr, target, lhs);
reverse(arr.begin(), arr.end());
solve(arr, target, rhs);
for (int i = 1; i < (int)lhs.size(); ++i) lhs[i] = min(lhs[i], lhs[i - 1]);
for (int i = 1; i < (int)rhs.size(); ++i) rhs[i] = min(rhs[i], rhs[i - 1]);
int ret = 1e9;
int n = arr.size();
for (int i = 1; i < n; ++i) ret = min(ret, lhs[i] + rhs[n - i]);
if (ret >= 1e9) ret = -1;
return ret;
}
};
Constraints:
Solution
06/13/2020:
class Solution {
public:
vector<int> runningSum(vector<int>& nums) {
partial_sum(nums.begin(), nums.end(), nums.begin());
return nums;
}
};
Return the minimum number of days you need to wait to be able to make m bouquets
from the garden. If it is impossible to make m bouquets return -1.
Example 1:
bloomDay.length == n
1 <= n <= 10^5
1 <= bloomDay[i] <= 10^9
1 <= m <= 10^6
1 <= k <= n
Solution
06/13/2020:
class Solution {
public:
int minDays(vector<int>& bloomDay, int m, int k) {
if (bloomDay.size() < (long long)m * k) return -1;
int lo = 0, hi = 1e9;
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
int amount = 0, candidate = 0;
for (auto& b : bloomDay) {
if (b <= mid)
++candidate;
else
candidate = 0;
if (candidate == k) {
candidate = 0;
++amount;
}
}
if (amount >= m)
hi = mid;
else
lo = mid + 1;
}
return lo;
}
};
You are given a tree with n nodes numbered from 0 to n-1 in the form of a parent
array where parent[i] is the parent of node i. The root of the tree is node 0.
Implement the function getKthAncestor(int node, int k) to return the k-th
ancestor of the given node. If there is no such ancestor, return -1.
The k-th ancestor of a tree node is the k-th node in the path from that node to
the root.
Example:
Input:
["TreeAncestor","getKthAncestor","getKthAncestor","getKthAncestor"]
[[7,[-1,0,0,1,1,2,2]],[3,1],[5,2],[6,3]]
Output:
[null,1,0,-1]
Explanation:
TreeAncestor treeAncestor = new TreeAncestor(7, [-1, 0, 0, 1, 1, 2, 2]);
Constraints:
Solution
06/13/2020:
class TreeAncestor {
public:
TreeAncestor(int n, vector<int>& parent) {
for (int i = 0; i < n; ++i) dp[i][0] = parent[i];
for (int d = 1; d < MAXD; ++d) {
for (int i = 0; i < n; ++i) {
if (dp[i][d - 1] == -1)
dp[i][d] = -1;
else
dp[i][d] = dp[dp[i][d - 1]][d - 1];
}
}
}
/**
* Your TreeAncestor object will be instantiated and called as such:
* TreeAncestor* obj = new TreeAncestor(n, parent);
* int param_1 = obj->getKthAncestor(node,k);
*/
Your country has an infinite number of lakes. Initially, all the lakes are
empty, but when it rains over the nth lake, the nth lake becomes full of water.
If it rains over a lake which is full of water, there will be a flood. Your goal
is to avoid the flood in any lake.
rains[i] > 0 means there will be rains over the rains[i] lake.
rains[i] == 0 means there are no rains this day and you can choose one lake this
day and dry it.
Return an array ans where:
ans.length == rains.length
ans[i] == -1 if rains[i] > 0.
ans[i] is the lake you choose to dry in the ith day if rains[i] == 0.
If there are multiple valid answers return any of them. If it is impossible to
avoid flood return an empty array.
Notice that if you chose to dry a full lake, it becomes empty, but if you chose
to dry an empty lake, nothing changes. (see example 4)
Example 1:
Constraints:
Solution
06/20/2020:
class Solution {
public:
vector<int> avoidFlood(vector<int>& rains) {
int n = rains.size();
unordered_map<int, int> bad;
set<int> canfix;
vector<int> ret(n, -1);
for (int i = 0; i < n; ++i) {
if (rains[i] == 0) {
canfix.insert(i);
ret[i] = 1;
} else {
if (bad.count(rains[i]) == 0) {
bad[rains[i]] = i;
} else {
int must = bad[rains[i]];
auto it = canfix.upper_bound(must);
if (it == canfix.end()) return {};
ret[*it] = rains[i];
canfix.erase(it);
bad[rains[i]] = i;
}
}
}
return ret;
}
};