Continue working from home. It looks like LeetCode will continue this every day problem series. Let’s continue this one day one go problem for June LeetCoding Challenge.
Week 1: June 1st–June 7th
Invert Binary Tree
Invert a binary tree.
Example:
Input:
1 |
|
Output:
1 |
|
Trivia:
This problem was inspired by this original tweet by Max Howell:
Google: 90% of our engineers use the software you wrote (Homebrew), but you can’t invert a binary tree on a whiteboard so f*** off.
Explanation 1
- In a recursive way, we can recursivly swap the left child and right child.
Solution 1
1 |
|
Explanation 2
- In a non recursive way, we need to create a queue, and we can swap the left and right child level by level. First, push the root to the queue, while the queue is not empty, poll it out and swap its left and right child. After swapping, push their left and right child to the queue.
Solution 2
1 |
|
Delete Node in a Linked List
Write a function to delete a node (except the tail) in a singly linked list, given only access to that node.
Given linked list – head = [4,5,1,9], which looks like following:
Example 1:
1 |
|
Example 2:
1 |
|
Note:
-
The linked list will have at least two elements.
-
All of the nodes’ values will be unique.
-
The given node will not be the tail and it will always be a valid node of the linked list.
-
Do not return anything from your function.
Explanation
- This time we are only giving the node that we want to delete. We can replace this node’s value with
node.next.val
, and change it’snext
pointer tonode.next.next
.
Solution
1 |
|
Two City Scheduling
There are 2N
people a company is planning to interview. The cost of flying the i
-th person to city A
is costs[i][0]
, and the cost of flying the i
-th person to city B
is costs[i][1]
.
Return the minimum cost to fly every person to a city such that exactly N
people arrive in each city.
Example 1:
1 |
|
Note:
-
1 <= costs.length <= 100
-
It is guaranteed that
costs.length
is even. -
1 <= costs[i][0], costs[i][1] <= 1000
Explanation 1
-
Assume all people go to city A. From the problem’s example, we have the total cost be 10 + 30 + 400 + 30 = 470.
-
Now we need to assign half the people to go to city B. If we assign the first person to city B, we increase our total cost by 10. If assign the second person to city B, total cost increase 170. Assign third person to city B, total cost decrease 350. Assign fourth person to city B, total cost decrease 10. In other words,
[10, 170, -350, -10]
. Now we know we should assign the third person and the fourth person to city B. -
We can solve this problem by sorting based on the different cost between cityA and cityB. From the problem’s example, after sorting, we have
[[30, 200], [10, 20], [30, 20], [400, 50]]
. Now, we can calculate the total cost. The first half people go to city A, the second half people go to city B.
Solution 1
1 |
|
Explanation 2
-
We can also use Dynamic Programming to solve this problem.
-
Dynamic init is
dp[i][j]
represetns the total cost fori + j
people such thati
people go to city A, andj
people go to city B. The length of thedp
array isdp[len(costs)/2+1][len(costs)/ 2 + 1]
. -
Dynamic base is
dp[0][0] = 0
since if no people go to city A and no people go to city B, then the total cost will be 0. For the left most column,dp[i][0]
, if no people go to city B, then the total costdp[i][0] = costs[i-1][0] + dp[i-1][0];
. For the top row, if no people go to city A, then the total costdp[0][j] = costs[i-1][1] + dp[0][i-1];
. -
Dynamic function is for the index
i + j -1
person, if he/she goes to city A, then the total cost will becosts[r + c - 1][0] + dp[r-1][c];
. If he/she goes to city B, then the total cost will becosts[r + c - 1][1] + dp[r][c-1];
. So,dp[r][c]
will take the minimum between these two values. -
Dynamic result is
dp[len(costs)/2+1][len(costs)/ 2 + 1]
which represents the total cost for half people go to city A and half people go to city B.
Solution 2
1 |
|
Reverse String
Write a function that reverses a string. The input string is given as an array of characters char[]
.
Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
You may assume all the characters consist of printable ascii characters.
Example 1:
1 |
|
Example 2:
1 |
|
Hint 1:
The entire logic for reversing a string is based on using the opposite directional two-pointer approach!
Explanation
- We can loop the string from beginning to the middle. Swap it with character at index
s.length-1-i
.
Solution
1 |
|
Random Pick with Weight
Given an array w
of positive integers, where w[i]
describes the weight of index i
, write a function pickIndex
which randomly picks an index in proportion to its weight.
Note:
-
1 <= w.length <= 10000
-
1 <= w[i] <= 10^5
-
pickIndex
will be called at most10000
times.
Example 1:
1 |
|
Example 2:
1 |
|
Explanation of Input Syntax:
The input is two lists: the subroutines called and their arguments. Solution
’s constructor has one argument, the array w
. pickIndex
has no arguments. Arguments are always wrapped with a list, even if there aren’t any.
Explanation
-
This problem asks us to random pick a number based on their weight. For example, if the input array is
[1, 3]
, then we pick 1 in probability 1/4, pick 3 in probability 3/4. Sincerandom()
will generate an equal probability number, instead of generate usingrand() % 2
, we will randomly generate usingrand() % 4
. If the random number is 0, then we pick 1, if the random number is from 1 to 3 inclusive, then we pick 3. -
We will generate an accumulate sum array first. If the input is
[1, 3, 2]
, then the accumulate sum array will be[1, 4, 6]
. The sum of all number is 6, so we will generate a random number byn = rand() % 6 + 1
, which is in between 1 to 6 inclusive. If the random number is 1, we return index 0; if the random number is either 2, 3, 4, we return index 1. If the random number is either 5, 6, we return index 2. In other words, we will pick the first number from the accumulate sum array that is greater than or equal than the random number, and that number’s index is the result.
Solution
1 |
|
Queue Reconstruction by Height
Suppose you have a random list of people standing in a queue. Each person is described by a pair of integers (h, k)
, where h
is the height of the person and k
is the number of people in front of this person who have a height greater than or equal to h
. Write an algorithm to reconstruct the queue.
Note:
The number of people is less than 1,100.
Example
1 |
|
Hint 1:
What can you say about the position of the shortest person? If the position of the shortest person is i, how many people would be in front of the shortest person?
Hint 2:
Once you fix the position of the shortest person, what can you say about the position of the second shortest person?
Explanation
-
First, we sort the input array by the higher height
h
in front, if same height, then smallk
in front. -
After we sort the array, we can create a result list. Iterate the sorted array, we add each iterated sub array to the result list on position equals to the the sub array’s
k
value. -
For example, if input is
[[7,0], [4,4], [7,1], [5,0], [6,1], [5,2]]
. After sort, we have[[7,0], [7,1], [6,1], [5,0], [5,2], [4,4]]
. Each iteration will be:
1 |
|
- At the end, we convert the result list to array and return it.
Solution
1 |
|
Coin Change 2
You are given coins of different denominations and a total amount of money. Write a function to compute the number of combinations that make up that amount. You may assume that you have infinite number of each kind of coin.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Note:
You can assume that
-
0 <= amount <= 5000
-
1 <= coin <= 5000
-
the number of coins is less than 500
-
the answer is guaranteed to fit into signed 32-bit integer
Explanation 1
-
We can use dynamic programming to solve this problem. Dynamic state is
dp[coins.length][amount+1]
. In this two dimensional array,dp[i][j]
means the total ways of making up amountj
using the firsti
index coins. -
Dynamic init is
dp[i][0] = 1
for anyi
because if the amount is 0, then we have only 1 way of making up amount 0, which is[]
. Also, if we only have 1 coin, thendp[0][i] = 0 + dp[0][i - coins[0]]
because if we exclude this coin, then we have 0 way to make the amounti
, and if we include this coin, then we have the same number of choices asdp[0][i - coins[0]
. -
Dynamic function. If
coins[i] > curAmount
, we must exclude this coin, thendp[i][a] = dp[i-1][a]
because we cannot use the current coins because it’s too large. Elsedp[i][a] = dp[i-1][a] + dp[i][a - coins[i]
because now the total ways is the total ways of exclude the current coint plus include the current coins with updating amount. -
Dynamic result is
dp[coins.length-1][amount]
, which uses all coins and make up amountamount
.
Solution 1
1 |
|
Explanation 2
- We can save space by using only 1 dimensional array.
Solution 2
1 |
|
Explanation 3
- We can also use top down approach to solve this problem.
Solution 3
1 |
|
Week 2: June 8th–June 14th
Power of Two
Given an integer, write a function to determine if it is a power of two.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Explanation
-
We can use bit manipulation to solve this problem. We notice that every number that is power of two will have a binary pattern that the only highest bit is 1, every other bit is 0. For example:
1
2
3
4
51 -> 1 2 -> 10 4 -> 100 8 -> 1000 16 -> 10000
-
We can check from the lowest bit to the highest bit, count how many 1 does this number has by using AND operator with 1 and the current bit, update the counter, then move the number
n
to right by 1 bit. -
At the end we check if counter equals 1.
Solution
1 |
|
Is Subsequence
Given a string s and a string t, check if s is subsequence of t.
A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ace"
is a subsequence of "abcde"
while "aec"
is not).
Follow up:
If there are lots of incoming S, say S1, S2, … , Sk where k >= 1B, and you want to check one by one to see if T has its subsequence. In this scenario, how would you change your code?
Credits:
Special thanks to @pbrother for adding this problem and creating all test cases.
Example 1:
1 |
|
Example 2:
1 |
|
Constraints:
-
0 <= s.length <= 100
-
0 <= t.length <= 10^4
-
Both strings consists only of lowercase characters.
Explanation 1
- We can use recursive approach to solve this problem. Compare the first string of both strings, if they are equal, then we recursively call the main function with
s[1:]
andt[1:]
. Else, we recursively call the main function withs
andt[1:]
.
Solution 1
1 |
|
Explanation 2
- We can use two pointers approach to solve this problem. We use variable
sIdx
points to the current character at strings
, and usei
points to the current character at stringt
. Then, loop through all characters int
. Ifs[sIdx]
is equal tot[i]
, then we increasesIdx
. IfsIdx
is equals to length ofs
, then we immediately return true. Outside the loop, we return false.
Solution 2
1 |
|
Explanation 3
-
For the follow up question, if we have a lot of
s
, andt
is unchanged, how can we improve. We can start working fort
since it’s unchanged. First, we can create an array of listList[26]
; in other words, for each character, it has a list that contains all this character’s index att
. Since we are loop throught
from left to right, then each array element’s list’s index will be sorted. -
Next, we loop through
s
. For each character, we check if its corresponding list is empty or not, if empty, that means there’s no currents
’s character int
, so we return false. Else, we use binary search in the corresponding character’s list to search for the insertion index forstartTIdx
.startTIdx
is initialized to 0, and it is the index oft
that we are begin to search. Now if the binary search resultinsertion
is equals to its corresponding list’s size, that meansstartTIdx
is greater than the last index of the current character that we can find int
, so we returnfalse
. Else, we updatedstartTIdx
beinsertion
plus one.
Solution 3
1 |
|
Search Insert Position
Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.
You may assume no duplicates in the array.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Example 4:
1 |
|
Explanation
- We can use binary search to solve this problem.
Solution
1 |
|
Sort Colors
Given an array with n objects colored red, white or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white and blue.
Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.
Note: You are not suppose to use the library’s sort function for this problem.
Example:
1 |
|
Follow up:
-
A rather straight forward solution is a two-pass algorithm using counting sort. First, iterate the array counting number of 0’s, 1’s, and 2’s, then overwrite array with total number of 0’s, then 1’s and followed by 2’s.
-
Could you come up with a one-pass algorithm using only constant space?
Explanation
-
We can use two pointer method to solve this problem. First, we delcare a redPointer points at the beginning, and a bluePointer points at the end index. Now, iterate from the beginning, if the element is red (0), then we swap it with the element that redPointer points at, redPointer moving forward. If the element is blue (2), then we swap it with the element that the bluePointer points at, bluePointer moving backward.
-
One corner case is when the element that the blue pointer points at is red (0), when iterating, if the current iterated element is blue (2), then we swap it with the red (0), now the iterator shouldn’t move to the next, it should check this iterated current element again and move the red (0) element to the correct position.
Solution
1 |
|
Insert Delete GetRandom O(1)
Design a data structure that supports all following operations in average O(1) time.
-
insert(val)
: Inserts an item val to the set if not already present. -
remove(val)
: Removes an item val from the set if present. -
getRandom
: Returns a random element from current set of elements. Each element must have the same probability of being returned.
Example:
1 |
|
Explanation
-
If we don’t consider the $O(1)$ runtime, we can easily use a set to solve this problem, but now the required runtime is $O(1)$, we know that to get a specific index element in a set is not $O(1)$, so we cannot use a set to solve this problem. To solve this, we need to use an ArrayList
lst
and a HashMaphm
with hashmap key is the inserted value, hashmap value is the ArrayList’s index. -
For the
Insert(val)
method, if the hashmap already contains the value, we return false immdediately. Else, we can just push theval
to the end of the ArrayListlst
and return true. -
For the
remove(val)
method, if the hashmap doesn’t contain the value, we return false immediately. Else, we get the indexpos
of the removed value, and update this position in the array listlst[pos]
with the last array list’s element. For example, if the array list is[2, 5, 7, 9]
and we want to remove5
, then after update, we have[2, 9, 7, 9]
, we also update thehashmap[lastEle] = pos
. Next, we want to remove the last element in the array list, and removehashmap[val]
. -
For the
getRandom
method, we can just return arraylist’s random index value.
Solution
1 |
|
Largest Divisible Subset
Given a set of distinct positive integers, find the largest subset such that every pair (Si, Sj) of elements in this subset satisfies:
Si % Sj = 0 or Sj % Si = 0.
If there are multiple solutions, return any subset is fine.
Example 1:
1 |
|
Example 2:
1 |
|
Explanation
-
Since the small number cannot be divisible by the large number, we need to first sort the array.
-
We can use Dynamic Programming to solve this problem.
dp[i]
means the maximum number of divisible elements from index 0 to indexi
inclusive. -
Dynamic init is all
dp[i]
equals 1 sincenums[i]
themselves is one number. -
Next, we loop
i
from 0 to the last index, inside the for loop, we create another for loop that loops fromi-1
to 0. Ifnums[i] % nums[j] == 0
anddp[j]+1 > dp[i]
, then we updatedp[i]
, and we recordnums[j]
can divisiblenums[i]
by having an arraydivisibleInd[i]
to record the index of the number that can divisibledivisible[i]
, in this case,divisibleInd[i] = j
. Outside of the inner for loop, we have the maximum length of divisible number from index 0 to indexi
inclusive, then we updatemax = dp[i]
andmaxInd = i
. -
Outside of these two for loops, now we have
max
that represents the maximum length of divisible numbers, in other words, the length of result array. We can get these elements by using thedivisibleInd[]
since it records each number’s divisible number’s index. For example, if the input array is[2, 4, 6, 8]
, then 4 is pointing to 2, 6 is pointing to 4, 8 is pointing to 6.
Solution
1 |
|
Cheapest Flights Within K Stops
There are n
cities connected by m
flights. Each flight starts from city u
and arrives at v
with a price w
.
Now given all the cities and flights, together with starting city src
and the destination dst
, your task is to find the cheapest price from src
to dst
with up to k
stops. If there is no such route, output -1
.
Example 1:
Input:
n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]]
src = 0, dst = 2, k = 1
Output: 200
Explanation:
The graph looks like this:
The cheapest price from city 0 to city 2 with at most 1 stop costs 200, as marked red in the picture.
Example 2:
Input:
n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]]
src = 0, dst = 2, k = 0
Output: 500
Explanation:
The graph looks like this:
The cheapest price from city 0 to city 2 with at most 0 stop costs 500, as marked blue in the picture.
Constraints:
-
The number of nodes
n
will be in range[1, 100]
, with nodes labeled from0
ton - 1
. -
The size of
flights
will be in range[0, n * (n - 1) / 2]
. -
The format of each flight will be
(src, dst, price)
. -
The price of each flight will be in the range
[1, 10000]
. -
k
is in the range of[0, n - 1]
. -
There will not be any duplicated flights or self cycles.
Explanation
-
Similar to Dijkstra’s Algorithm, but in this problem we are limited to K+1 edges from the source to destination.
-
First, we build the adjacent list. For each neighbor element, besides the destination vertex, we also keep track of the distance to reach the destination. For example, from the problem’s example 1, we have adjacent list
[[{1, 100}, {2, 500}], [{2, 100}], []]
. -
In Dijkstra’s Algorithm, we start from the source vertex, in other word, we start from the smallest distance from the source. In this problem, we can create a priority queue, each element in the priority queue will be an array of size 3; the first array element is the vertex, the second array element is the distance from source, the third element is the number of edges from source to this vertex. So initially, we push
int[]{src, 0, 0}
to the priority queue. -
While the priority queue is not empty, we poll the array
[vertex, distance, numEdge]
from the queue. If this array’svertex
is the destination, then we immediately return itsdistance
. If this array’snumEdge
is equal toK + 1
, we skip this vertex since we can’t have more thanK
stops orK + 1
edges from the source. Else, we loop through the neighbors of the current array’svertex
. For each neighbor, we update its distance bedistance + neighbor[1]
, update its number of edge benumEdge + 1
, and store them to the priority queue. Repeat until the priority queue is empty. -
If the priority queue is empty and we still not found the destination, then we return -1.
Solution
1 |
|
Week 3: June 15th–June 21st
Search in a Binary Search Tree
Given the root node of a binary search tree (BST) and a value. You need to find the node in the BST that the node’s value equals the given value. Return the subtree rooted with that node. If such node doesn’t exist, you should return NULL.
For example,
1 |
|
You should return this subtree:
1 |
|
In the example above, if we want to search the value 5
, since there is no node with value 5
, we should return NULL
.
Note that an empty tree is represented by NULL
, therefore you would see the expected output (serialized tree format) as []
, not null
.
Explanation 1
-
Since the tree is a binary search tree, so the left child value is less than the root value, and the right child value is greater than the root value.
-
We can do it in a recursive way. If root is NULL, then we return NULL. If root value is equal to target value, then we return the root. If target value is less than the root value, then we recursively call the main function with
root.left
and the target value. Else, we recursively call the main function withroot.right
and the target value.
Solution 1
1 |
|
Explanation 2
- We can also do it in iterative way. First, we create a pointer
cur
pointing to the root. Whilecur
is not NULL, then we check ifcur.val
is equal to target, then we returncur
. Else if target value is less thancur.val
, then we updatecur = cur.left
. Else if target value is greater thancur.val
, we updatecur = cur.right
. Outside the while loop, that meanscur
is NULL and we haven’t found the target value, so we return NULL.
Solution 2
1 |
|
Validate IP Address
Write a function to check whether an input string is a valid IPv4 address or IPv6 address or neither.
IPv4 addresses are canonically represented in dot-decimal notation, which consists of four decimal numbers, each ranging from 0 to 255, separated by dots (“.”), e.g.,172.16.254.1
;
Besides, leading zeros in the IPv4 is invalid. For example, the address 172.16.254.01
is invalid.
IPv6 addresses are represented as eight groups of four hexadecimal digits, each group representing 16 bits. The groups are separated by colons (“:”). For example, the address 2001:0db8:85a3:0000:0000:8a2e:0370:7334
is a valid one. Also, we could omit some leading zeros among four hexadecimal digits and some low-case characters in the address to upper-case ones, so 2001:db8:85a3:0:0:8A2E:0370:7334
is also a valid IPv6 address(Omit leading zeros and using upper cases).
However, we don’t replace a consecutive group of zero value with a single empty group using two consecutive colons (::) to pursue simplicity. For example, 2001:0db8:85a3::8A2E:0370:7334
is an invalid IPv6 address.
Besides, extra leading zeros in the IPv6 is also invalid. For example, the address 02001:0db8:85a3:0000:0000:8a2e:0370:7334
is invalid.
Note: You may assume there is no extra space or special characters in the input string.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Explanation
-
If the input string has
.
that means we need to check if it’s IPv4. Else if the string has:
, that means we need to check if it’s IPv6. If the input string doesn’t have neither.
nor:
, then we returnNeither
. -
When we check if the input string is IPv4. First, we split the string by
.
and check the length of the splitted array. If the length is not 4, then we immediately returnNeither
. Next, we loop through and check these 4 string tokens. If the token’s length is 0 or greater than 3, then we immediately returnNeither
. Next, we check if the first character of the token string is0
and its length is not 1, then we returnNeither
immediately. Next, we check if this token string can be converted into integer and its value is between 0 and 255. If one of the condition is false, we returnNeither
. After checking these 4 token strings, we returnIPv4
. -
When we check if the input string is IPv6. First, we split the string by
:
and check the length of the splitted array. If the length is not 8, then we immediately returnNeither
. Next, we loop through and check these 8 string tokens. If the token’s length is 0 or greater than 4, then we immediately returnNeither
. Next, we loop through every character of the token and see if every character is in the range of[0-9a-fA-F]
. If one of the condition is false, we returnNeither
. After checking these 8 token strings, we returnIPv6
.
Solution
1 |
|
Surrounded Regions
Given a 2D board containing 'X'
and 'O'
(the letter O), capture all regions surrounded by 'X'
.
A region is captured by flipping all 'O'
s into 'X'
s in that surrounded region.
Example:
1 |
|
After running your function, the board should be:
1 |
|
Explanation:
Surrounded regions shouldn’t be on the border, which means that any 'O'
on the border of the board are not flipped to 'X'
. Any 'O'
that is not on the border and it is not connected to an 'O'
on the border will be flipped to 'X'
. Two cells are connected if they are adjacent cells connected horizontally or vertically.
Explanation
-
First, we can find the boarder’s character, if they are ‘O’, then we flood fill them to ‘Y’.
-
Next, we can replace the rest of ‘O’ to be ‘X’ since they are not connected to the boarder.
-
Finally, replace all ‘Y’ back to ‘O’.
Solution
1 |
|
H-Index II
Given an array of citations sorted in ascending order (each citation is a non-negative integer) of a researcher, write a function to compute the researcher’s h-index.
According to the definition of h-index on Wikipedia: “A scientist has index h if h of his/her N papers have at least h citations each, and the other N − h papers have no more than h citations each.”
Example:
1 |
|
Note:
If there are several possible values for h, the maximum one is taken as the h-index.
Follow up:
-
This is a follow up problem to H-Index, where
citations
is now guaranteed to be sorted in ascending order. -
Could you solve it in logarithmic time complexity?
Hint 1:
Expected runtime complexity is in O(log n) and the input is sorted.
Explanation
-
If we want to solve it in $O(\log n)$ time, we can use binary search method. While
left < righ
, when we get themid
index, then we calculate how many elements is equal to or greater thancitations[mid]
bylen - mid
. Assumelen-mid
is theh
, we compare it withcitations[mid]
sinceh
paper should have at leasth
citations each. -
If
citations[mid]
is less thanlen-mid
, that meansh
should be smaller, so we updateleft = mid + 1
. -
If
citations[mid]
is greater thanlen-mid
, that meansh
should be bigger, so we updateright = mid
. -
Outside the while loop,
len-left
will be theh
.
Solution
1 |
|
Longest Duplicate Substring
Given a string S
, consider all duplicated substrings: (contiguous) substrings of S that occur 2 or more times. (The occurrences may overlap.)
Return any duplicated substring that has the longest possible length. (If S
does not have a duplicated substring, the answer is ""
.)
Example 1:
1 |
|
Example 2:
1 |
|
Note:
-
2 <= S.length <= 10^5
-
S
consists of lowercase English letters.
Hint 1:
Binary search for the length of the answer. (If there’s an answer of length 10, then there are answers of length 9, 8, 7, …)
Hint 2:
To check whether an answer of length K exists, we can use Rabin-Karp ‘s algorithm.
Explanation
-
Assume the longest duplicate substring has length
ldsLen
, we create a helper function to find the longest duplicate substring with lengthldsLen
from the input string. If we find it, then we update the result string equal to the longest duplicate substring we found; and we increaseldsLen
and run it with helper function. Else we don’t find it, we can decreaseldsLen
and run it with the helper function. We can use binary search to find the largestldsLen
. -
In the helper function, we can loop the
startIdx
from index 0 to indexlen(S) - ldsLen + 1
inclusive. In each iteration, we check if the current stringS[startIdx, startIdx + ldsLen]
is in the set or no. If it’s not in the set, we add it to the set. Else, that means we find a dupliate stringS[startIdx, startIdx + ldsLen]
with lengthldsLen
.
Solution
1 |
|
Permutation Sequence
The set [1,2,3,...,n]
contains a total of n! unique permutations.
By listing and labeling all of the permutations in order, we get the following sequence for n = 3:
-
"123"
-
"132"
-
"213"
-
"231"
-
"312"
-
"321"
Given n and k, return the kth permutation sequence.
Note:
-
Given n will be between 1 and 9 inclusive.
-
Given k will be between 1 and n! inclusive.
Example 1:
1 |
|
Example 2:
1 |
|
Explanation
-
For example, when
n=4
,k=9
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
241234 1243 1324 1342 1423 1432 2134 2143 2314 <= k = 9 2341 2413 2431 3124 3142 3214 3241 3412 3421 4123 4132 4213 4231 4312 4321
-
The most significant digit can be choosen from {1, 2, 3, 4}, and each number in the most significant digit is repeated
(n-1)! = 6
times. So, in the result, the most significant digit will be the second (res[0] = 9 / 6 + 1 = 2
) number, which is 2. -
Now we know the result’s most significant digit is the number 2, then we need to find out what’s the number for the second most significant digit, and we can only choose from number {1, 3, 4} in these 6
(3!)
numbers: 2134, 2143, 2314, 2341, 2413, 2431.k
is 9, now the newk'
will become9 % (3!) = 9 % 6 = 3
. And each number {1, 3, 4} in the second most significant digit is repeated(n-2)! = 2
times. So, in the result, the second most significant digit will be the second (res[1] = 3 / 2 + 1 = 2
) number, which is 3. -
Now we know the result is starting from 23, and we can only choose from number {1, 4} in these 2
(2!)
numbers: 2314, 2341.k'
is 3, now the newk''
will become3 % (2!) = 3 % 2 = 1
. And each number {1, 4} in the third most significant digit is appear(n-3)! = 1
time. So, in the result, the third most significant digit will be the first number, which is 1. -
Now we know the result is starting from 231, and there is only {4} left, so the last digit is 4, and the result will be 2314.
-
Basically, after we find out the most significant digit by doing
k / fac[i]
, then we need to find out the new k in the next most significant digit by doingk % fac[i]
, and repeat the process.
Solution
1 |
|
Dungeon Game
The demons had captured the princess (P) and imprisoned her in the bottom-right corner of a dungeon. The dungeon consists of M x N rooms laid out in a 2D grid. Our valiant knight (K) was initially positioned in the top-left room and must fight his way through the dungeon to rescue the princess.
The knight has an initial health point represented by a positive integer. If at any point his health point drops to 0 or below, he dies immediately.
Some of the rooms are guarded by demons, so the knight loses health (negative integers) upon entering these rooms; other rooms are either empty (0’s) or contain magic orbs that increase the knight’s health (positive integers).
In order to reach the princess as quickly as possible, the knight decides to move only rightward or downward in each step.
Write a function to determine the knight’s minimum initial health so that he is able to rescue the princess.
For example, given the dungeon below, the initial health of the knight must be at least 7 if he follows the optimal path RIGHT-> RIGHT -> DOWN -> DOWN
.
-2 (K) | -3 | 3 |
-5 | -10 | 1 |
10 | 30 | -5 (P) |
Note:
-
The knight’s health has no upper bound.
-
Any room can contain threats or power-ups, even the first room the knight enters and the bottom-right room where the princess is imprisoned.
Explanation
-
We can use dynamic programming to solve this problem.
-
Dynamic state is a two dimensional array.
dp[r][c]
means the initial health point before fighting at position(r, c)
, so the return result will bedp[0][0]
. -
Dynamic init, we create one more row and column, and we assign these whole new row and new column’s elements all be maximum number. We will start from the princess’s position, and the princess’s position depends on its down and right position. We will assign these two positions be 1 instead of maximum because after fighting at the pricness’s position, the knight at least have 1 health point before going to down or right position.
-
Dynamic function, the health point before fighting is
dp[r][c]
, so before fighting at its down position, the health point fordp[r+1][c] = dp[r][c] + dungeon[r][c]
, in other word,dp[r][c]
is depend on its down position, sodp[r][c] = dp[r+1][c] - dungeon[r][c]
. If the knight goes to the right position, thendp[r][c] = dp[r][c+1] - dungeon[r][c]
. To use less point as possible, the knight will choose the less point to go to, so it ismin[dp[r+1][c], dp[r][c+1]
. If the subtraction result is negative, then we will lose, sodp[r][c]
has at least 1 health point. Therefore, we get our dynamic functiondp[r][c] = Math.max(1, Math.min(dp[r+1][c], dp[r][c+1]) - dungeon[r][c])
. -
Dynamic result is
dp[0][0]
which is the beginning top left position.
Solution
1 |
|
Week 4: June 22nd–June 28th
Single Number II
Given a non-empty array of integers, every element appears three times except for one, which appears exactly once. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
Example 1:
1 |
|
Example 2:
1 |
|
Explanation 1
-
If the input array is
[10, 10, 13, 10]
, then the result should be 13. The binary representation of the input array would be:1
2
3
41010 1010 1101 <--- result 1010
For each bit, we sum every numbers’ value, then we get:
1
4131
Then, we module each bit number by 3, then we get the result in binary:
1
1101
-
We can code the above approach. Create an array
bits[]
of size 32. Loopi
32 times, for each bitbits[i]
, we inner loop the input array. For each number, to get its corresponding bit value, we can right shift the current numberi
times and AND 1. So we sum each number’s result tobits[i]
. Also, each time, we take module 3 ofbits[i]
. -
After we get the result
bits[]
in binary format, we can convert it back to integer. Loop 32 times, each time, we left shift the current biti
times and sum this result as our final result.
Solution 1
1 |
|
Explanation 2
-
We can solve this problem in one pass. Now we create two variables
int ones
which records the number of same position bits have been occured 1 time, 4 time, 7 time… andint twos
records the number of same position bits have been occured 2 time, 5 time, 8 time… . If the same position bits have been occured 3 time, 6 time, 9 time, then we think of them appear 0 time. -
Using this example input
[10, 10, 13, 10]
and loop through this array.- Current value in binary format: 1010;
ones = [1010]
;twos = [0000]
. - Current value in binary format: 1010;
ones = [0000]
;twos = [1010]
. - Current value in binary format: 1101;
ones = [0101]
;twos = [0010]
. - Current value in binary format: 1010;
ones = [1101]
;twos = [0000]
.
- Current value in binary format: 1010;
-
We can calculate
twos
bytwos = twos OR (ones AND num)
, and calculateones
byones = ones XOR num
. Now, if hit the first one,ones = 0 xor 1 = 1
. If hit the second one,ones = 1 xor 1 = 0
. If hit the third one,ones = 0 xor 1 = 1
. Since we have seen three1
s, we wantones
be 0. We can achieve this by also create a variablethrees
to record the number of bits have been occured three times. Thenthrees = ones & twos
. Each iteration, after we calculatethrees
, we updateones = ones AND (NOT threes)
, similarlly fortwos = twos AND (NOT threes)
.
Solution 2
1 |
|
Count Complete Tree Nodes
Given a complete binary tree, count the number of nodes.
Note:
Definition of a complete binary tree from Wikipedia:
In a complete binary tree every level, except possibly the last, is completely filled, and all nodes in the last level are as far left as possible. It can have between 1 and 2h nodes inclusive at the last level h.
Example:
1 |
|
Explanation
-
Get the left most’s height and right most’s height. If they are equal, then the tree is a full binary tree, which means all nodes have two children except the leaves nodes. So a full binary tree has total $2^h-1$ nodes.
-
If the left most height and right most height are not equal, we can recursivly call this method for the left child and also call this method for the right child, also plus one which is for the root node.
Solution
1 |
|
Unique Binary Search Trees
Given n, how many structurally unique BST’s (binary search trees) that store values 1 … n?
Example:
1 |
|
Explanation
-
We can use dynamic programming to solve this problem.
-
Dynamic state is a one dimensional array,
dp[n]
means when input isn
, the total number of unique BST. -
Dynamic init is
dp[0] = 1
,dp[1] = 1
. For example, whenn
is 1, we only have one way to struct the unique BST. -
Dynamic function. When
n = 2
, the total number of unqiue BST is 2, in other word, the root node can be 1, right node can be 2; or root node is 2, left node is 1. Whenn = 3
, we have three cases: when root node is element 1, there is 0 node on the left and there are 2 nodes on the right; when root node element is 2, there is 1 node on the left and 1 node on the right; when root node is element 3, there are 2 nodes on the left and 0 node on the right. We can illustrate it below:1
2
31 2 3 / \ / \ / \ 0 2 1 1 2 0
-
From the above illustration, input
n=3
, when root node is element 1, it can only have 0 node on the left and 2 nodes on the right, and there are 2 unique ways becausedp[0] = 1
,dp[2] = 2
, and1 * 2 = 2
. When root node is element 2, there is one node on the left and one on the right, and there is 1 unique way becausedp[1] = 1
,1 * 1 = 1
. When root node is element 3, there are two node on the left and zero node on the right, and there are 2 unique ways becausedp[2] = 2
,dp[0] = 1
,2 * 1 = 2
. Therefore, when input is3
, we havedp[0]*dp[2] + dp[1]*dp[1] + dp[2]*dp[0] = 5
unique ways. So, when input isn
, if there is0
node on the left, then there aren-1
node on the right because we need to subtract there is 1 root node.
Solution
1 |
|
Find the Duplicate Number
Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one.
Example 1:
1 |
|
Example 2:
1 |
|
Note:
-
You must not modify the array (assume the array is read only).
-
You must use only constant, O(1) extra space.
-
Your runtime complexity should be less than O(n2).
-
There is only one duplicate number in the array, but it could be repeated more than once.
Explanation 1
- If we can modify the array, then we loop through the array, and each iteration we add
m = len(nums)
tonums[nums[i]]
. For example, if the input array is[1, 3, 4, 2, 2]
. After this loop, we have[1, 8, 14, 7, 7]
. The unique number will be less than2 * len(nums)
. If the number is more than2 * len(nums)
and it’s the maximum number, then this maximum number’s index is the duplicated number, whiich is 2 in this example. We can reverse this array to the original array by module each number bylen(nums)
.
Solution 1
1 |
|
Explanation 2
-
This problem can use the same technique as 142. Linked List Cycle II since there are duplicated number in the array and each integer is between 1 and n (inclusive), it must have a cycle. For example, if the input is
[1, 2, 3, 4, 2]
, we have (both the duplicated number 2 are pointing to 3):1
2
31->2->3->4->2 | | <------
-
Initialize
slow
andfast
be 0, thenslow
moves one step,slow = nums[slow]
;fast
moves two steps,fast = nums[fast]; fast = nums[fast]
, in other words,fast = nums[nums[fast]]
. Repeat this step, untilslow = fast
, which is their meeting point. -
Then,
slow
set to 0 instead ofnums[0]
because in 142. Linked List Cycle II this method, we find the cycle starting point which is 3 in the above example, but now we want to find the point that is one step before the the cycle starting point, so we setslow
to 0. Nowslow
andfast
move at the same speed, this time their meeting point is the point before the meeting point, which is the duplicated number.
Solution 2
1 |
|
Sum Root to Leaf Numbers
Given a binary tree containing digits from 0-9
only, each root-to-leaf path could represent a number.
An example is the root-to-leaf path 1->2->3
which represents the number 123
.
Find the total sum of all root-to-leaf numbers.
Note: A leaf is a node with no children.
Example:
1 |
|
Example 2:
1 |
|
Explanation
-
We can use recursion method to solve. Whenever we encounted a root value, we will multiple the previous sum by 10 then add the current root value to become a new sum.
-
We can think of the left node as a root, the right node as a root, then solve them recursivly and pass the new sum as left child and right child’s previous sum to the helper method to get their sums and add them both to become the root’s sum.
Solution
1 |
|
Perfect Squares
Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...
) which sum to n.
Example 1:
1 |
|
Example 2:
1 |
|
Explanation
-
We can solve this problem using dynamic programming. Dynamic state is creating an one dimensional array
dp
has lengthn+1
since ifn=5
, array will start have index0, 1, 2, 3, 4, 5
.dp[i]
means the numOfPerfectSquares fori
, so the result we will return isdp[5]
. -
Dynamic init is
dp[i] = i
since every positive numbern
can be formed byn
number of perfect square 1. -
Dynamic function will be
dp[i] = min(dp[i], dp[i - j*j] + 1
, thej
means loop from 1 untilj*j <= i
. We plus one becausedp[j*j] = 1
. For example,dp[5] = dp[5-1*1]+1 = dp[4]+1 = 2
,dp[5]
can also bedp[5-2*2]+1 = dp[1]+1 = 2
. The base case isdp[0]=0
ifi == j*j
, thendp[i] = dp[0]+1=1
. -
Dynamic result is
dp[n]
.
Solution
1 |
|
Reconstruct Itinerary
Given a list of airline tickets represented by pairs of departure and arrival airports [from, to]
, reconstruct the itinerary in order. All of the tickets belong to a man who departs from JFK
. Thus, the itinerary must begin with JFK
.
Note:
-
If there are multiple valid itineraries, you should return the itinerary that has the smallest lexical order when read as a single string. For example, the itinerary
["JFK", "LGA"]
has a smaller lexical order than["JFK", "LGB"]
. -
All airports are represented by three capital letters (IATA code).
-
You may assume all tickets form at least one valid itinerary.
-
One must use all the tickets once and only once.
Example 1:
1 |
|
Example 2:
1 |
|
Explanation
-
First, we should construct a graph adjacency list using a HashMap
hm<String, PriorityQueue<String>>
. -
Then we use DFS passing the starting point
JFK
as parameter. Inside this DFS, we iterate this priority queuehm.get(startingPoint)
, poll out the first String in the priority queue (remove the edge so don’t repeat) and pass it to the recursive DFS method. The base case is Ifhm.get(startingPoint)
is NULL, which means it’s the end point, then we add it in front of the result list.
Solution
1 |
|
Week 5: June 29th–June 30th
Unique Paths
A robot is located at the top-left corner of a m x n grid (marked ‘Start’ in the diagram below).
The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked ‘Finish’ in the diagram below).
How many possible unique paths are there?
Above is a 7 x 3 grid. How many possible unique paths are there?
Example 1:
1 |
|
Example 2:
1 |
|
Constraints:
-
1 <= m, n <= 100
-
It’s guaranteed that the answer will be less than or equal to
2 * 10 ^ 9.
Explanation
-
We can solve this whole problem by solving the subproblem, so we can use dynamic programming.
-
We can make a tow dimensional array
dp[row][col]
representing that the total steps reach the coordinate ofrow
andcol
. Anddp[row][col] = dp[row-1][col] + dp[row][col-1]
which means the total steps of reaching the current coordinate is equal to the steps reaching the top row plus the steps reaching the left column. -
The base case is reaching any coordinate of the first row is always 1, and reaching the first column is also always 1.
-
Now we can just find out the value of
dp[row-1][col-1]
.
Solution 1
1 |
|
Solution 2
1 |
|
Word Search II
Given a 2D board and a list of words from the dictionary, find all words in the board.
Each word must be constructed from letters of sequentially adjacent cell, where “adjacent” cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once in a word.
Example:
1 |
|
Note:
-
All inputs are consist of lowercase letters
a-z
. -
The values of
words
are distinct.
Hint 1:
You would need to optimize your backtracking to pass the larger test. Could you stop backtracking earlier?
Hint 2:
If the current candidate does not exist in all words’ prefix, you could stop backtracking immediately. What kind of data structure could answer such query efficiently? Does a hash table work? Why or why not? How about a Trie? If you would like to learn how to implement a basic trie, please work on this problem: Implement Trie (Prefix Tree) first.
Explanation
- We can also use Trie to solve this problem. First, insert all words into the trie. Then loop through the board’s every character. For each character, we use DFS to check if the Trie has this character as a children. If not, then return. Else, we mark the character as visited; append this character into the current string; if this character in the trie is the end of word, then we add the updated current string into the result set. Next, we keep DFS with the updated string, updated Trie pointer and updated position. After DFS of the 4 directions, we restore the visited character as unvisited.
Solution
1 |
|