Last month of 2020! Except went to wework office in Feburary, all other days I have been working from home. Let’s continue December LeetCoding Challenge.
Week 1: December 1st - December 7th
Shortest Word Distance
Given a list of words and two words word1 and word2, return the shortest distance between these two words in the list.
Example:
Assume that words = ["practice", "makes", "perfect", "coding", "makes"]
.
1 |
|
1 |
|
Note:
You may assume that word1 does not equal to word2, and word1 and word2 are both in the list.
Explanation
- We can use
idx1
points to the most recentword1
’s index andidx2
points to the most recentword2
’s index. Loop all the words, when we find both words, we can calculate their distance byabs(idx1 - idx2)
.
Solution
1 |
|
Maximum Depth of Binary Tree
Given the root
of a binary tree, return its maximum depth.
A binary tree’s maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Example 4:
1 |
|
Constraints:
-
The number of nodes in the tree is in the range
[0, 10^4]
. -
-100 <= Node.val <= 100
Explanation
-
We want to find the maximum height of the tree, which means we need to find the height of the left subtree plus one and the height of the right subtree plus one. Compare both and take the maximum.
-
The base case is if the root tree node is NULL, we return 0.
Solution
1 |
|
Linked List Random Node
Given a singly linked list, return a random node’s value from the linked list. Each node must have the same probability of being chosen.
Follow up:
What if the linked list is extremely large and its length is unknown to you? Could you solve this efficiently without using extra space?
Example:
1 |
|
Explanation
- We don’t need to know the size of the linked list, we can use Reservoir Sampling to solve this problem.
Solution
1 |
|
Increasing Order Search Tree
Given the root
of a binary search tree, rearrange the tree in in-order so that the leftmost node in the tree is now the root of the tree, and every node has no left child and only one right child.
Example 1:
1 |
|
Example 2:
1 |
|
Constraints:
-
The number of nodes in the given tree will be in the range
[1, 100]
. -
0 <= Node.val <= 1000
Explanation 1
-
We can traverse the tree using in-order traversal and store every node into a list.
-
After traversing all the nodes and store into a list, we can generate the result tree by traversing the list.
Solution 1
1 |
|
Explanation 2
- We can generate the result tree on the fly when we are traversing, we just need a global pointer
cur
pointing to the right leaf of the result tree, then every node is added tocur.right
then we updatecur = cur.right
.
Solution 2
1 |
|
The kth Factor of n
Given two positive integers n
and k
.
A factor of an integer n
is defined as an integer i
where n % i == 0
.
Consider a list of all factors of n
sorted in ascending order, return the kth
factor in this list or return -1 if n
has less than k
factors.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Example 4:
1 |
|
Example 5:
1 |
|
Constraints:
1 <= k <= n <= 1000
Hint 1:
The factors of n will be always in the range [1, n].
Hint 2:
Keep a list of all factors sorted. Loop i from 1 to n and add i if n % i == 0. Return the kth factor if it exist in this list.
Explanation 1
- We can solve this in O(n) time complexity. Loop
i
from 1 ton
inclusive, if we find a factor then we decreasek
. Whenk
is 0, we return the factori
. After the loop, that means we can’t find thek
th factor so we return -1.
Solution 1
1 |
|
Explanation 2
-
We can solve this in O(sqrt(n)) time complexity. If
n = 16
, when we find a factor 1, then we know 16 is 1’s corresponding factor; when we find a factor 2, then 8 is its corresponding factor; when we find a factor 4, then 4 is itself’s corresponding factor. So we can loop from 1 tosqrt(n)
inclusive then we find all the factors as[1, 2, 4, 8, 16]
. -
First, we loop
i
from 1 to 2 inclusive. Whenn % i == 0 && --k == 0
, then we knowi
is thek
th factor. -
After the above loop, that means
k
is in the second half. We can loopi
from 4 to 1 backward inclusive. Whenn % i == 0 && --k == 0
, then thek
th factor is the factori
’s corresponding factorn / i
.
Solution 2
1 |
|
Can Place Flowers
You have a long flowerbed in which some of the plots are planted, and some are not. However, flowers cannot be planted in adjacent plots.
Given an integer array flowerbed
containing 0
’s and 1
’s, where 0
means empty and 1
means not empty, and an integer n
, return if n
new flowers can be planted in the flowerbed
without violating the no-adjacent-flowers rule.
Example 1:
1 |
|
Example 2:
1 |
|
Constraints:
-
1 <= flowerbed.length <= 2 * 10^4
-
flowerbed[i]
is0
or1
. -
There are no two adjacent flowers in
flowerbed
. -
0 <= n <= flowerbed.length
Explanation
-
We can use greedy approach to solve this problem. Loop through the input array, if the current element is 1, then we skip. If the current element is 0, then we check if its left neighbor and right neighbor are also 0, then we can place the flower.
-
Cornor case is the first and last element. If we are on the first element, we only check the right neighbor. If we are on the last element, then we only check the left neighbor.
Solution
1 |
|
Populating Next Right Pointers in Each Node II
Given a binary tree
1 |
|
Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL
.
Initially, all next pointers are set to NULL
.
Follow up:
-
You may only use constant extra space.
-
Recursive approach is fine, you may assume implicit stack space does not count as extra space for this problem.
Example 1:
1 |
|
Constraints:
-
The number of nodes in the given tree is less than
6000
. -
-100 <= node.val <= 100
Explanation
- This solution uses O(1) space and it is iterating level by level. First, we create a dummy list that is used to pointing to each level’s element before the first element. We create a
cur
pointer initially points todummy
and it is used to connect the current level’s element. First, if the left subnode exists,cur.next
connects it, then iteratecur = cur.next
. If the right subnode exists,cur.next
connects it, then iteratecur = cur.next
. Now, the root’s left and right subnodes are connected. Then, we moveroot
to the right. After we move, ifroot
is not exist, then it means we finish connecting to current root node’s sub node. We then resetroot
to dummy’s next node,cur
reset pointing todummy
, and we setdummy
’s next to null because we want thecur
pointer’s next to NULL so that we can usecur.next
to point to the first element in the next level.
Solution
1 |
|
Spiral Matrix II
Given a positive integer n
, generate an n x n
matrix
filled with elements from 1
to n^2
in spiral order.
Example 1:
1 |
|
Example 2:
1 |
|
Constraints:
1 <= n <= 20
Explanation
- Similar to 54. Spiral Matrix, we create
top, right, bottom, left
variables. Then create acounter
starts from 1, fill the matrix. Whentop == bottom
orleft == right
, since it’s a square matrix, we check if inputn
is an odd number or not. If it’s event, then we are done. If it’s odd, there’s a middle element, and the middle element position will bematrix[n/2][n/2]
, so we fill it with thecounter
. Finally return the filled matrix.
Solution
1 |
|
Week 2: December 8th - December 14th
Missing Ranges
You are given an inclusive range [lower, upper]
and a sorted unique integer array nums
, where all elements are in the inclusive range.
A number x
is considered missing if x
is in the range [lower, upper]
and x
is not in nums
.
Return the smallest sorted list of ranges that cover every missing number exactly. That is, no element of nums
is in any of the ranges, and each missing number is in one of the ranges.
Each range [a,b]
in the list should be output as:
-
"a->b" if a != b
-
"a" if a == b
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Example 4:
1 |
|
Example 5:
1 |
|
Constraints:
-
-10^9 <= lower <= upper <= 10^9
-
0 <= nums.length <= 10^0
-
lower <= nums[i] <= upper
-
All the values of
nums
are unique.
Explanation
- We can use brute force to solve this problem. First initialize a counter
cnt = lower
. Loop through the array, ifcnt
is less thannums[i]
. Then we can add the range[cnt, nums[i]-1]
to the result list. Each iteration, we updatecnt = nums[i] + 1
. Outside the loop, we comparecnt
withupper
. Ifcnt
is greater thanupper
that means the last element in the array is equal toupper
so we can just return the result list. Else, that means the last element in the array is smaller thanupper
, so we add the range[cnt, upper]
into the result list and return the list.
Solution
1 |
|
Pairs of Songs With Total Durations Divisible by 60
You are given a list of songs where the ith song has a duration of time[i]
seconds.
Return the number of pairs of songs for which their total duration in seconds is divisible by 60
. Formally, we want the number of indices i
, j
such that i < j
with (time[i] + time[j]) % 60 == 0
.
Example 1:
1 |
|
Example 2:
1 |
|
Constraints:
-
1 <= time.length <= 6 * 10^4
-
1 <= time[i] <= 500
Hint 1:
We only need to consider each song length modulo 60.
Hint 2:
We can count the number of songs with (length % 60) equal to r, and store that in an array of size 60.
Explanation
-
We can create an array of size 60,
arr[i]
represents the number of times we visited elementi
. If the current element is 20, then the target element is 60 - 20 = 40, the result will increasearr[40]
. Each element we can module it by 60 since if element is 20 or 80, their target element is 40. -
Special case is when current element is 60, we module it by 60, then it means current element is 0. Its target element is 60 - 0 = 60, and arr[60] is out of bound. Actually every element is in the range [0, 59] since we module each element by 60, so 0’s target element is also 0. So we can use
(60 - t) % 60
as the target element.
Solution
1 |
|
Binary Search Tree Iterator
Implement the BSTIterator
class that represents an iterator over the in-order traversal of a binary search tree (BST):
-
BSTIterator(TreeNode root)
Initializes an object of theBSTIterator
class. Theroot
of the BST is given as part of the constructor. The pointer should be initialized to a non-existent number smaller than any element in the BST. -
boolean hasNext()
Returnstrue
if there exists a number in the traversal to the right of the pointer, otherwise returnsfalse
. -
int next()
Moves the pointer to the right, then returns the number at the pointer.
Notice that by initializing the pointer to a non-existent smallest number, the first call to next()
will return the smallest element in the BST.
You may assume that next()
calls will always be valid. That is, there will be at least a next number in the in-order traversal when next()
is called.
Example 1
1 |
|
Constraints:
-
The number of nodes in the tree is in the range
[1, 10^5]
. -
0 <= Node.val <= 10^6
-
At most
10^5
calls will be made tohasNext
, andnext
.
Follow up:
- Could you implement
next()
andhasNext()
to run in averageO(1)
time and useO(h)
memory, whereh
is the height of the tree?
Explanation
-
In the constructor, we can use in-order traversal iterative way to store the left child elements into a stack.
-
In the
hasNext
function, we can check if stack is empty. If not empty, then return true. -
In the
next
function, we can return the pop node element. Also, we check if that pop node has right child, if it has right child, then we think of that right child is the root, and we push that “root” and all its left nodes to the stack like we did in the step 1.
Solution
1 |
|
Valid Mountain Array
Given an array of integers arr
, return true
if and only if it is a valid mountain array.
Recall that arr is a mountain array if and only if:
-
arr.length >= 3
-
There exists some
i
with0 < i < arr.length - 1
such that:-
arr[0] < arr[1] < ... < arr[i - 1] < A[i]
-
arr[i] > arr[i + 1] > ... > arr[arr.length - 1]
-
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Constraints:
-
1 <= arr.length <= 10^4
-
0 <= arr[i] <= 10^4
Hint 1:
It’s very easy to keep track of a monotonically increasing or decreasing ordering of elements. You just need to be able to determine the start of the valley in the mountain and from that point onwards, it should be a valley i.e. no mini-hills after that. Use this information in regards to the values in the array and you will be able to come up with a straightforward solution.
Explanation
-
A valid mountain array can only has exactly one increasing and one decreasing Also, we see
increasing
first, thendecreasing
. -
Loop through the array. If
arr[i-1] < arr[i]
then we updateincreasing = true
. Also we check ifdecreasing
is true or not. Ifdecreasing
is also true that means we seedecreasing
in frontincreasing
so we return false. Ifarr[i-1] > arr[i]
, then we just updatedecreasing = true
. Else ifarr[i-1] == arr[i]
, then we can return false immediately. -
At the end, if
increasing
anddecreasing
both are true, then we return true, else return false.
Solution
1 |
|
Remove Duplicates from Sorted Array II
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.
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 a modification to the input array will be known to the caller.
Internally you can think of this:
1 |
|
Example 1:
1 |
|
Example 2:
1 |
|
Constraints:
-
0 <= nums.length <= 3 * 10^4
-
-10^4 <= nums[i] <= 10^4
-
nums
is sorted in ascending order.
Explanation
-
First, we start from the third element because we can have two duplicated, so it doesn’t matter if the first two elements are the same or not. We also use currentPointer and fastPointer technique to solve this problem. Initially, the current pointer and the fastPointer are pointing at the third element. The currentPointer is used to store the next valid element, the fastPointer is used to iterate the input array until it hits the end.
-
We can compare the fast pointer element with the currentPointer-1 index element and currentPointer-2 index element, if they are the same, then it means there are already two same elements before the currentPointer index. Else, we can set the currentPointer index’s value to the fastPointer’s pointing value.
Solution
1 |
|
Smallest Subtree with all the Deepest Nodes
Given the root
of a binary tree, the depth of each node is the shortest distance to the root.
Return the smallest subtree such that it contains all the deepest nodes in the original tree.
A node is called the deepest if it has the largest depth possible among any node in the entire tree.
The subtree of a node is tree consisting of that node, plus the set of all descendants of that node.
Note: This question is the same as 1123: https://leetcode.com/problems/lowest-common-ancestor-of-deepest-leaves/
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Constraints:
-
The number of nodes in the tree will be in the range
[1, 500]
. -
0 <= Node.val <= 500
-
The values of the nodes in the tree are unique.
Explanation 1
- If the left child and right child’s height are the same, then the smallest subtree with all the deepest nodes (result node) must be the root node. Else left child height is higher than the right child height, then the result node will be inside the left subtree, so we recursively call the main function with the left child node; else if right child height is higher, then the result node will be in the right subtree, so we call the main function with the right child node.
Solution 1
1 |
|
Explanation 2
- There are many duplicate computation from the above solution, we can improve it. Instead of just returning the height in the helper function, we return the height and the smallest subtree with all the deepest nodes, in other words, we return the height and the result node.
Solution 2
1 |
|
Burst Balloons
Given n
balloons, indexed from 0
to n-1
. Each balloon is painted with a number on it represented by array nums
. You are asked to burst all the balloons. If the you burst balloon i
you will get nums[left] * nums[i] * nums[right]
coins. Here left
and right
are adjacent indices of i
. After the burst, the left
and right
then becomes adjacent.
Find the maximum coins you can collect by bursting the balloons wisely.
Note:
-
You may imagine
nums[-1] = nums[n] = 1
. They are not real therefore you can not burst them. -
0 ≤
n
≤ 500, 0 ≤nums[i]
≤ 100
Example:
1 |
|
Explanation
-
We can use dynamic programming to solve this problem.
-
Dynamic state is
dp[left][right]
, it means the maximum coins that can get betweenleft+1
toright-1
inclusive. We will add1
to the beginning and the end of the array as the updated array. So the dynamic result will bedp[0][n-1]
,n
is the number of elements in the updated array. If the input array is[2, 5, 3]
, then the udpated array will be[1, 2, 5, 3, 1]
. We will finddp[0][5-1]
. -
Dynamic init will be all
dp[left][right]
be zero. -
If input array is
[2, 5, 3]
, updated array is[1, 2, 5, 3, 1]
, we will finddp[left=0][right=5-1=4]
. Ifi=5
, and it is the last element we burst, then its coin will be1*5*1
;2
and3
are already burst before5
, so we will add their coins, which are1*2*5
and5*3*1
. In other words, adddp[left][i]
anddp[i][right]
. Remember the dynamic state isdp[left][right]
, it means the maximum coins that can get betweenleft+1
toright-1
inclusive. So, our dynamic function isdp[left][right] = max(dp[left][right], coins[i]*coins[left]*coins[right] + dp[left][i] + dp[i][right])
. -
If input array has only one element, for example
[2]
, then the updated array will have length 3, which is[1, 2, 1]
.left
andright
will have max distance 2 (rightIndex - leftIndex), and the result will bedp[0, 2]
. Also, 2 is also the minimum distance. If input array is[2, 3]
, then updated array is[1, 2, 3, 1]
, which has max distance 3 betweenleft
andright
. At the beginning, we can first find out all the result of the smallest distancedp
, in other words, the smallest sub array result, then we find the larger distance sub array result. So we will find subarray[1, 2, 3]
and subarray[2, 3, 1]
, then find the whole array[1, 2, 3, 1]
. If the last ballon we burst is 2, then we have coin1*2*1
, and3
is already burst before 2, so we have coin2*3*1
, which is the result of the subarraydp[2, 3, 1]
, so the totoal coin is1*2*1+2*3*1
. If the last ballon we burst is 3, then we have coin1*3*1
, and2
is already burst before 3, so we have coin1*2*3
, which is the result of the subarraydp[1, 2, 3]
, so the total coin is1*3*1+1*2*3
. At the end, we compare both result and take the maximum as the final result for the updated array[1, 2, 3, 1]
. -
So, we first loop through distance, then loop through the
left
starting point, andright
will beright = left + distance
. Then, we loop throughi
, which isleft < i < right
, to choose which element is the last element we burst. Then we use our dynamic functiondp[left][right] = max(dp[left][right], coins[i]*coins[left]*coins[right] + dp[left][i] + dp[i][right])
to update the solution. -
At the end, we return the dynamic result
dp[0][n-1]
. If input array is[2]
, updated array is[1, 2, 1]
, dynamic result will bedp[0][3-1]
.
Solution
1 |
|
Palindrome Partitioning
Given a string s
, partition s
such that every substring of the partition is a palindrome. Return all possible palindrome partitioning of s
.
A palindrome string is a string that reads the same backward as forward.
Example 1:
1 |
|
Example 2:
1 |
|
Constraints:
-
1 <= s.length <= 16
-
s
contains only lowercase English letters.
Explanation
-
First create a function to check whether a string is palindrome.
-
We can use backtracking to find all combination, if a substring is palindrome, then we start from the next character of the substring and check. For example, “abac”, when we check “aba” is a palindrome, then we check start from “c”.
Solution
1 |
|
Week 3: December 15th - December 21st
Plus One Linked List
Given a non-negative integer represented as a linked list of digits, plus one to the integer.
The digits are stored such that the most significant digit is at the head
of the list.
Example 1:
1 |
|
Example 2:
1 |
|
Constraints:
-
The number of nodes in the linked list is in the range
[1, 100]
. -
0 <= Node.val <= 9
-
The number represented by the linked list does not contain leading zeros except for the zero itself.
Explanation
-
First, we create a dummy node and connect it before the
head
. -
Then we find the right most digit that is not equal to 9, initially this non-nine node points to dummy.
-
Increase the right most non-nine node’s value by 1, and set all its following node to value 0.
-
If the non-nine node is still points to dummy, that means the link list’s all digits are 0, so we return
dummy
. Else, we returndummy.next
which is the originalhead
.
Solution
1 |
|
Squares of a Sorted Array
Given an integer array nums
sorted in non-decreasing order, return an array of the squares of each number sorted in non-decreasing order.
Example 1:
1 |
|
Example 2:
1 |
|
Constraints:
-
1 <= nums.length <= 10^4
-
-10^4 <= nums[i] <= 10^4
-
nums
is sorted in non-decreasing order.
Explanation 1
-
We can use two pointers to solve this problem. For negative number, the larger negative number has smaller square. For non-negative number, the smaller positive number has the smaller square. First, we need to find the first non-negative number’s index, then we use a
right
pointer points to this index, and use aleft
pointer points to index atright - 1
. We will comparenums[left]
andnums[right]
, ifnums[left]
is smaller, then we append it into the result array and decreaseleft
; else we appendnums[right]
into the array and increaseright
. -
Corner case are if the first number of the input array is equal or greater than 0, then we simply one loop and each iteration we put the square of the iterated number into the result array. If the last number of the input array is negative, then we simply loop from right to left and each iteration, we put the iterated number’s square into the array.
Solution 1
1 |
|
Explanation 2
- We can also start to find the larger square first. For negative number, the larger square is at index 0 so we use
left
pointer points at 0. For non-negative number, the larger square is at the last index of the array so we useright
pointer points at last index of the array. If the right square (nums[right] * nums[right]
) is larger, then we prepend the right square at end of the result array and decreaseright
pointer. Else if the left square (nums[left] * nums[left]
) is larger, then we prepend the left square and increaseleft
pointer.
Solution 2
1 |
|
Validate Binary Search Tree
Given the root
of a binary tree, determine if it is a valid binary search tree (BST).
A valid BST is defined as follows:
-
The left subtree of a node contains only nodes with keys less than the node’s key.
-
The right subtree of a node contains only nodes with keys greater than the node’s key.
-
Both the left and right subtrees must also be binary search trees.
Example 1:
1 |
|
Example 2:
1 |
|
Constraints:
-
The number of nodes in the tree is in the range
[1, 10^4]
. -
-2^31 <= Node.val <= 2^31 - 1
Explanation
-
We can solve this problem using in-order traversal.
-
When we are iterating, we can compare the current node’s value with previous node’s value. If previous node’s value is greater than or equal to current iterated node’s value, we can return false immediately.
-
We can initialize the previouse node value as
null
. -
In the helper function, if current node is null, we need to return true.
Solution
1 |
|
4Sum II
Given four lists A, B, C, D of integer values, compute how many tuples (i, j, k, l)
there are such that A[i] + B[j] + C[k] + D[l]
is zero.
To make problem a bit easier, all A, B, C, D have same length of N where 0 ≤ N ≤ 500. All integers are in the range of -2^28 to 2^28 - 1 and the result is guaranteed to be at most 2^31 - 1.
Example:
1 |
|
Explanation
-
Similar to Two Sum, in Two Sum, we iterate the list and push elements as key into a HashMap, its index as value. Then loop the list again to find the target, which is
0-arr[i]
, from the HashMap. -
Now if we iterate 4 lists, then we need n4 runtime. We can reduce it to n2 by iterating every elements of ListA and ListB. Push all the sums as key to a HashMap and value will be the sums’ frequency.
-
Next, we iterate every elements of ListC and ListD, calculate the sums, target will be
0-sum
, from the HashMap, accumulate the frequency to result.
Solution
1 |
|
Increasing Triplet Subsequence
Given an integer array nums
, return true
if there exists a triple of indices (i, j, k)
such that i < j < k
and nums[i] < nums[j] < nums[k]
. If no such indices exists, return false
.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Constraints:
-
1 <= nums.length <= 105
-
-2^31 <= nums[i] <= 2^31 - 1
Follow up: Could you implement a solution that runs in O(n)
time complexity and O(1)
space complexity?
Explanation 1
-
We create an array
dp[i]
, which means beforenums[i]
, the number of elements that are less thannums[i]
. We initializedp[]
has the same length asnums[]
and all the values initialize to 1. -
For every
nums[i]
, we loop every element (nums[j]
) beforenums[i]
, ifnums[j] < nums[i]
, then we updatedp[i] = dp[j] + 1
. -
If
dp[i] == 3
, that means there are two elements before it are less thannums[i]
, so we returntrue
. Else after checking every element, we returnfalse
.
Solution 1
1 |
|
Explanation 2
- We want to three numbers that stisify
m1 < m2 < nums[i]
. First, we create two variablesm1
andm2
that equals to maximum integer. Next, we loop through every element in the array, ifnums[i] <= m1
, then we updatem1 = nums[i]
; else ifnums[i] > m1 && nums[i] <= m2
, then we udpatem2
; else ifm1 < nums[i] && m2 < nums[i]
, then we returntrue
. After looping all elements, if we don’t returntrue
, then we returnfalse
.
Solution 2
1 |
|
Explanation 3
- We create two arrays
forward[]
andbackward[]
.forward[i]
means the minimum elements that are from index 0 to index i (inclusive).backward[i]
means the maximum elements that are from index i to the last index (inclusive). We initializeforward[0] = nums[0]
and loop from index 1 to last index, updateforward[i]
. Next, we initializebackward[nums.length-1] = nums[nums.length-1]
, loop from indexnums.length-2
to index 0, updatebackward[i]
. After we updating bothforward[]
andbackward[]
, we loopnums[]
from index 0 to last index. Ifforward[i] < nums[i] && nums[i] < backward[i]
, we returntrue
. Else after finish looping, we returnfalse
.
Solution 3
1 |
|
Cherry Pickup II
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:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Example 4:
1 |
|
Constraints:
-
rows == grid.length
-
cols == grid[i].length
-
2 <= rows, cols <= 70
-
0 <= grid[i][j] <= 100
Hint 1:
Use dynammic programming, define DP[i][j][k]: The maximum cherries that both robots can take starting on the ith row, and column j and k of Robot 1 and 2 respectively.
Explanation
-
We can use dynamic programming to solve this problem. Dynamic state is
dp[r][col1][col2]
which represents the maximum cherries that both robots can take starting on the ith row, and column j and k of Robot 1 and 2 respectively. For each row, we need to check all the combinations of robot1’s column and robot2’s column and that’s why we need a 3 dimensional arraydp[r][col1][col2]
. -
First, we initialize all the dp elements to -1, so
dp[r][col1][col2]
represents both robots cannot reachgrid[r][col1]
andgrid[r][col2]
. Dynamic init isdp[0][0][col] = grid[0][0] + grid[0][col]
since both robots start from these two points. -
Dynamic function is
dp[r][col1][col2] = max(dp[r][col1][col2], prev + grid[r][col1] + grid[r][col2])
whereprev = dp[r-1][c1][c2]
andcol1
can be one of[c1-1, c1, c1+1]
, and similarlly forcol2
can be one of[c2-1, c2, c2+1]
. Ifcol1
is equal tocol2
, then instead ofprev + grid[r][col1] + grid[r][col2]
, we only need to plus one of them soprev + grid[r][col1]
because when both robots stay on the same cell, only one of them takes the cherries. Every time we updatedp[r][col1][col2]
, we need to keep track of the maximum resultres
. -
At the end, we return the maximum result
res
.
Solution
1 |
|
Decoded String at Index
An encoded string S
is given. To find and write the decoded string to a tape, the encoded string is read one character at a time and the following steps are taken:
-
If the character read is a letter, that letter is written onto the tape.
-
If the character read is a digit (say
d
), the entire current tape is repeatedly writtend-1
more times in total.
Now for some encoded string S
, and an index K
, find and return the K
-th letter (1 indexed) in the decoded string.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Constraints:
-
2 <= S.length <= 100
-
S
will only contain lowercase letters and digits2
through9
. -
S
starts with a letter. -
1 <= K <= 10^9
-
It’s guaranteed that
K
is less than or equal to the length of the decoded string. -
The decoded string is guaranteed to have less than
2^63
letters.
Explanation
-
If we have a decoded string like
appleappleappleappleappleapple
and an index likeK = 24
, the answer is the same ifK = 4
. -
In general, when a decoded string is equal to some word with
size
length repeated some number of times (such as apple withsize = 5
repeated 6 times), the answer is the same for the indexK
as it is for the indexK % size
. -
We can use this insight by working backwards, keeping track of the size of the decoded string. Whenever the decoded string would equal some word repeated d times, we can reduce
K
toK % (word.length)
. -
First, find the length of the decoded string, when
size
is greater than or equal toK
we can stop here. After, we’ll work backwards, keeping track ofsize
: the length of the decoded string after parsing symbolsS[0], S[1], ..., S[i]
. -
If we see a digit
S[i]
, it means the size of the decoded string after parsingS[0], S[1], ..., S[i-1]
will besize / Integer(S[i])
. Otherwise, it will besize - 1
. -
Corner case is
size
should be typelong
.
Source: 880. Decoded String at Index Solution
Solution
1 |
|
Smallest Range II
Given an array A
of integers, for each integer A[i]
we need to choose either x = -K
or x = K
, and add x
to A[i] (only once)
.
After this process, we have some array B
.
Return the smallest possible difference between the maximum value of B
and the minimum value of B
.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Note:
-
1 <= A.length <= 10000
-
0 <= A[i] <= 10000
-
0 <= K <= 10000
Explanation
-
First, we sort the array.
-
We want to find the smallest difference between the maximum value and minimum value in the new array, so we will try to in the original array plus K for the minimum value and subtract K for the minimum value.
-
We can divide the original array into two half
A[0: i]
andA[i+1: len(A)]
. In the first half array, we will plus K for every element; in the second half, we will subtract K for every element. So in the first half, the minimum value isA[0] + K
and the maximum value isA[i] + K
. In the second half, the minimum value isA[i+1] - K
and the maximum value isA[len(A)-1] - K
. Therefore, in the entire new array, the minimum value ismin(A[0] + K, A[i+1] - K)
and the maximum value ismax(A[i] + K, A[len(A)-1] - K)
. So, we can iteratei
and each iteration, we calculate the minimum difference.
Solution
1 |
|
Week 4: December 22nd - December 28th
Find Nearest Right Node in Binary Tree
Given the root
of a binary tree and a node u
in the tree, return the nearest node on the same level that is to the right of u
, or return null
if u
is the rightmost node in its level.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Example 4:
1 |
|
Constraints:
-
The number of nodes in the tree is in the range
[1, 10^5]
. -
1 <= Node.val <= 10^5
-
All values in the tree are distinct.
-
u
is a node in the binary tree rooted atroot
.
Hint 1:
Use BFS, traverse the tree level by level and always push the left node first
Hint 2:
When you reach the target node, mark a boolean variable true
Hint 3:
If you meet another node in the same level after marking the boolean true, return this node.
Hint 4:
If you did not meet new nodes in the same level and started traversing a new level, return Null
Explanation
- We can use level-order traversal to solve this problem. When we find the target node, we can check if the current
i
is at the end of the current level, then we returnnull
, else we return the next node of the queue.
Solution
1 |
|
Balanced Binary Tree
Given a binary tree, determine if it is height-balanced.
For this problem, a height-balanced binary tree is defined as:
a binary tree in which the left and right subtrees of every node differ in height by no more than 1.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Constraints:
-
The number of nodes in the tree is in the range
[0, 5000]
. -
-10^4 <= Node.val <= 10^4
Explanation
-
This problem is very similar to 865. Smallest Subtree with all the Deepest Nodes. We need to find the left subtree’s height and right subtree’s height, then compare these two height’s difference. If the difference is less than or equal to 1, then it’s balanced, else it’s unbalanced. So this problem can be solved by using post-order traversal.
-
It is possible that the left subtree and right subtree’s height are the same, but left subtree or right subtree is unbalanced, so we need to recursively run the main function to check if left subtree is balanced or not, and run the main function to check if the right subtree is balanced or not.
-
Above solution requires us to calculate the height of the subtree multiple times. To improve time complexity, instead of just returning the height in the helper function, we can return the height and a boolean value to indicate if the subtree is balanced or not. So, if the left subtree is unbalanced, then we can return
1 + leftSubtreeHeight
andfalse
immediately and skip checking right subtree, vice versa. If left subtree and right subtree are balanced, then we can return1 + max(leftHeight, rightHeight)
andtrue
.
Solution
1 |
|
Next Greater Element III
Given a positive integer n
, find the smallest integer which has exactly the same digits existing in the integer n
and is greater in value than n
. If no such positive integer exists, return -1
.
Note that the returned integer should fit in 32-bit integer, if there is a valid answer but it does not fit in 32-bit integer, return -1
.
Example 1:
1 |
|
Example 2:
1 |
|
Constraints:
1 <= n <= 2^31 - 1
Explanation
-
If the input is 12443322, then the result should be 13222344. We observe that the reason the number becomes large is the first 2 change to be 3. Also, after this position, the rest of the numbers becomes from decreasing to increasing.
-
The reason we choose to update the first 2 is from the right to left, 2 is the first number less than its right number. If the whole input number is decreasing order (i.e. 443322), then we can’t reorder it to get the larger number, so we return -1.
-
The reason we choose 3 to swap with the first 2 is from the right to left, 3 is the first number greater than 2.
-
After we swap, we need to sort or reverse all the digits after the first 2, so they become increasing.
Solution
1 |
|
Swap Nodes in Pairs
Given a linked list, swap every two adjacent nodes and return its head.
You may not modify the values in the list’s nodes. Only nodes itself may be changed.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Constraints:
-
The number of nodes in the list is in the range
[0, 100]
. -
0 <= Node.val <= 100
Explanation
-
From the problem example, we need to swap 1 and 2, then swap 3 and 4. In order to swap 3 and 4, we need a pointer that can point both node. In this case, to swap 3 and 4, we need a pre-node pointing at 2, this pre-node can represent 3 using
pre.next
and represent 4 usingpre.next.next
. So, in order to swap the first two elements, we need to create a dummy node in front of the input’s head. -
Now, the node become this:
pre->1->2->3->4
. The solution basically do:1
2
3pre->2->3->4 1->3->4 pre->2->1->3->4
-
After we swap, we move the
pre
pointing topre.next.next
and repeat the above process.
Solution
1 |
|
Diagonal Traverse
Given a matrix of M x N elements (M rows, N columns), return all elements of the matrix in diagonal order as shown in the below image.
Example:
1 |
|
Note:
The total number of elements of the given matrix will not exceed 10,000.
Explanation
-
We either go up right or down left directions. We also need to consider 4 different edge cases.
- When go up right direction, current position hit top border, we should move right (
c = c + 1
). - When go up right direction, current position hit right border, we should move down (
r = r + 1
). - When go down left direction, current position hit left border, we should move down (
r = r + 1
). - When go down left direction, current position hit bottom border, we should move right (
c = c + 1
).
- When go up right direction, current position hit top border, we should move right (
-
If in up right direction, current position is on top right corner exactly, then we move down. If in down left direction, current position is on bottom left corner exactly, then we move right.
Solution
1 |
|
Decode Ways
A message containing letters from A-Z
is being encoded to numbers using the following mapping:
1 |
|
Given a non-empty string containing only digits, determine the total number of ways to decode it.
The answer is guaranteed to fit in a 32-bit integer.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Example 4:
1 |
|
Constraints:
-
1 <= s.length <= 100
-
s
contains only digits and may contain leading zero(s).
Explanation 1
-
We can use dynamic programming to solve this problem.
-
Dynamic state is a one dimensional array,
dp[s.length()+1]
, and itsi
index element is the decode ways of the substring choosing the firsti
character. For example, let input strings=123
, thendp[1]
is the decode way of1
;dp[2]
is the decode way of12
;dp[3]
is the decode way of123
; -
Dynamic init is
dp[1]=1
,dp[0]=1
because later we want the dynamic function to bedp[i] = dp[i-1] + dp[i-2]
, sodp[2] = dp[1] + dp[0]
, so we need to setdp[0]
to some value,dp[0]
is 1 because in general case, for example strings="12"
, we know the decode way is 2;s="1"
, we know the decode way is 1, so we setdp[1]=1
, sodp[0]=1
. -
Dynamic function in general case is
dp[i] = dp[i-1] + dp[i-2]
. For example,s = "123"
, ifi
is iterating at character 3, then we can think of 3 as a group, 12 as another group, in this cases = "123"
its decode way is the same the decode way ofs=12
, in other word,dp[i] = dp[i-1]
. Beside this, we can think of 23 as a group, 1 as another group, in this case, its decode way is the same whens=1
, in other word,dp[i] = dp[i-2]
. -
There are some special case of the above dynamic function. If the string is “120”, the current iterated element is 0, then we cannot think of 0 as a group, we need to consider “20” as a group, 1 as another group, so
dp[i] = dp[i-2]
. Also, if the string is “130” or “100”, then we cannot think of “0”, “30”, or “00” as a group, there is actually no way to decode such string. One more special case is whens=103
, we can think of3
as a group and10
as another group, sodp[i]=dp[i-1]
, but we cannot think of03
as group, so we cannot usedp[i]=dp[i-2]
. -
Dynamic result is
dp[s.length()]
, which means return the decode way when we choose all the elements.
Solution 1
1 |
|
Explanation 2
-
We can also use recursion to solve this problem. For example if the input string is
"123"
. If we think of1
as a group, then the number of decode way for123
is the same as the number of decode way for23
. -
If the input string is
"23"
. if we think of2
as a group, then the number of decode way for23
is the same as the number of decode way for3
. -
Base case is if the input string length is 1 and it’s not equal to
"0"
, then we return 1. Since we know that"23"
can have total of 2 ways to decode. One way is when we think of2
as a group, so3
as another group, so we return 1. Another way is when we think of23
as a group, so an empty string""
as another group, but we still return 1. So another base case is if the input string is an empty string, we return 1. -
When we think of some number as a group, we need to check this number is between 1 to 26 first.
Solution 2
1 |
|
Jump Game IV
Given an array of integers arr
, you are initially positioned at the first index of the array.
In one step you can jump from index i
to index:
-
i + 1
where:i + 1 < arr.length
. -
i - 1
where:i - 1 >= 0
. -
j
where:arr[i] == arr[j]
andi != j
.
Return the minimum number of steps to reach the last index of the array.
Notice that you can not jump outside of the array at any time.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Example 4:
1 |
|
Example 5:
1 |
|
Constraints:
-
1 <= arr.length <= 5 * 10^4
-
-10^8 <= arr[i] <= 10^8
Hint 1:
Build a graph of n nodes where nodes are the indices of the array and edges for node i are nodes i+1, i-1, j where arr[i] == arr[j].
Hint 2:
Start bfs from node 0 and keep distance, answer is the distance when you reach onode n-1.
Explanation
-
We can solve this problem using brute force with BFS. For example, if the input array is
[1, 2, 7, 1, 5, 1, 8]
. Start from the first number, using 1 step, we can go to[num2, secondNum1, thirdNum1]
. Then, start from[num2, secondNum1, thirdNum1]
, using 2 step, we can go to[num7, num5, num8]
. Sincenum8
is at the last index, we return 2. -
First, we need to build a graph by adjacency list. Key is the element, value is the list of indexes of this element. To prevent duplicate, we also need a visited set. Then, we can start our BFS using a queue and follow the above method to find the result.
Solution
1 |
|
Reach a Number
You are standing at position 0
on an infinite number line. There is a goal at position target
.
On each move, you can either go left or right. During the n-th move (starting from 1), you take n steps.
Return the minimum number of steps required to reach the destination.
Example 1:
1 |
|
Example 2:
1 |
|
Note:
target
will be a non-zero integer in the range[-10^9, 10^9]
.
Explanation
-
Since the number line is symmetry, the step to reach negative target is the same as the step to reach positive target.
-
If the
target
is4
, then we keep moving forward until we reach a number that is greater than or equal totarget
. We have:1
2
3
4
50 + 1 = 1 1 + 2 = 3 3 + 3 = 6
-
Since 6 is greater than 4, and exceed the target by 2, which is an even number. So, if when we were adding 1, instead of adding 1, we add negative 1, we will reach the target. For example:
1
2
3
4
50 - 1 = -1 -1 + 2 = 1 1 + 3 = 4
-
So when we exceed the target by
d
, andd
is an even number, when we were addingd/2
, instead of addingd/2
, we add-d/2
, we will reach thetarget
. -
If
d
is an odd number and the current step isn
. We need to consider whether the next stepn+1
is an even number or odd number. Ifn+1
is an odd number, then we move one more step forward, and now thed
becomes even number, so we can returnn+1
as our result. Ifn+1
is even, thenn+2
will be odd, so we need to move two steps forward in order to maked
even, so we returnn+2
as our result.
Solution
1 |
|
Week 5: December 29th - December 31st
Longest Substring with At Most K Distinct Characters
Given a string s
and an integer k
, return the length of the longest substring of s
that contains at most k
distinct characters.
Example 1:
1 |
|
Example 2:
1 |
|
Constraints:
-
1 <= s.length <= 5 * 10^4
-
0 <= k <= 50
Explanation
-
This problem is the same as 159. Longest Substring with At Most Two Distinct Characters except we need to change
k
equals to 2 to any number now. -
First, we can create a HashMap, and use it to store the key is the character, the value is the frequency of the character. Also, we initialize the
left
be 0. Iterate the input string and update the hashmap. While the hashmap has size greater thank
, then we need to decrease the frequency of characters[left]
and increase left by 1. Also if thes[left]
’s frequency is 0, we remove the keys[left]
from the hashmap. Repeat these steps until the hashmap has size less than or equal tok
. Next, we update the result bemax(res, i-left+1)
.
Solution
1 |
|
Pseudo-Palindromic Paths in a Binary Tree
Given a binary tree where node values are digits from 1 to 9. A path in the binary tree is said to be pseudo-palindromic if at least one permutation of the node values in the path is a palindrome.
Return the number of pseudo-palindromic paths going from the root node to leaf nodes.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Constraints:
-
The given binary tree will have between
1
and10^5
nodes. -
Node values are digits from
1
to9
.
Hint 1:
Note that the node values of a path form a palindrome if at most one digit has an odd frequency (parity).
Hint 2:
Use a Depth First Search (DFS) keeping the frequency (parity) of the digits. Once you are in a leaf node check if at most one digit has an odd frequency (parity).
Explanation
-
We can use brute force to solve this problem. First, build all the root-to-leaf paths. Then count every path that is palindrome and return the counter as the result.
-
We can use pre-order traversal to iterate every element and save each root-to-leaf path into each list, but this is space consuming. To save space, we can use an integer to hold the path by using bitwise operation. The idea is to keep the frequency of digit 1 in the first bit, 2 in the second bit, etc:
path ^= (1 << node.val)
. For example, the first time when we iterate the node value 2, we havepath = 010
; the second time when we iterate the node value 2, we havepath = 000
; the third time when we iterate the node value 2, we havepath = 010
. -
If the root-to-leaf path is palindrome, then at most one digit has an odd frequency. To determine if
path
is palindrome, we can turn off (= setting to 0) the rightmost 1-bit bypath & (path - 1)
then check ifpath
become 0. Ifpath
becomes 0, then we find a palindrome path and increase our counter.
Solution
1 |
|
Game of Life
According to Wikipedia’s article: “The Game of Life, also known simply as Life, is a cellular automaton devised by the British mathematician John Horton Conway in 1970.”
The board is made up of an m x n
grid of cells, where each cell has an initial state: live (represented by a 1
) or dead (represented by a 0
). Each cell interacts with its eight neighbors (horizontal, vertical, diagonal) using the following four rules (taken from the above Wikipedia article):
-
Any live cell with fewer than two live neighbors dies as if caused by under-population.
-
Any live cell with two or three live neighbors lives on to the next generation.
-
Any live cell with more than three live neighbors dies, as if by over-population.
-
Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.
The next state is created by applying the above rules simultaneously to every cell in the current state, where births and deaths occur simultaneously. Given the current state of the m x n
grid board
, return the next state.
Example 1:
1 |
|
Example 2:
1 |
|
Constraints:
-
m == board.length
-
n == board[i].length
-
1 <= m, n <= 25
-
board[i][j]
is0
or1
.
Follow up:
-
Could you solve it in-place? Remember that the board needs to be updated simultaneously: You cannot update some cells first and then use their updated values to update other cells.
-
In this question, we represent the board using a 2D array. In principle, the board is infinite, which would cause problems when the active area encroaches upon the border of the array (i.e., live cells reach the border). How would you address these problems?
Explanation
- First, we define the 4 states, and update all cells to the state.
- State 0: die cell to die cell
- State 1: live cell to live cell
- State 2: live cell to die cell
- State 3: die cell to live cell
-
After we update every cell to its state, we can loop through all the cell again and update to the final result of the each cell. We can use their state number module 2 to get the final result. In other words, if the module result is 0 (state0 and state2), final result will be 0. Else if the module result is not 0 (state 1 and state 3), final result will be 1.
-
We need a counter
live
to count how many live neighbor in each cell’s 8 neighbors. If the neighbor cell value is 1 or 2, that means they are live cell originally. After scanning every cell’s 8 neighbors, if thelive
counter is less than 2 or greater than 3, and the current cell is live cell, then mark the current cell to state 2. If there are exactly 3live
counter, and the current cell is die cell, then mark it as state 3. - After we update every cell’s state, we loop through the board again, and for each cell, we module 2 to get each cell’s final result.
Solution
1 |
|
Largest Rectangle in Histogram
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.
Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3]
.
The largest rectangle is shown in the shaded area, which has area = 10
unit.
Example:
1 |
|
Explanation 1
-
Iterate each element, if the next element is less than the current element or we hit the end of the array, then we start to find the rectangle’s area and that rectangle’s right side is fixed on current index.
-
We can find the min height by loop backward from the current index to zero, and we multiple the width with the minHeight.
Solution 1
1 |
|
Explanation 2
-
We can find the area by finding the current element’s leftMost and rightMost index and
area = heights[cur] * (rightMost-leftMost-1)
. From the above example, if the current element is at index 2, its height is 5. Then theleftMost
is at index 1, andrightMost
is at index 4 (leftMost is the previous first index element height that is less than the current element height, rightMost is the next first index element height that is less than the current element height). So, when current index is 2, its maximum area is5 * (4-1-1) = 10
which shows the red area. Another example is when current index is 3 which is at height 6, its maximum area is6 * (4-2-1) = 6
. -
First, we create an array
leftMost[]
to store every corresponding element’s leftMost index, similarlly create another arrayrightMost[]
to store every corresponding element’s rightMost index. -
When we are iterating the original array and find the leftMost index for the current element at index
i
, in other words, to findleftMost[i]
. We first think of the leftMost indexl
isi-1
. Whileheights[l]
is greater than or equal toheights[i]
, we decreasingl
. Outside this while loop,l
will be the first index of the element height less than the current heightheights[i]
, soleftMost[i] = l
. When we are decreasingl
this takes O(n) time, instead, we can improve the time complexity by settingl = leftMost[l]
. Similarlly, for rightMost indexr
, we setr = rightMost[r]
. -
After we calculate the results for
leftMost[]
andrightMost[]
, we can iterate the input array one more time and use step 1’s formula (area = heights[cur] * (rightMost[cur]-leftMost[cur]-1)
) to calculate the maximum area.
Solution 2
1 |
|