It’s been half year since doing LeetCoding Challenge! Let’s continue October LeetCoding Challenge.
Week 1: October 1st - October 7th
Maximum Distance in Arrays
Given m
arrays, and each array is sorted in ascending order. Now you can pick up two integers from two different arrays (each array picks one) and calculate the distance. We define the distance between two integers a
and b
to be their absolute difference |a-b|
. Your task is to find the maximum distance.
Example 1:
1 |
|
Note:
-
Each given array will have at least 1 number. There will be at least two non-empty arrays.
-
The total number of the integers in all the
m
arrays will be in the range of [2, 10000]. -
The integers in the
m
arrays will be in the range of [-10000, 10000].
Explanation 1
-
Since each array is sorted, we can get the minimum element and maximum element easily, then the result will be the maximum element subtract the minimum element.
-
Since we can’t get both the minimum and maximum element from the same array, we need to to record both the element and its index. We can solve this problem using a minHeap and a maxHeap. Both heaps will store the pair of element and its index. MinHeap will store the each array’s first element and the array index, maxHeap will store each array’s last element and the array index.
-
After looping all arrays and build up the minHeap and maxHeap. We compare the top of both heaps to check if both pair element are from the same array index. If they are, then we return the max between
max(max - secondMin, secondMax - min)
. Else, we can just return maxHeap’s top element subtract minHeap’s top element.
Solution 1
1 |
|
Explanation 2
- Since we can’t pick
max
andmin
from the same array, in other words,max
andmin
must from different arrays. Before we hit the current array, we need to keep track of thepreMax
andpreMin
. Then when we are in the current array, we can calculate the result beres = max(res, abs(preMax - curMin), abs(curMax - preMin)))
, then updatepreMin
andpreMax
as the minimum element and maximum element we have seen so far.
Solution 2
1 |
|
Number of Recent Calls
You have a RecentCounter
class which counts the number of recent requests within a certain time frame.
Implement the RecentCounter
class:
-
RecentCounter()
Initializes the counter with zero recent requests. -
int ping(int t)
Adds a new request at timet
, wheret
represents some time in milliseconds, and returns the number of requests that has happened in the past3000
milliseconds (including the new request). Specifically, return the number of requests that have happened in the inclusive range[t - 3000, t]
.
It is guaranteed that every call to ping
uses a strictly larger value of t
than the previous call.
Example 1:
1 |
|
Constraints:
-
1 <= t <= 10^9
-
Each test case will call
ping
with strictly increasing values oft
. -
At most
10^4
calls will be made toping
.
Explanation
-
We need to keep track of the number of request in the past 3000 millseconds, we can use a queue to do this.
-
In the constructor method, we initialize the queue and also the counter.
-
In the ping method, first increase the counter and append the
t
into the queue. Whileq[0] < t - 3000
, we poll from the queue and decrease the counter. At the end, the queue will only contain the past 3000 millseconds ping request, we can return its length or the counter.
Solution
1 |
|
Combination Sum
Given an array of distinct integers candidates
and a target
integer target, return a list of all unique combinations of candidates
where the chosen numbers sum to target
. You may return the combinations in any order.
The same number may be chosen from candidates
an unlimited number of times. Two combinations are unique if the frequency of at least one of the chosen numbers is different.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Example 4:
1 |
|
Example 5:
1 |
|
Constraints:
-
1 <= candidates.length <= 30
-
1 <= candidates[i] <= 200
-
All elements of
candidates
are distinct. -
1 <= target <= 500
Explanation 1
-
We can use recursion to solve this problem.
-
First, we create a result list and a sub temporary sublist, passing these two lists as the parameters to the helper function. Also, we pass the start index initialize to 0 to the helper function. The start index is used to avoid duplicate sublist. For example, if
condidates=[1, 2, 3]
, then if we already push the sublist[1, 2]
into the result list, then we don’t want to put[2, 1]
into the result list. In other words, after we finding out all the sublist that starts with 1, we then need to find out all the sublist that starts with 2. -
The base case if
target == 0
, we push the sublist into the result list, and return. If thetarget < 0
, we just return. -
Note, when we push the temporary sublist into the result list, we will pass the new object of temporary sublist, not the reference of original temporary sublist since it will change everytime.
Solution 1
1 |
|
Explanation 2
-
We can also solve this problem using dynamic programming. Let’s use the problem’s Example 1. We first create a dp array
dp[]
anddp[t]
represents all the combinations for targett
. -
Loop through all the candidates, for each candidate
c
, inner loop through targett
from 1 totarget
inclusive. Ifc > t
, we can skip. Else ifc == t
, we find one combination for targett
, which is[c]
, so we append this combination todp[t]
. Else ifc < t
, assumec
is part of the combination, then we need to find all the combinations fordp[t - c]
, and for each combination, we appendc
to it, now this combination become the combination fordp[t]
.
1 |
|
Solution 3
1 |
|
K-diff Pairs in an Array
Given an array of integers nums
and an integer k
, return the number of unique k-diff pairs in the array.
A k-diff pair is an integer pair (nums[i], nums[j])
, where the following are true:
-
0 <= i, j < nums.length
-
i != j
-
a <= b
-
b - a == k
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Example 4:
1 |
|
Example 5:
1 |
|
Constraints:
-
1 <= nums.length <= 10^4
-
-10^7 <= nums[i] <= 10^7
-
0 <= k <= 10^7
Explanation
-
First, we put all numbers and their frequency into a hash map.
-
We want to find two numbers’ difference is
k
, so if one number plusk
and its sum is inside the hashmap, then we increase the result. So we iterate through the hashmap’s key set. For every key, we check ifkey + k
is inside the hashmap, if true, we increase the result by 1. -
If
k
is zero, then for every iterated key, we check its frequency. If the current key’s frequency is greater than 1, we increase the result.
Solution
1 |
|
Remove Covered Intervals
Given a list of intervals
, remove all intervals that are covered by another interval in the list.
Interval [a,b)
is covered by interval [c,d)
if and only if c <= a
and b <= d
.
After doing so, return the number of remaining intervals.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Example 4:
1 |
|
Example 5:
1 |
|
Constraints:
-
1 <= intervals.length <= 1000
-
intervals[i].length == 2
-
0 <= intervals[i][0] < intervals[i][1] <= 10^5
-
All the intervals are unique.
Hint 1:
How to check if an interval is covered by another?
Hint 2:
Compare each interval to all others and check if it is covered by any interval.
Explanation
-
For interval problems, we often first sort all intervals by their start or left point.
-
We have two cases for overlap.
1
2------- --------------------
1
2-------------------- -------
-
We initialize the first interval as the pre-interval and its start and end as
preLeft
andpreRight
, and initialize the resultres
to 1. Loop from the second interval to the last interval. Each iteration, check if the pre-interval with current iterated interval are overlap or not. If overlap, resultres
increase by 1. Next, update the pre-interval be the interval that has the largest ending point. -
After looping all intervals, we return the result
res
.
Solution
1 |
|
Complement of Base 10 Integer
Every non-negative integer N
has a binary representation. For example, 5
can be represented as "101"
in binary, 11
as "1011"
in binary, and so on. Note that except for N = 0
, there are no leading zeroes in any binary representation.
The complement of a binary representation is the number in binary you get when changing every 1
to a 0
and 0
to a 1
. For example, the complement of "101"
in binary is "010"
in binary.
For a given number N
in base-10, return the complement of it’s binary representation as a base-10 integer.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Note:
-
0 <= N < 10^9
-
This question is the same as 476: https://leetcode.com/problems/number-complement/
Hint 1:
A binary number plus its complement will equal 111….111 in binary. Also, N = 0 is a corner case.
Explanation
-
In order to make
101
becomes010
, we can just do101 ^ 111 = 010
. Similarlly,111 ^ 111 = 000
, and1010 ^ 1111 = 0101
. -
From the above example, we know that we first need to find the smallest number
a
that has all bits set to 1 anda <= N
. Initially, we definea = 1
, whilea < N
, then we doa = (a << 1) + 1
ora = (a << 1) | 1
. Outside the while loop, we return the resulta ^ N
.
Solution
1 |
|
Insert into a Binary Search Tree
You are given the root
node of a binary search tree (BST) and a value
to insert into the tree. Return the root node of the BST after the insertion. It is guaranteed that the new value does not exist in the original BST.
Notice that there may exist multiple valid ways for the insertion, as long as the tree remains a BST after insertion. You can return any of them.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Constraints:
-
The number of nodes in the tree will be in the range
[0, 104]
. -
-10^8 <= Node.val <= 10^8
-
All the values
Node.val
are unique. -
-10^8 <= val <= 10^8
-
It’s guaranteed that
val
does not exist in the original BST.
Explanation
-
For tree problem, we can usually solve it using recursion. In this problem, we can solve it by recursively calling the main function.
-
For example, using the problem’s example 1,
5
is greater than 4, so we check 4’s right child 7. Now5
is less than 7, so we check 7’s left child which is NULL. Now we can just create a new TreeNode with value5
and return it. -
The basecase is if
root
is NULL, we can just create a new TreeNode with valueval
and return it. Else ifval
is less thanroot
, then we recursively call the main function withroot.left
andval
, the return value will beroot.left
. Similarlly, ifval
is greater thanroot
, then we recursively call the main function withroot.right
andval
, the return value will beroot.right
. At the end, we returnroot
.
Solution
1 |
|
Rotate List
Given a linked list, rotate the list to the right by k places, where k is non-negative.
Example 1:
1 |
|
Example 2:
1 |
|
Explanation
-
We need two pointers, slow and fast. Fast pointer move k step ahead, then both slow and fast pointer move at the same time until fast pointer hits the end.
-
Now,
fast.next = head
,head = slow.next
, andslow.next = null
. -
Corner case is when
k
is bigger than the size of the linkedlist. Actually, the k isk = k % size
.
Solution
1 |
|
Week 2: October 8th - October 14th
Two Sum III - Data structure design
Design a data structure that accepts a stream of integers and checks if it has a pair of integers that sum up to a particular value.
Implement the TwoSum
class:
-
TwoSum()
Initializes theTwoSum
object, with an empty array initially. -
void add(int number)
Addsnumber
to the data structure. -
boolean find(int value)
Returnstrue
if there exists any pair of numbers whose sum is equal tovalue
, otherwise, it returnsfalse
.
Example 1:
1 |
|
Constraints:
-
-10^5 <= number <= 10^5
-
-23^1 <= value <= 23^1 - 1
-
At most
5 * 10^4
calls will be made toadd
andfind
.
Explanation
-
In the
add
method, We can use a HashMap to record the frequency of the added number. The key is the number, the value is the frequency. -
In the
find
method, we loop through the HashMap keyset’s every numbernum
, thetarget
will bevalue - num
. Then we check if the hashmap contains thetarget
, then we need to consider two cases. The first case is if thetarget
is equal to the current number and the frequency of that number is 1, then wecontinue
. The second case is if thetarget
is not equal to the current number, that means we find a pair that sum tovalue
so we returntrue
. At the end when we loop through all the number, then we returnfalse
.
Solution
1 |
|
Binary Search
Given a sorted (in ascending order) integer array nums
of n
elements and a target
value, write a function to search target
in nums
. If target
exists, then return its index, otherwise return -1
.
Example 1:
1 |
|
Example 2:
1 |
|
Note:
-
You may assume that all elements in
nums
are unique. -
n
will be in the range[1, 10000]
. -
The value of each element in
nums
will be in the range[-9999, 9999]
.
Explanation
- Standard binary search. First, initialize the range
left = 0, right = nums.length-1
. Whileleft <= right
, we find the middle indexmid = left + (right - left) / 2
. Then comparetarget
withnums[mid]
. Ifnums[mid] == target
, we returnmid
. Else ifnums[mid] < target
, then we updateleft = mid + 1
. Else ifnums[mid] < target
, then we updateright = mid - 1
.
Solution
1 |
|
Serialize and Deserialize BST
Serialization is converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment.
Design an algorithm to serialize and deserialize a binary search tree. There is no restriction on how your serialization/deserialization algorithm should work. You need to ensure that a binary search tree can be serialized to a string, and this string can be deserialized to the original tree structure.
The encoded string should be as compact as possible.
Example 1:
1 |
|
Example 2:
1 |
|
Constraints:
-
The number of nodes in the tree is in the range
[0, 10^4]
. -
0 <= Node.val <= 10^4
-
The input tree is guaranteed to be a binary search tree.
Explanation
-
We can use level order traversal, in other word, BFS, to store all node value into a list, if the node is
null
, we can store any symbol, for example#
. At the end, we can useString.join
add,
between the list element and return it as a string. -
In the deserialize method, first we split the string into array. Then if the first element is not
#
, we make a new TreeNoderoot
with value equals to the first value of the array. Next, we store thisroot
TreeNode into the queue. While the queue is not empty, we pop the queue to getpopNode
. If thepopNode
is not empty, we make a new nodeleft = null
and check ifarray[i]
is not equals to#
, thenleft
have the value ofarray[i]
. Next, connectpopNode
withleft
bypopNode.left = left
, and we storeleft
into the queue and increasei
. Same forright
. Outside when queue is empty, we return theroot
.
Solution
1 |
|
Minimum Number of Arrows to Burst Balloons
There are some spherical balloons spread in two-dimensional space. For each balloon, provided input is the start and end coordinates of the horizontal diameter. Since it’s horizontal, y-coordinates don’t matter, and hence the x-coordinates of start and end of the diameter suffice. The start is always smaller than the end.
An arrow can be shot up exactly vertically from different points along the x-axis. A balloon with xstart
and xend
bursts by an arrow shot at x
if xstart ≤ x ≤ xend
. There is no limit to the number of arrows that can be shot. An arrow once shot keeps traveling up infinitely.
Given an array points
where points[i] = [xstart, xend]
, return the minimum number of arrows that must be shot to burst all balloons.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Example 4:
1 |
|
Example 5:
1 |
|
Constraints:
-
0 <= points.length <= 10^4
-
points[i].length == 2
-
-23^1 <= xstart < xend <= 23^1 - 1
Explanation
-
First, we sort the horizontal lines by their starting points.
1
2
3
4
5
6
7
8------- --------- -------- ------ -------- ------------------- ---- ------
-
Next, we default the shooting point is the first ballon’s right ending point. If the second ballon’s starting point is less than or equals to the first boolean’s right ending point, then we update the shooting point be the minium of these two boolean’s right ending point. If the current boolean’s starting point is greater than the updated ending point, then we make another shoot, and the shooting point is the current boolean’s ending point.
Solution
1 |
|
Remove Duplicate Letters
Given a string s
, remove duplicate letters so that every letter appears once and only once. You must make sure your result is the smallest in lexicographical order among all possible results.
Note: This question is the same as 1081: https://leetcode.com/problems/smallest-subsequence-of-distinct-characters/
Example 1:
1 |
|
Example 2:
1 |
|
Constraints:
-
1 <= s.length <= 10^4
-
s
consists of lowercase English letters.
Hint 1:
Greedily try to add one missing character. How to check if adding some character will not cause problems ? Use bit-masks to check whether you will be able to complete the sub-sequence if you add the character at some index i.
Explanation
-
First, we create a HashMap to count the frequency of each character. Also, we create a visited map to keep track if the character is already appeared in the
res
string. -
Loop through every character in the string. Update its frequency, check if it’s already visited. If it’s visited, then we
continue
. If it’s not visited, then we compare it with the last character of theres
string. While the current iterated element is smaller than the last character of theres
string, and the last character from theres
string still has frequency at least one, in other words, it will appear in the later iterated character. Then we delete that last character from theres
string, and add the smaller iterated character to the string. Repeat this while loop until the current iterated character is greater than the last character of theres
string, then we append the current iterated character to theres
. -
Initially, we will add a
'0'
to theres
string because it’s smaller than any letter, so that it is easier for us to do the comparison with the last character of the string. At the end, we will returnres.substring(1)
to ignore that first character.
Solution
1 |
|
Buddy Strings
Given two strings A
and B
of lowercase letters, return true
if you can swap two letters in A
so the result is equal to B
, otherwise, return false
.
Swapping letters is defined as taking two indices i
and j
(0-indexed) such that i != j
and swapping the characters at A[i]
and A[j]
. For example, swapping at indices 0
and 2
in "abcd"
results in "cbad"
.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Example 4:
1 |
|
Example 5:
1 |
|
Constraints:
-
0 <= A.length <= 20000
-
0 <= B.length <= 20000
-
A
andB
consist of lowercase letters.
Explanation
-
We can use brute force to solve this problem.
-
First, if two strings have different length or string A’s length is less than 2, then return false immediately.
-
If string
A
and stringB
are equal, but if stringA
’s all characters are unique, then we return false immediately because we can only swap two same characters in this case. We can use a HashSet to store all characters in stringA
, then check if the set’s size is less than stringA
’s length, that means there are same characters. -
If string
A
and stringB
are not equal, we can use a list to store the indexes whenA[i] != B[i]
. After looping checking all characters, if the list’s size is not equal to 2, we can return false immediately. If it’s equal to 2 that means there are two places the characters are different, we can compare these 4 characters and return the result.
Solution
1 |
|
Sort List
Given the head
of a linked list, return the list after sorting it in ascending order.
Follow up: Can you sort the linked list in O(n logn)
time and O(1)
memory (i.e. constant space)?
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Constraints:
-
The number of nodes in the list is in the range
[0, 5 * 104]
. -
-10^5 <= Node.val <= 10^5
Explanation
-
We can use merge sort method to solve this problem.
-
First we need to find the mid node or the right list’s head node. We can use slow and fast pointer technique to find the mid node.
-
Next, we want to split the list into left list and right list. If the list is 1->2->3->4, we want the left list be 1->2 and the right list be 3->4. We can recursively call the main function with the left list, and recursively call the main function with the right list to spit the list.
-
After splitting, we want to merge the left list and right list in a sorted order.
Solution
1 |
|
House Robber II
You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed. All houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, adjacent houses have a security system connected, and it will automatically contact the police if two adjacent houses were broken into on the same night.
Given a list of non-negative integers nums
representing the amount of money of each house, return the maximum amount of money you can rob tonight without alerting the police.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Constraints:
-
1 <= nums.length <= 100
-
0 <= nums[i] <= 1000
Hint 1:
Since House[1] and House[n] are adjacent, they cannot be robbed together. Therefore, the problem becomes to rob either House[1]-House[n-1] or House[2]-House[n], depending on which choice offers more money. Now the problem has degenerated to the House Robber, which is already been solved.
Explanation
- The problem’s hint basically answer the problem: Since House[1] and House[n] are adjacent, they cannot be robbed together. Therefore, the problem becomes to rob either House[1]-House[n-1] or House[2]-House[n], depending on which choice offers more money.
Solution
1 |
|
Week 3: October 15th - October 21st
Meeting Rooms II
Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...]
(si < ei), find the minimum number of conference rooms required.
Example 1:
1 |
|
Example 2:
1 |
|
NOTE: input types have been changed on April 15, 2019. Please reset to default code definition to get new method signature.
Hint 1:
Think about how we would approach this problem in a very simplistic way. We will allocate rooms to meetings that occur earlier in the day v/s the ones that occur later on, right?
Hint 2:
If you’ve figured out that we have to sort the meetings by their start time, the next thing to think about is how do we do the allocation? There are two scenarios possible here for any meeting. Either there is no meeting room available and a new one has to be allocated, or a meeting room has freed up and this meeting can take place there.
Hint 3:
An important thing to note is that we don’t really care which room gets freed up while allocating a room for the current meeting. As long as a room is free, our job is done.
We already know the rooms we have allocated till now and we also know when are they due to get free because of the end times of the meetings going on in those rooms. We can simply check the room which is due to get vacated the earliest amongst all the allocated rooms.
Hint 4:
Following up on the previous hint, we can make use of a min-heap to store the end times of the meetings in various rooms.
So, every time we want to check if any room is free or not, simply check the topmost element of the min heap as that would be the room that would get free the earliest out of all the other rooms currently occupied.
If the room we extracted from the top of the min heap isn’t free, then no other room is. So, we can save time here and simply allocate a new room.
Explanation
-
For interval problem, first we sort all intervals by their start time.
-
If two interval overlap, that means the second interval’s start time is less than the first interval’s end time. If two interval don’t overlap, that means the second interval’s start time is equal or greater than the first interval’s end time.
-
We can use a minHeap to record the end time we already interated. Initially, we append the first interval’s end time into the minHeap. Start looping from the second interval. If the current interval’s start time is less than the minHeap’s top end time, that means we have overlap so increase the result. Else the current interval’s start time is equal or greater than the minHeap’s top end time, so we can pop the minHeap until the current interval’s start time is less than the minHeap’s top end time; then we append the current interval’s end time.
-
The minHeap’s size is the number of meeting we are now having, the
res
is the maximum number of overlapping meeting. So ifminHeap.size() < res
, we don’t need to increaseres
, we can just append the current interval’s end time to the minHeap. For example, in below’s graph, when the current interval is [4284, 5907], the minHeap only has [5870]. Even though 4284 < 5870, we just append the current interval’s end time to this minHeap.
1 |
|
Solution
1 |
|
Rotate Array
Given an array, rotate the array to the right by k steps, where k is non-negative.
Follow up:
-
Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem.
-
Could you do it in-place with O(1) extra space?
Example 1:
1 |
|
Example 2:
1 |
|
Constraints:
-
1 <= nums.length <= 2 * 10^4
-
-23^1 <= nums[i] <= 23^1 - 1
-
0 <= k <= 10^5
Hint 1:
The easiest solution would use additional memory and that is perfectly fine.
Hint 2:
The actual trick comes when trying to solve this problem without using any additional memory. This means you need to use the original array somehow to move the elements around. Now, we can place each element in its original location and shift all the elements around it to adjust as that would be too costly and most likely will time out on larger input arrays.
Hint 3:
One line of thought is based on reversing the array (or parts of it) to obtain the desired result. Think about how reversal might potentially help us out by using an example.
Hint 4:
The other line of thought is a tad bit complicated but essentially it builds on the idea of placing each element in its original position while keeping track of the element originally in that position. Basically, at every step, we place an element in its rightful position and keep track of the element already there or the one being overwritten in an additional variable. We can’t do this in one linear pass and the idea here is based on cyclic-dependencies between elements.
Explanation
-
We can use $O(1)$ space to solve this problem.
-
First, reverse the whole array.
-
Then, reverse the first k numbers.
-
Finally, reverse the last len(nums)-k numbers.
Solution
1 |
|
Search a 2D Matrix
Write an efficient algorithm that searches for a value in an m x n
matrix. This matrix has the following properties:
-
Integers in each row are sorted from left to right.
-
The first integer of each row is greater than the last integer of the previous row.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Constraints:
-
m == matrix.length
-
n == matrix[i].length
-
0 <= m, n <= 100
-
-10^4 <= matrix[i][j], target <= 10^4
Explanation
-
We can think of all the subarrays are flatterned into one single array, then apply binary search to find the target element.
-
If all elements are in a single array, then we have total
row * col
elements. So initiallyleft = 0, right = row * col - 1
. After we find themid
, it can transform back to a 2d array’s row asmid / col
, column asmid % col
.
Solution
1 |
|
Repeated DNA Sequences
All DNA is composed of a series of nucleotides abbreviated as 'A'
, 'C'
, 'G'
, and 'T'
, for example: "ACGAATTCCG"
. When studying DNA, it is sometimes useful to identify repeated sequences within the DNA.
Write a function to find all the 10-letter-long sequences (substrings) that occur more than once in a DNA molecule.
Example 1:
1 |
|
Example 2:
1 |
|
Constraints:
-
0 <= s.length <= 10^5
-
s[i]
is'A'
,'C'
,'G'
, or'T'
.
Explanation
-
If the string has length less than or equal to 10, we return empty result.
-
We can use brute force to solve this problem. First, we check the first 10 character string starts from index 0, then check the second 10 character string starts from index 1, etc. When iterating, we put them into a frequency map.
-
At the end, all string that appears more than once in the frequency map are result string.
Solution
1 |
|
Best Time to Buy and Sell Stock IV
You are given an integer array prices
where prices[i]
is the price of a given stock on the ith
day.
Design an algorithm to find the maximum profit. You may complete at most k
transactions.
Notice that you may not engage in multiple transactions simultaneously (i.e., you must sell the stock before you buy again).
Example 1:
1 |
|
Example 2:
1 |
|
Constraints:
-
0 <= k <= 10^9
-
0 <= prices.length <= 10^4
-
0 <= prices[i] <= 1000
Explanation
-
We can use dynamic programming to solve this problem.
-
Dynamic state is a two dimensional array
dp[t][d]
, row is transaction and column is the day, and it represents the maximum profit can be made using at mostt
transaction ind
day. Note, the length of the row ist+1
because we need consider zero transaction. -
Dynamic init is
dp[0][d]
(top row) all values will be zero because we are not making any transaction.dp[t][0]
all (left column) will be zero because if only has one day, then we can’t make any profit for one day. -
Dynamic function will be taking the maximum profit of either not making any transaction on day
d
, which isdp[t][d-1]
; another way is make transaction on dayd
, which the profit will beprices[d] - prices[m] + dp[t-1][m]
, wherem
will be the day we buy the stock and sell this stock on dayd
for the last transaction andm
will be from 0 to d-1. How do we find them
? We can switch the order ofprices[d] - prices[m] + dp[t-1][m]
toprices[d] + (dp[t-1][m] - prices[m])
, so we need to find them
that makse the maximum ofdp[t-1][m] - prices[m]
, let’s call thismaxDiff
. So, we can iterate them
from 0 to d-1, and find the maximum ofmaxDiff
. Therefore, the dynamic function ismax(dp[t][d-1], prices[d] + maxDiff
wheremaxDiff = dp[t-1][m]-prices[m]
form = 0 to d-1
. -
Dynamic result will be the bottom right value, which is
dp[t][d]
.
Solution
1 |
|
Minimum Domino Rotations For Equal Row
In a row of dominoes, A[i]
and B[i]
represent the top and bottom halves of the ith
domino. (A domino is a tile with two numbers from 1 to 6 - one on each half of the tile.)
We may rotate the ith
domino, so that A[i]
and B[i]
swap values.
Return the minimum number of rotations so that all the values in A
are the same, or all the values in B
are the same.
If it cannot be done, return -1
.
Example 1:
1 |
|
Example 2:
1 |
|
Constraints:
-
2 <= A.length == B.length <= 2 * 10^4
-
1 <= A[i], B[i] <= 6
Explanation
-
We want either one row to have the same number
target
, there are can be only two choices, either all row to beA[0]
orB[0]
. -
First, we create a helper function and assume the target is
A[0]
. Looplen(A)
times, in each iteration, we check if bothA[i]
andB[i]
are not equal toA[0]
, that means we cannot useA[0]
as the target, so we return -1 from the helper function. Else ifA[i]
is not equal to target, then we increasecntA
which means flip rowA
. Similarlly, else ifB[i]
is not equal to target, then we increasecntB
which means flip rowB
. At the end we return the minimum betweencntA
andcntB
. -
If the result
res
return from the helper function with target equals toA[0]
is -1, then we run the helper function with targetB[0]
and return that value, else if theres
return from the helper function with target equals toA[0]
is not -1, then we returnres
; in this case, why don’t we need to try target isB[0]
? Because if we try target isB[0]
, its answer will either be -1 or equal tores
when target isA[0]
. For example, ifA = [5, 5, 5, 1]
, andB = [1, 1, 1, 5]
. When target is either 5 or 1, the result is the same.
Solution
1 |
|
Clone Graph
Given a reference of a node in a connected undirected graph.
Return a deep copy (clone) of the graph.
Each node in the graph contains a val (int
) and a list (List[Node]
) of its neighbors.
1 |
|
Test case format:
For simplicity sake, each node’s value is the same as the node’s index (1-indexed). For example, the first node with val = 1
, the second node with val = 2
, and so on. The graph is represented in the test case using an adjacency list.
Adjacency list is a collection of unordered lists used to represent a finite graph. Each list describes the set of neighbors of a node in the graph.
The given node will always be the first node with val = 1
. You must return the copy of the given node as a reference to the cloned graph.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Example 4:
1 |
|
Constraints:
-
1 <= Node.val <= 100
-
Node.val
is unique for each node. -
Number of Nodes will not exceed 100.
-
There is no repeated edges and no self-loops in the graph.
-
The Graph is connected and all nodes can be visited starting from the given node.
Explanation
-
We can use DFS and a HashMap to solve this problem.
-
In DFS, we iterate every node. In each iteration, we create a copy of the node and put its value as key, the copied node as value into the hashmap. Then loop through the original node’s neighbors and recursively call each neighbor with DFS. But before we recursively call the function, we check if the neighbor is in the hashmap or not. If not, then we call; and the return value will be added to the current copied node’s neighbor list. Else if the neighbor node’s value is already in the hashmap, then we don’t need to recursively call the DFS function, we can simply add the mapping node to the current copied node’s neighbor list.
Solution
1 |
|
Asteroid Collision
We are given an array asteroids
of integers representing asteroids in a row.
For each asteroid, the absolute value represents its size, and the sign represents its direction (positive meaning right, negative meaning left). Each asteroid moves at the same speed.
Find out the state of the asteroids after all collisions. If two asteroids meet, the smaller one will explode. If both are the same size, both will explode. Two asteroids moving in the same direction will never meet.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Example 4:
1 |
|
Constraints:
-
1 <= asteroids <= 10^4
-
-1000 <= asteroids[i] <= 1000
-
asteroids[i] != 0
Hint 1:
Say a row of asteroids is stable. What happens when a new asteroid is added on the right?
Explanation
-
This is a stack problem.
-
Loop through the input array, put each iterated number into the stack. While the top of stack
topNum
is positive and the current iterated number is negative, then there’s a collision. While there’s collision, we compare ifabs(topNum) < curNum
, then we pop from stack and continue this while check. Else ifabs(topNum) == curNum
, we pop from stack, break from this while loop and don’t push the current number, so markpushNum = false
. Else ifabs(topNum) > curNum
, we break from this while loop and don’t push current number. After the while loop andpushNum
is still true, then we push the current number.
Solution
1 |
|
Week 4: October 22nd - October 28th
Search in a Sorted Array of Unknown Size
Given an integer array sorted in ascending order, write a function to search target
in nums
. If target
exists, then return its index, otherwise return -1
. However, the array size is unknown to you. You may only access the array using an ArrayReader
interface, where ArrayReader.get(k)
returns the element of the array at index k
(0-indexed).
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:
1 |
|
Example 2:
1 |
|
Constraints:
-
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]
. -
The length of the array will be in the range
[1, 10^4]
.
Explanation
-
My first attempt is to use binary search to find the array’s length, then use binary search again to find the target.
-
Actually we can assume the array’s length is
INT_MAX
and assume elements that are outside the array have valuesINT_MAX
. Since this array is sorted and every array element is less thanINT_MAX
, we can use binary search to find out the target element.
Solution
1 |
|
Minimum Depth of Binary Tree
Given a binary tree, find its minimum depth.
The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node.
Note: A leaf is a node with no children.
Example 1:
1 |
|
Example 2:
1 |
|
Constraints:
-
The number of nodes in the tree is in the range
[0, 10^5]
. -
-1000 <= Node.val <= 1000
Explanation
- We can use level-order traversal to solve this problem. In the current level, if the node poll from the queue which is a leaf node, then we return the result or the number of level immediately, else if the poll node is not a leaf node, then we append its left child node and right child node to the queue.
Solution
1 |
|
132 Pattern
Given an array of n
integers nums
, a 132 pattern is a subsequence of three integers nums[i]
, nums[j]
and nums[k]
such that i < j < k
and nums[i] < nums[k] < nums[j]
.
Return true
if there is a 132 pattern in nums
, otherwise, return false
.
Follow up: The O(n^2)
is trivial, could you come up with the O(n logn)
or the O(n)
solution?
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Constraints:
-
n == nums.length
-
1 <= n <= 10^4
-
-10^9 <= nums[i] <= 10^9
Explanation
-
We can use monotonous stack to solve this problem in $O(n)$ runtime.
-
If the input array is
[2, 4, 2, 3, 5]
. We loop from the right to left, and make a stack[2, 3, 5]
(2 is the top of stack, the upper the stack, the lower the number). In the iteration we iterate to 4, we check 4 is greater than 2, we pop 2, update the pattern’s third numberthird=2
; now 4 is greater than 3, we pop 3, updatethird=3
; now 4 is less than 5, we push 4 into the stack, so we have[4, 5]
(4 is the top of stack). Next iteration, we iterate the 2, since2 < third
, we return true because now we find a 132 pattern which is2, 4, 3
.
Solution
1 |
|
Bag of Tokens
You have an initial power of P
, an initial score of 0
, and a bag of tokens
where tokens[i]
is the value of the ith
token (0-indexed).
Your goal is to maximize your total score by potentially playing each token in one of two ways:
If your current power is at least tokens[i]
, you may play the ith
token face up, losing tokens[i]
power and gaining 1
score.
If your current score is at least 1
, you may play the ith
token face down, gaining tokens[i]
power and losing 1
score.
Each token may be played at most once and in any order. You do not have to play all the tokens.
Return the largest possible score you can achieve after playing any number of tokens.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Constraints:
-
0 <= tokens.length <= 1000
-
0 <= tokens[i], P < 10^4
Explanation
-
We can use greedy approach to solve this problem.
-
We want to spend less power and gain more score; and if not enough power, then we want to spend 1 score and gain more power.
-
First, sort the array. Create a pointer
i
points to the smallest token, and a pointerj
points to the largest token. If we have enough power (P >= tokens[i]
) to gain score, then we spend our power and increase our score. At the same time, we keep track of the maximum score. Then movei
to the right. Else if we don’t have enough power to gain score, then we want to spend 1 score and gain the most power. So we subtract 1 from our score, increase our power, and movej
to the left. -
When pointer
i > j
, we break out the loop and return the maximum score we keep tracked.
Solution
1 |
|
Stone Game IV
Alice and Bob take turns playing a game, with Alice starting first.
Initially, there are n
stones in a pile. On each player’s turn, that player makes a move consisting of removing any non-zero square number of stones in the pile.
Also, if a player cannot make a move, he/she loses the game.
Given a positive integer n
. Return True
if and only if Alice wins the game otherwise return False
, assuming both players play optimally.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Example 4:
1 |
|
Example 5:
1 |
|
Constraints:
1 <= n <= 10^5
Hint 1:
Use dynamic programming to keep track of winning and losing states. Given some number of stones, Alice can win if she can force Bob onto a losing state.
Explanation 1
-
We can use recursive/dynamic programming (top down) to solve this problem.
-
Base case is if
n
is 0, then we returnfalse
immediately. -
We define a helper function, for example
helper(5)
represents if Alice can win whenn
is 5. In this case, we can try remove 1 stone, then recursively call the helper functionhelper(4)
. Ifhelper(4)
returns false, that means Bob lose the game, so Alice win. In other word, ifhelper(4) == false
, thenhelper(5) = win
. Else ifhelper(4)
is true, then we keep try removing 2 * 2 = 4 stones. Now, Bob left with (5 - 4 = 1) stone, we check ifhelper(1)
is false, then Alice can win. Buthelper(1)
is true, so we keep try removing 3 * 3 = 9 stones, since there are total 5 stones, we cannot remove 9 stones. So after we try all possibilities and cannot find any recursive function returns false, then Alice lose the game.
Solution 1
1 |
|
Explanation 2
-
We can also use bottom up approach to solve this problem.
-
First, we create a boolean array
dp
that has sizen + 1
, anddp[i]
represents if numberi
can win or not. -
Loop from
i = 1
toi = n
inclusive. For eachi
, inner loopj
from1
toj * j <= n
, andj
represents the number of stones we try to remove. Ifdp[i - j * j]
is false, that meansdp[i]
is true. -
At the end, we return
dp[n]
.
Solution 2
1 |
|
Champagne Tower
We stack glasses in a pyramid, where the first row has 1
glass, the second row has 2
glasses, and so on until the 100th row. Each glass holds one cup of champagne.
Then, some champagne is poured into the first glass at the top. When the topmost glass is full, any excess liquid poured will fall equally to the glass immediately to the left and right of it. When those glasses become full, any excess champagne will fall equally to the left and right of those glasses, and so on. (A glass at the bottom row has its excess champagne fall on the floor.)
For example, after one cup of champagne is poured, the top most glass is full. After two cups of champagne are poured, the two glasses on the second row are half full. After three cups of champagne are poured, those two cups become full - there are 3 full glasses total now. After four cups of champagne are poured, the third row has the middle glass half full, and the two outside glasses are a quarter full, as pictured below.
Now after pouring some non-negative integer cups of champagne, return how full the jth
glass in the ith
row is (both i
and j
are 0-indexed.)
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Constraints:
-
0 <= poured <= 10^9
-
0 <= query_glass <= query_row < 100
Explanation 1
-
If there are 3 cups of champagne are poured on the topmost glass, then the topmost glass is full, (3 - 1) = 2 cups of champagne will be poured equally on the next row’s left glass and right glass, so the second row’s first glass get 2 / 2 = 1 cup, and the right glass get 2 / 2 = 1 cup.
-
If there are 4 cups of champagne are poured on the topmost glass, then the topmost glass is full, (4 - 1) = 3 cups of champagne will be poured equally on the next row’s left glass and right glass, so the second row’s first glass get 3 / 2 = 1.5 cup, and the right glass get 3 / 2 = 1.5 cup. Now, we iterate to second row. Since the second row’s first glass has 1.5 cup, it will poured equally on the next row’s left glass and right glass. So the second row’s first cup is full and (1.5 - 1 = 0.5) cup will be poured equally on the third row’s first glass and second glass. Similarlly, since the second row’s second glass has 1.5 cup, it will become full, and (1.5 - 1 = 0.5) cup will be poured equally on the third row’s second glass and third glass equally.
-
We can use dynamic programming to solve this problem.
-
Dynamic state is
dp[r][c]
represents ther
row andc
column’s glass of champagne. -
Dynamic init is
dp[0][0]
equals to the inputpoured
. -
Dynamic function is if the current glass is full, it will split equally to the next row’s left glass and right glass. In other words,
dp[r+1][c] = (dp[r][c] - 1) / 2.0
anddp[r+1][c+1] = (dp[r][c] - 1) / 2.0
. -
Dynamic result is
dp[query_row][query_glass]
.
Solution 1
1 |
|
Explanation 2
- Since the current row’s glass is depends on the last row’s glass only, we can also use one dymensional array to solve this problem.
Solution 2
1 |
|
Linked List Cycle II
Given a linked list, return the node where the cycle begins. If there is no cycle, return null
.
There is a cycle in a linked list if there is some node in the list that can be reached again by continuously following the next
pointer. Internally, pos
is used to denote the index of the node that tail’s next
pointer is connected to. Note that pos
is not passed as a parameter.
Notice that you should not modify the linked list.
Follow up:
Can you solve it using O(1)
(i.e. constant) memory?
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Constraints:
-
The number of the nodes in the list is in the range
[0, 10^4]
. -
-10^5 <= Node.val <= 10^5
-
pos
is-1
or a valid index in the linked-list.
Explanation
-
Both slow and fast pointers point to the head.
-
While fast and fast.next is not null, when slow pointer moves one step, fast pointer moves two steps.
-
If slow pointer and fast pointer points to the same node, then it means there’s cycle, break out of the while loop.
-
When out of the while loop, we first check if the fast pointer hits the end, if either fast or fast.next is null, then it means no cycle.
-
Now, slow pointer moves back to the head. Fast pointer doesn’t move.
-
Then run both, slow pointer and fast pointer at the same speed, the point the meet is the entry of cycle.
Solution
1 |
|
Summary Ranges
You are given a sorted unique integer array nums
.
Return the smallest sorted list of ranges that cover all the numbers in the array exactly. That is, each element of nums
is covered by exactly one of the ranges, and there is no integer x
such that x
is in one of the ranges but not in nums
.
Each range [a,b]
in the list should be output as:
-
"a->b"
ifa != b
-
"a"
ifa == b
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Example 4:
1 |
|
Example 5:
1 |
|
Constraints:
-
0 <= nums.length <= 20
-
-2^31 <= nums[i] <= 2^31 - 1
-
All the values of
nums
are unique.
Explanation
- Loop through the string, mark the current number as
left
. While the current numbernums[i]
plus one equal to the next numbernums[i+1]
, increasei
. Until the current number is not equal to the next number. Now,nums[i]
is theright
. Ifleft
andright
are not the same, we find the push the left range and right range to the result list. If theyleft
andright
are the same, that means only one number of the range, and we push eitherleft
orright
to the list.
Solution
1 |
|
Week 5: October 29th - October 31st
Encode N-ary Tree to Binary Tree
Design an algorithm to encode an N-ary tree into a binary tree and decode the binary tree to get the original N-ary tree. An N-ary tree is a rooted tree in which each node has no more than N children. Similarly, a binary tree is a rooted tree in which each node has no more than 2 children. There is no restriction on how your encode/decode algorithm should work. You just need to ensure that an N-ary tree can be encoded to a binary tree and this binary tree can be decoded to the original N-nary tree structure.
Nary-Tree input serialization is represented in their level order traversal, each group of children is separated by the null value (See following example).
For example, you may encode the following 3-ary
tree to a binary tree in this way:
1 |
|
Note that the above is just an example which might or might not work. You do not necessarily need to follow this format, so please be creative and come up with different approaches yourself.
Constraints:
-
The height of the n-ary tree is less than or equal to
1000
-
The total number of nodes is between
[0, 10^4]
-
Do not use class member/global/static variables to store states. Your encode and decode algorithms should be stateless.
Explanation
-
One way to encode the N-ary tree to a binary tree is using the method on Wikipedia. For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18N-ary Tree: 1 / | \ 3 2 4 / \ 5 6 Binary Tree: 1 / 3 / \ 5 2 \ \ 6 4
-
In the above example,
3, 2, 4
are in the same level under the parent node1
. First, we put this level’s first child node3
as the parent node’s left child. Then all other child nodes2, 4
will be put under the first child node3
’s right side. Similarlly, for the parent node3
, it has children5, 6
. We put this level’s first child node5
as node 3’s left child node. Then all other child nodes6
will be put under the first child node5
’s right side.
Solution
1 |
|
Maximize Distance to Closest Person
You are given an array representing a row of seats
where seats[i] = 1
represents a person sitting in the ith
seat, and seats[i] = 0
represents that the ith
seat is empty (0-indexed).
There is at least one empty seat, and at least one person sitting.
Alex wants to sit in the seat such that the distance between him and the closest person to him is maximized.
Return that maximum distance to the closest person.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Constraints:
-
2 <= seats.length <= 2 * 10^4
-
seats[i]
is0
or1
. -
At least one seat is empty.
-
At least one seat is occupied.
Explanation
-
We need to consider 3 cases. First case is there are left neighbor and right neighbor. For example, if the input is
[1, 0, 0, 0, 1]
, then Alex should sit in the middle, and the result is(rightNeighborIdx - leftNeighborIdx) / 2 = (4 - 0) / 2 = 2
. -
Second case is there is no left neighbor. For example, if the input is
[0, 0, 1]
, then Alex should sit in the first seat, and the result is equal to the first neighbor’s index which is 2. -
Third case is there is no right neighbor. For example, if the input is
[1, 0, 0]
, then Alex should sit in the last seat, and the result is equal tolastIdx - lastNeighborIdx = 2 - 0 = 2
. -
Initially, we need to find the first neighbor index, and initialize the result to be
max(1, firstNeighborIdx)
because the result is at least 1. Then, we record the left neighbor index to a variableleft
. Then loop through the array, whenseats[i]
is 1, that means we find a right neighbor, so we calculate the result using case 1’s function. When we iterate to the last index, if the last seat is not empty, then we use case 1’s function as normal, but if last seat is empty, then we use case 3’s function to calculate the result. At the end, we return the maximum result.
Solution
1 |
|
Number of Longest Increasing Subsequence
Given an integer array nums
, return the number of longest increasing subsequences.
Example 1:
1 |
|
Example 2:
1 |
|
Constraints:
-
0 <= nums.length <= 2000
-
-10^6 <= nums[i] <= 10^6
Explanation
-
Similar to 300. Longest Increasing Subsequence, we need an array
sizeArr[i]
represents the size of LIS and the LIS ends at indexi
. In this problem, we also need an arraycountArr[i]
represents the number of LIS and the LIS ends at indexi
. Both elements insizeArr
andcountArr
are initialized to 1. -
Loop
i
from index 0 to the last index. Inner loopj
from index 0 to indexi
exclusive. Ifnums[i] > nums[j]
that means we find an increasing sequence. Then we check ifsizeArr[i] < sizeArr[j] + 1
that means this is the first time we find an increasing sequence that ends at indexi
, so we updatesizeArr[i] = sizeArr[j] + 1
andcountArr[i] = countArr[j]
. Else ifsizeArr[i] == sizeArr[j] + 1
that means we find anotherj
that also can build the LIS ending at indexi
, so we only updatecountArr[i] += countArr[j]
. After the inner loop, we update thelongestSize = max(longestSize, sizeArr[i]
. -
Outside the outtter loop, we iterate the
sizeArr
, ifsizeArr[i]
equals tolongestSize
, then we update our countres += countArr[i]
. At the end, return the total countres
.
Solution
1 |
|
Recover Binary Search Tree
You are given the root
of a binary search tree (BST), where exactly two nodes of the tree were swapped by mistake. Recover the tree without changing its structure.
Follow up: A solution using O(n)
space is pretty straight forward. Could you devise a constant space solution?
Example 1:
1 |
|
Example 2:
1 |
|
Constraints:
-
The number of nodes in the tree is in the range
[2, 1000]
. -
-2^31 <= Node.val <= 2^31 - 1
Explanation
-
If we use O(n) space, we can use in-order traversal method to solve this problem. In a valid BST, if we use in-order traversal, all traversaled elements should be sorted, if it is not sorted, then this is not a valid BST.
-
If the correct valid BST is
[1, 2, 3, 4, 5, 6, 7, 8]
, if two elements are swaped mistake, let say 2 and 6 are swapped so we want to create two new variable to record 2 and 6, let sayfirst
andsecond
, and now the traversal elements become[1, 6, 3, 4, 5, 2, 7, 8]
. We find out 6 and 3 are not sorted in order (first is 6, second is 3), also 5 and 2 are not sorted in order (first remains 6, second is 2). So we swapfirst
andsecond
and we are done.
Solution
1 |
|