Leetcode Pro Sheet
Leetcode Pro Sheet
LeetCode-Solutions
896. Monotonic Array
892. Surface Area of 3D Shapes
890. Find and Replace Pattern
888. Fair Candy Swap
887. Projection Area of 3D Shapes
885. Boats to Save People
883. Generate Random Point in a Circle
882. Random Point in Non-overlapping Rectangles
873. Length of Longest Fibonacci Subsequence
872. Leaf-Similar Trees
870. Advantage Shuffle
859. Buddy Strings
846. Hand of Straights
807. Max Increase to Keep City Skyline
784. Letter Case Permutation
746. Min Cost Climbing Stairs
590. N-ary Tree Postorder Traversal
589. N-ary Tree Preorder Traversal
559. Maximum Depth of N-ary Tree
495. Teemo Attacking
442. Find All Duplicates in an Array
409. Longest Palindrome
429. N-ary Tree Level Order Traversal
350. Intersection of Two Arrays II
345. Reverse Vowels of a String
274. H-Index
256. Paint House
238. Product of Array Except Self
219. Contains Duplicate II
200. Number of Islands
198. House Robber
169. Majority Element
102. Binary Tree Level Order Traversal
73. Set Matrix Zeroes
69. Sqrt(x)
54. Spiral Matrix
33. Search in Rotated Sorted Array
19. Remove Nth Node From End of List
13. Roman to Integer
11. Container With Most Water
Solution
The idea is that the total increment/decrement of a montonic array is same as the difference between the
first and last element in the array. Hence, we just need to sum up the absolute value of the difference of
two adjacent elements, then compare with the absolute value of the difference between the first element
and last element.
Here is the solution in C++. Time complexity: O(N) vs. Space complexity: O(1).
class Solution {
public:
bool isMonotonic(vector<int>& A) {
int n = A.size(), sum = 0;
for (int i = 0; i < A.size() - 1; ++i)
sum += abs(A[i] - A[i + 1]);
return abs(A[n-1] - A[0]) == sum;
}
};
892. Surface Area of 3D Shapes
Description
Solution
const int d[4][2] = { {1, 0}, {0, 1}, {-1, 0}, {0, -1} };
class Solution {
public:
int surfaceArea(vector<vector<int>>& grid) {
int ret = 0;
for (int i = 0; i < grid.size(); ++i) {
for (int j = 0; j < grid[0].size(); ++j) {
if (grid[i][j])
ret += 2;
for (int k = 0; k < 4; ++k) {
int ni = i + d[k][0];
int nj = j + d[k][1];
if (ni < 0 || ni == grid.size() || nj < 0 || nj ==
grid[0].size())
ret += grid[i][j];
else if (grid[ni][nj] < grid[i][j])
ret += grid[i][j] - grid[ni][nj];
}
}
}
return ret;
}
};
Solution
The idea is to check whether the number of letter occurrences in the given word and that of pattern are the
same, besides, the number of pairs (words[k][i], pattern[i]) should also be the same.
class Solution {
public:
vector<string> findAndReplacePattern(vector<string>& words, string pattern)
{
vector<string> ret;
for (auto w : words)
if (matchPattern(w, pattern))
ret.push_back(w);
return ret;
}
Solution
The idea is to find the difference diff between the sum of two arrays A and B. Then find two elements,
one in A and the other in B, such that a[i] - b[j] = diff / 2.
class Solution {
public:
vector<int> fairCandySwap(vector<int>& A, vector<int>& B) {
sort(A.begin(), A.end());
sort(B.begin(), B.end());
int diff{0};
for (auto a : A)
diff += a;
for (auto b : B)
diff -= b;
diff /= 2;
vector<int> ret;
for (int i = 0, j = 0; i < A.size() && j < B.size();) {
if (A[i] - B[j] == diff) {
ret.push_back(A[i]), ret.push_back(B[j]);
return ret;
}
else if (A[i] - B[j] > diff)
++j;
else
++i;
}
}
};
Solution
The idea is
1. For the projection on xy-plane, just count the number of nonzero entries grid[i][j] != 0, where i =
0, ..., gridRowSize - 1, j = 0, ..., gridColSizes[0] - 1.
2. For the projection on xz-plane, sum up the maximums of each row.
3. For the projection on yz-plane, sum up the maximums of each column.
4. Sum up all the numbers above.
Solution
The idea is to sort people's weight in descending order, and then try to pair the one of highest weight with
the one of the lowest weight. If the total weight of the two is no more than limit, then pair them up and
carry on. If not, the one of highest weight takes one boat, and the one of lowest weight remains waiting to
be paired with the one of second highest weight. Repeat the above.
Solution
The idea is to use generate uniformly distributed angles and radius, then transform them into Cartesian
coordinates.
However, I got Internal Error for the Python code and Wrong Answer for the C code. Since these
points are random, how could the expected answer be the same as my output???!
Update: Thanks to caraxin, fixed the issue. Use x = obj->x_center + obj->raidus * sqrt((double)
rand() / RAND_MAX) * cos(theta) rather than x = obj->x_center + obj->raidus * ((double)
rand() / RAND_MAX) * cos(theta), same for y.
C:
typedef struct {
double radius;
double x_center;
double y_center;
} Solution;
Solution* solutionCreate(double radius, double x_center, double y_center) {
Solution *solution = malloc(sizeof(Solution));
solution->radius = radius;
solution->x_center = x_center;
solution->y_center = y_center;
return solution;
}
/**
* Your Solution struct will be instantiated and called as such:
* struct Solution* obj = solutionCreate(radius, x_center, y_center);
* double* param_1 = solutionRandPoint(obj);
* solutionFree(obj);
*/
Python:
class Solution(object):
def randPoint(self):
"""
:rtype: List[float]
"""
scale = random.uniform(0, 1)
theta = random.uniform(0, 8 * math.atan(1))
x = self.x_center + self.radius * math.sqrt(scale) * math.cos(theta)
y = self.y_center + self.radius * math.sqrt(scale) * math.sin(theta)
return [x, y]
Solution
1. First calculate the areas of rectangles, and then calculate the ratio of area of each rectangle against the
total areas of rectangels, using cumsum to obtain the probability to pick the rectangle.
2. Once pick certain rectangle, we determine the point on the rectangle by calculating x = x1 - 0.5 +
(double) rand() / RAND_MAX * (x2 - x1 + 1), then round to the nearest integer. Do the same for
y.
C:
typedef struct {
int rectsSize;
int **rects;
double *distribution;
} Solution;
/**
* Your Solution struct will be instantiated and called as such:
* struct Solution* obj = solutionCreate(rects, rectsSize);
* int* param_1 = solutionPick(obj);
* solutionFree(obj);
*/
Python:
import numpy as np
class Solution:
Solution
if (key == cur->key)
cur->val += val;
for (cur = head; key > cur->key; cur = cur->next) {
if (cur->next && key > cur->next->key)
continue;
else if (cur->next && key == cur->next->key)
cur->next->val += val;
else {
node *new = (node *) malloc(sizeof(node));
init(new, key, val, cur->next);
cur->next = new;
}
}
}
#define N 10000
int cur_max = 0;
for (int i = 0; i < ASize - 2; i++) {
for (int j = i + 1; j < ASize - 1; j++) {
int cnt = 2;
int first = A[i], second = A[j], third = first + second;
while (search(&hash[third % N], third)) {
first = second, second = third, third = first + second;
cnt++;
}
if (cnt > 2)
cur_max = cur_max > cnt ? cur_max : cnt;
}
}
free(hash);
return cur_max;
}
Solution
Basic idea: traverse two trees using recursion to obtain the leaves and then compare leaves one by one.
C (0 ms):
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
void traverse(struct TreeNode *root, int *leaves, int *i) {
if (!root)
return;
if (!root->left && !root->right)
leaves[(*i)++] = root->val;
traverse(root->left, leaves, i);
traverse(root->right, leaves, i);
}
class Solution:
def leafSimilar(self, root1, root2):
"""
:type root1: TreeNode
:type root2: TreeNode
:rtype: bool
"""
return self.traverse(root1) == self.traverse(root2)
Solution
Basic idea:
1. Use an array of struct pair (j, b) to store the indices and elements of array B in order to find keep
the index of B after sorting.
2. Sorting both arrays in ascending order gives [a1, a2, ..., an] and [(j1, b1), (j2, b2), ...,
(jn, bn)].
/**
* Return an array of size *returnSize.
* Note: The returned array must be malloced, assume caller calls free().
*/
struct pair {
int key;
int val;
};
Solution
The number of occurrences of each letter in both strings (hence also the length of two strings) shall be
the same;
If the condition above is satisfied, then the number of different occurrences must be exactly 2, or 0
unless there is at least one repeating letter.
Solution
The idea is to check whether the remainder of hand[i] / W are evenly distributed, that is, the number of
0, 1, ..., W - 1 should be the same.
// Check whether the number of cards of each group are the same by checking
// whether the remainders of handSize / W are evenly distributed
int rowSize = W, colSize = handSize / rowSize;
int *colIndex = calloc(rowSize, sizeof(int));
for (int i = 0; i < handSize; i++) {
colIndex[hand[i] % W]++;
if (colIndex[hand[i] % W] > colSize)
return false;
}
// Rearrange cards such that cards in each row have the same remainder
int **handMatrix = malloc(rowSize * sizeof(int *));
free(colIndex), colIndex = calloc(rowSize, sizeof(int));
for (int i = 0; i < handSize; i++) {
int row = hand[i] % rowSize;
if (colIndex[row] == 0)
handMatrix[row] = malloc(colSize * sizeof(int));
handMatrix[row][colIndex[row]++] = hand[i];
if (colIndex[row] == colSize)
qsort(handMatrix[row], colSize, sizeof(int), comparator);
}
Solution
The idea is to sum up the difference between grid[i][j] and minimum of the maximum of row i and
column j.
class Solution {
public:
int maxIncreaseKeepingSkyline(vector<vector<int>>& grid) {
int ret = 0;
if (!grid.size())
return ret;
vector<int> colMax, rowMax;
for (int j = 0; j < grid[0].size(); ++j) {
int curColMax = grid[0][j];
for (int i = 1; i < grid.size(); ++i)
curColMax = max(curColMax, grid[i][j]);
colMax.push_back(curColMax);
}
for (int i = 0; i < grid.size(); ++i)
rowMax.push_back(*max_element(grid[i].begin(), grid[i].end()));
for (int i = 0; i < grid.size(); ++i)
for (int j = 0; j < grid[i].size(); ++j)
ret += min(rowMax[i], colMax[j]) - grid[i][j];
return ret;
}
};
Solution
Update:
class Solution {
public:
vector<string> letterCasePermutation(string S) {
vector<string> ret;
if (!S.size()) {
ret.push_back("");
return ret;
}
char lastCh = S.back();
S.pop_back();
vector<string> cur = letterCasePermutation(S);
if (isalpha(lastCh))
for (auto c : cur)
ret.push_back(c + string(1, tolower(lastCh))),
ret.push_back(c + string(1, toupper(lastCh)));
else
for (auto c : cur)
ret.push_back(c + string(1, lastCh));
return ret;
}
};
/**
* Return an array of size *returnSize.
* Note: The returned array must be malloced, assume caller calls free().
*/
char** letterCasePermutation(char* S, int* returnSize) {
char **ret;
if (!S[0]) {
*returnSize = 1;
ret = malloc(sizeof(char *));
ret[0] = malloc(sizeof(char));
ret[0][0] = '\0';
return ret;
}
Original post:
C++:
class Solution {
public:
vector<string> letterCasePermutation(string S) {
vector<string> ret;
if (!S.size()) {
ret.push_back("");
return ret;
}
char lastCh = S.back();
S.pop_back();
ret = letterCasePermutation(S);
if (isalpha(lastCh)) {
vector<string> ret_copy = ret;
for (int i = 0; i < ret.size(); i++) {
ret_copy[i].insert(ret_copy[i].end(), toupper(lastCh));
ret[i].insert(ret[i].end(), tolower(lastCh));
}
ret.insert(ret.end(), ret_copy.begin(), ret_copy.end());
}
else {
for (auto &r : ret)
r.insert(r.end(), lastCh);
}
return ret;
}
};
C:
/**
* Return an array of size *returnSize.
* Note: The returned array must be malloced, assume caller calls free().
*/
char** letterCasePermutation(char* S, int* returnSize) {
char **ret;
if (!S[0]) {
*returnSize = 1;
ret = malloc(sizeof(char *));
ret[0] = malloc(sizeof(char));
ret[0][0] = '\0';
return ret;
}
int size;
char lastCh = S[strlen(S) - 1];
S[strlen(S) - 1] = '\0';
char **cur = letterCasePermutation(S, &size);
if (isalpha(lastCh)) {
*returnSize = 2 * size;
ret = malloc(*returnSize * sizeof(char *));
for (int i = 0; i < size; ++i) {
int len = strlen(cur[i]);
ret[2 * i] = malloc((len + 2) * sizeof(char));
ret[2 * i + 1] = malloc((len + 2) * sizeof(char));
// sprintf(ret[2 * i], "%s%c", cur[i], tolower(lastCh));
// sprintf(ret[2 * i + 1], "%s%c", cur[i], toupper(lastCh));
strcpy(ret[2 * i], cur[i]);
ret[2 * i][len] = tolower(lastCh);
strcpy(ret[2 * i + 1], cur[i]);
ret[2 * i + 1][len] = toupper(lastCh);
ret[2 * i][len + 1] = '\0';
ret[2 * i + 1][len + 1] = '\0';
free(cur[i]);
}
}
else {
*returnSize = size;
ret = malloc(*returnSize * sizeof(char *));
for (int i = 0; i < size; ++i) {
int len = strlen(cur[i]);
ret[i] = malloc((len + 2) * sizeof(char));
// sprintf(ret[i], "%s%c", cur[i], lastCh);
strcpy(ret[i], cur[i]);
ret[i][len] = lastCh;
ret[i][len + 1] = '\0';
free(cur[i]);
}
}
free(cur);
return ret;
}
746. Min Cost Climbing Stairs
Description
On a staircase, the i-th step has some non-negative cost cost[i] assigned (0
indexed).
Once you pay the cost, you can either climb one or two steps. You need to find
minimum cost to reach the top of the floor, and you can either start from the
step with index 0, or the step with index 1.
Example 1:
Solution
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
cost.push_back(0);
for (int i = 2; i < cost.size(); ++i)
cost[i] += min(cost[i - 2], cost[i - 1]);
return cost.back();
}
};
Update:
Iterative solution:
class Solution {
public:
vector<int> postorder(Node* root) {
vector<int> ret;
if (!root)
return ret;
vector<Node *> v{root};
while (!v.empty()) {
int n = v.size();
for (int i = 0; i < n; ++i) {
Node *cur = v.back(); v.pop_back();
ret.insert(ret.begin(), cur->val);
v.insert(v.end(), cur->children.begin(), cur->children.end());
}
}
return ret;
}
};
The idea is to use DFS based on recursion, which is the trivial case in the problem statement...
class Solution {
public:
vector<int> postorder(Node* root) {
vector<int> ret;
if (!root)
return ret;
for (auto child : root->children) {
vector<int> tmp = postorder(child);
ret.insert(ret.end(), tmp.begin(), tmp.end());
}
ret.push_back(root->val);
return ret;
}
};
Solution
Iterative solution:
class Solution {
public:
vector<int> preorder(Node* root) {
vector<int> ret;
if (!root)
return ret;
vector<Node *> n{root};
while (!n.empty()) {
Node *cur = n.back();
n.pop_back();
ret.push_back(cur->val);
n.insert(n.end(), cur->children.rbegin(), cur->children.rend());
}
return ret;
}
};
Recursive solution:
class Solution {
public:
vector<int> preorder(Node* root) {
vector<int> ret;
if (!root)
return ret;
ret.push_back(root->val);
for (auto &c : root->children) {
vector<int> tmp = preorder(c);
ret.insert(ret.end(), tmp.begin(), tmp.end());
}
return ret;
}
};
Solution
Basically, I did the same thing, but got "beats 99.58%". Here is the code:
class Solution {
public:
int maxDepth(Node* root) {
if (!root)
return 0;
int depth = 0;
for (auto &c : root->children)
depth = max(depth, maxDepth(c));
return depth + 1;
}
};
Used black magic! Yep, add last several lines, your code runs faster, magically and surprisingly.
Solution
The idea is very simple: add the duration if the time difference is between two consecutive attacking
time, otherwise add the time difference.
Solution
The idea is to make the best of the range of a[i]. Hence, we can use negation of nums[abs(nums[i]) -
1]th element to find the duplicate elements
class Solution {
public:
vector<int> findDuplicates(vector<int>& nums) {
vector<int> ret;
for (int i = 0; i < nums.size(); ++i) {
nums[abs(nums[i]) - 1] *= -1;
if (nums[abs(nums[i]) - 1] > 0)
ret.push_back(abs(nums[i]));
}
return ret;
}
};
class Solution {
public:
vector<int> findDuplicates(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<int> ret;
for (int i = 0, j = 0; nums.size() && i < nums.size() - 1;) {
for (j = 0; j < nums.size() && nums[i] == nums[i + j]; ++j);
if (j == 2)
ret.push_back(nums[i]);
i += j;
}
return ret;
}
};
Solution
The basic idea is to use hash table to get the frequency of each letter in the string. If the frequency is even,
then the corresponding letter is considered as a candidate to form the longest palindrome string. If it is
odd, however, we can take away one letter to make it even. At the end, pick one of the letters taken away
into the middle of the string.
For example, given a string "aaaaabbbccdde". We can get the following: hash['a'] = 5, hash['b'] =
3, hash['c'] = 2, hash['d'] = 2, and hash['e'] = 1. Pick all the even occurrence letters, "cc" and
"dd", and taking away one letter from odd occurrence letters gives "aaaa", "bb". As a result, the string
candidates are ["aaaa", "bb", "cc", "dd"], and the leftover becomes ['a', 'b', 'e']. Thus, we
can form a palindrome string from candidate letters, say "aabcddcbaa". At last, pick any one letter in the
leftover, say 'e', and putting it into the middle of the string yields "aabcdedcbaa".
#define N 128
int longestPalindrome(char* s) {
int hash[N] = {0}, res = 0, odd = 0;
for (int i = 0; s[i]; hash[s[i++]]++) {}
for (int i = 0; i < N; i++)
if (hash[i] % 2)
odd = 1, res += hash[i] - 1;
else
res += hash[i];
return res + odd;
}
Solution
The idea is to use recursion. The key is to merge vectors ret and r:
1. It is apparent that the child node is always one level lower than its parent node. Suppose r =
levelOrder(root->child), and ret a vector to store the final output for current level. Hence, r[0],
r[1], r[2], ..., should be merged to ret[1], ret[2], ret[3], ..., respectively.
2. If ret[1] does NOT exist, i.e., ret.size() == 1, then ret.push_back(r[0]). Otherwise, combine
ret[1] with r[0] by ret[1].insert(ret[1].end(), r[0].begin(), r[0].end());. To illustrate
this, see below:
Node() {}
Solution
1. Sort two arrays first and then compare each elements of the sorted arrays.
2. Using hash table to record the elements of one of the arrays, then traverse the elements in the other
array and check whether the element is in the hash table: if the element is indeed in the hash table
(there exists a key and the value/count is greater than 0), then update the value/count in the hash table
and append the element into resulting array.
Solution based on the built-in function qsort() with space complexity: O(1), time complexity: O(N log
N):
/**
* Return an array of size *returnSize.
* Note: The returned array must be malloced, assume caller calls free().
*/
int comparator(const void *a, const void *b) {
return *(int *) a > *(int *) b;
}
int* intersect(int* nums1, int nums1Size, int* nums2, int nums2Size, int*
returnSize) {
qsort(nums1, nums1Size, sizeof(int), comparator);
qsort(nums2, nums2Size, sizeof(int), comparator);
*returnSize = 0;
int *res = malloc(nums1Size * sizeof(int));
for (int i = 0, j = 0; i < nums1Size && j < nums2Size; ) {
if (nums1[i] == nums2[j]) {
res[(*returnSize)++] = nums1[i];
i++, j++;
}
else if (nums1[i] < nums2[j])
i++;
else
j++;
}
return realloc(res, *returnSize * sizeof(int));
}
Solution using hash table with space complexity: O(N), time complexity: O(N):
if (key == cur->key)
cur->val += val;
for (cur = head; key > cur->key; cur = cur->next) {
if (cur->next && key > cur->next->key)
continue;
else if (cur->next && key == cur->next->key)
cur->next->val += val;
else {
node *new = (node *) malloc(sizeof(node));
init(new, key, val, cur->next);
cur->next = new;
}
}
}
/**
* Return an array of size *returnSize.
* Note: The returned array must be malloced, assume caller calls free().
*/
#define N 10000
int* intersect(int* nums1, int nums1Size, int* nums2, int nums2Size, int*
returnSize) {
node *hash = malloc(N * sizeof(node));
for (int i = 0; i < N; init(&hash[i], i, 0, NULL), i++) {}
for (int i = 0; i < nums2Size; insert(&hash[nums2[i] % N], nums2[i], 1),
i++) {}
Solution
1. Use two arrays vows, vowsIndex to record the vowels and the corresponding index in the string (one
for loop).
2. Loop through the vows, and replace the original vowels.
Time complexity: O(N) vs. Space complexity: O(M), where N is the size of the string, and M is the number
of vowels in the string.
char* reverseVowels(char* s) {
int sSize = strlen(s), cnt = 0;
int *vowsIndex = malloc(sSize * sizeof(int));
char *vows = malloc((sSize + 1) * sizeof(char));
vows[sSize] = '\0';
for (int i = 0; s[i]; i++) {
switch (s[i]) {
case 'a': case 'e': case 'i': case 'o': case 'u':
case 'A': case 'E': case 'I': case 'O': case 'U':
vows[cnt] = s[i];
vowsIndex[cnt++] = i;
break;
}
}
for (int i = 0; i < cnt; i++)
s[vowsIndex[i]] = vows[cnt - i - 1];
free(vowsIndex), free(vows);
return s;
}
1. One pointer l starts from the beginning of the string and the other r starts from the end of string.
2. Two pointers move inwards until next closest vowels, and swap them.
3. Keep step 2 going until two pointers meet up.
Time complexity: O(N) vs. Space complexity: O(1).
char* reverseVowels(char* s) {
for (int l = 0, r = strlen(s) - 1; l < r; l++, r--) {
while (s[l] != 'a' && s[l] != 'e' && s[l] != 'i' && s[l] != 'o' && s[l]
!= 'u' &&
s[l] != 'A' && s[l] != 'E' && s[l] != 'I' && s[l] != 'O' && s[l]
!= 'U')
l++;
while (s[r] != 'a' && s[r] != 'e' && s[r] != 'i' && s[r] != 'o' && s[r]
!= 'u' &&
s[r] != 'A' && s[r] != 'E' && s[r] != 'I' && s[r] != 'O' && s[r]
!= 'U')
r--;
if (l < r) {
char tmp = s[l];
s[l] = s[r];
s[r] = tmp;
}
}
return s;
}
274. H-Index
Description
Solution
The idea is to sort the array citations in descending order, then apply the definition to find the h-index.
Note:
All costs are positive integers.
Example:
Input: [[17,2,17],[16,16,5],[14,3,19]]
Output: 10
Explanation: Paint house 0 into blue, paint house 1 into green, paint house 2
into blue.
Minimum cost: 2 + 5 + 3 = 10.
Solution
class Solution {
public:
int minCost(vector<vector<int>>& costs) {
for (int i = 1; i < costs.size(); ++i) {
for (int j = 0; j < costs[0].size(); ++j) {
int cur_min = INT_MAX;
for (int k = 0; k < costs[0].size(); ++k)
if (k != j)
cur_min = min(cur_min, costs[i - 1][k]);
costs[i][j] += cur_min;
}
}
return costs.size() > 0 ? *min_element(costs.back().begin(),
costs.back().end()) : 0;
}
};
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
vector<int> ret;
set<int> zeros;
long prod = 1;
for (int i = 0; i < nums.size(); ++i)
if (nums[i] == 0)
zeros.insert(i);
else
prod *= nums[i];
for (int i = 0; i < nums.size(); ++i)
if (zeros.size() == 0)
ret.push_back(prod / nums[i]);
else if (zeros.size() == 1 && zeros.count(i))
ret.push_back(prod);
else
ret.push_back(0);
return ret;
}
};
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
vector<int> ret(nums.size(), 1);
for (int i = 1; i < nums.size(); ++i)
ret[i] = ret[i - 1] * nums[i - 1];
int r_prod = 1;
for (int i = nums.size() - 1; i >= 0; --i) {
ret[i] *= r_prod;
r_prod *= nums[i];
}
return ret;
}
};
219. Contains Duplicate II
Description
Solution
#define N 2503
bool containsNearbyDuplicate(int* nums, int numsSize, int k) {
node *hash = malloc(N * sizeof(node));
for (int i = 0; i < N; init(&hash[i], i, 0, NULL), ++i);
for (int i = 0; i < numsSize; insert(&hash[(nums[i] % N + N) % N], nums[i],
1), ++i);
for (int i = 0; i < numsSize; ++i)
if (search(&hash[(nums[i] % N + N) % N], nums[i]))
for (int j = 1; i + j < numsSize && j <= k; ++j)
if (nums[i + j] == nums[i])
return true;
return false;
}
Solution
The idea is to use DFS to identify the island. Once a part of the island has been found, say grid[i][j] ==
'1', then use dfs(grid, i, j) to set the rest of island to be '0'.
class Solution {
public:
int numIslands(vector<vector<char>>& grid) {
int ret = 0;
for (int i = 0; i < grid.size(); ++i)
for (int j = 0; j < grid[0].size(); ++j)
if (grid[i][j] == '1')
++ret, dfs(grid, i, j);
return ret;
}
void dfs(vector<vector<char>>& grid, int i, int j) {
if (i < 0 || i >= grid.size() || j < 0 || j >= grid[0].size() || grid[i]
[j] == '0')
return;
grid[i][j] = '0';
dfs(grid, i - 1, j), dfs(grid, i + 1, j), dfs(grid, i, j - 1), dfs(grid,
i, j + 1);
}
};
C (4 ms, beats 100%):
Solution
The idea is to use Dynamic Programming. We only need to consider skipping one or two houses. If it is
three, we can absolutely rob the one in the middle, hence narrows down to the case of skipping one house.
Therefore, the recurrence is D[n] = max(D[n - 2] + nums[n - 2], D[n - 3] + nums[n - 3]), and
the base case is D[0] = 0, D[1] = 0.
Solution
The idea is
class Solution {
public:
int majorityElement(vector<int>& nums) {
int n = nums.size();
if (n == 1)
return nums[0];
if (n % 2 == 1) {
int count = 1;
for (int i = 0; i < n - 1; ++i)
if (nums[n-1] == nums[i])
++count;
if (count > n / 2)
return nums[n-1];
}
vector<int> numsTmp;
for (int i = 0; i < n / 2; ++i)
if (nums[2 * i] == nums[2 * i + 1])
numsTmp.push_back(nums[2 * i]);
return majorityElement(numsTmp);
}
};
Solution
DFS solution (16 ms): The idea is same as this post. But seems not very effiecient... any suggestion to make
it faster?
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> ret;
if (!root)
return ret;
ret.push_back({root->val});
if (root->left) {
vector<vector<int>> l = levelOrder(root->left);
for (int i = 0; i < l.size(); ++i)
if (i + 1 > ret.size() - 1)
ret.push_back(l[i]);
else
ret[i + 1].insert(ret[i + 1].end(), l[i].begin(),
l[i].end());
}
if (root->right) {
vector<vector<int>> r = levelOrder(root->right);
for (int i = 0; i < r.size(); ++i)
if (i + 1 > ret.size() - 1)
ret.push_back(r[i]);
else
ret[i + 1].insert(ret[i + 1].end(), r[i].begin(),
r[i].end());
}
return ret;
}
};
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> ret;
if (!root)
return ret;
ret.push_back({root->val});
vector<vector<int>> l = levelOrder(root->left);
vector<vector<int>> r = levelOrder(root->right);
merge_vector(&ret, l);
merge_vector(&ret, r);
return ret;
}
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> ret;
if (!root)
return ret;
queue<TreeNode *> q;
q.push(root);
while (!q.empty()) {
vector<int> r;
int n = q.size();
for (int i = 0; i < n; ++i) {
auto cur = q.front(); q.pop();
r.push_back(cur->val);
if (cur->left)
q.push(cur->left);
if (cur->right)
q.push(cur->right);
}
ret.push_back(r);
}
return ret;
}
};
Solution
The idea is to use two arrays, row and col, to record rows and columns that has at zeros. And then set the
corresponding rows and columns to zero according to row and col.
Time complexity: O(N * M) vs. Space complexity: O(N + M), where N and M represent the number of
rows and columns of the given matrix, respectively.
69. Sqrt(x)
Description
Solution
int mySqrt(int x) {
int low = 0, high = x;
while (low < high) {
long mid = (low + high) >> 1;
if (mid * mid <= x)
low = mid + 1;
else
high = mid;
}
return x > 1 ? low - 1 : x;
}
Update: Optimized the code a little bit, as a result, it outperformed the above, and performed just as good
as applying the built-in function sqrt().
int mySqrt(int x) {
int low = 0, high = x;
while (low < high) {
long mid = (low + high) / 2 + 1;
if (mid * mid > x)
high = mid - 1;
else
low = mid;
}
return low;
}
54. Spiral Matrix
Description
Solution
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* spiralOrder(int** matrix, int matrixRowSize, int matrixColSize) {
int d[][2] = { {0, 1}, {1, 0}, {0, -1}, {-1, 0}}, n = matrixRowSize *
matrixColSize;
int *ret = malloc(n * sizeof(int));
for (int i = 0, j = 0, k = 0, cnt = 0; cnt < n; cnt++) {
ret[cnt] = matrix[i][j], matrix[i][j] = INT_MIN;
int ni = i + d[k][0], nj = j + d[k][1];
if (ni < 0 || ni > matrixRowSize - 1 || // if the updated i is out
of bound
nj < 0 || nj > matrixColSize - 1 || // if the updated j is out
of bound
matrix[ni][nj] == INT_MIN) // if the new matrix entry
has been visited
k = (k + 1) % 4;
i = i + d[k][0], j = j + d[k][1];
}
return ret;
}
Solution
The idea is to do the binary search when target and the nums[mid] in the same sorted section. If they are
not, then adjust mid until nums[mid] is. Time complexity: O(log(N)) vs. Space complexity: O(1).
Solution
The idea is to move the fast pointer to the n-th node from the head node first, then move both slow and
fast pointers at the same pace until fast reaches to the end of the linked list, at which slow is just right
before the node to be removed. Remove the node by slow->next = slow->next->next. Done.
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
struct ListNode *fast, *slow;
for (fast = head; fast && fast->next && n > 0; fast = fast->next, n--);
for (slow = head; fast && fast->next; fast = fast->next, slow = slow->next);
if (slow && n == 0)
slow->next = slow->next->next;
return n == 1 ? head->next : head;
}
Solution
The idea is very simple: just sum up the value of each symbol and change the sign if it appears before the
symbol that is greater than itself, e.g., I before V or X.
int romanToInt(char* s) {
int ret = 0;
for (int i = 0; s[i]; i++) {
switch (s[i]) {
case 'I': ret += s[i + 1] && (s[i + 1] == 'V' || s[i + 1] == 'X') ?
-1 : 1; break;
case 'X': ret += s[i + 1] && (s[i + 1] == 'L' || s[i + 1] == 'C') ?
-10 : 10; break;
case 'C': ret += s[i + 1] && (s[i + 1] == 'D' || s[i + 1] == 'M') ?
-100 : 100; break;
case 'V': ret += 5; break;
case 'L': ret += 50; break;
case 'D': ret += 500; break;
case 'M': ret += 1000; break;
}
}
return ret;
}
Solution
The idea is straightforward: use two loops to find out the maximum area.