Introduction
After praticing many LeetCode problems, I think it’s very important to summarize different patterns for the coding problems. I found out Grokking the Coding Interview: Patterns for Coding Questions explains very well, but some of the contents is not free, so I will refernce its free part, and also adding the problems that I found online and grouping them into the corresponding patterns.
Sliding Window
Find the average of all contiguous subarrays
In a coding problem, if we see words like “contiguous subarrays”, then we should think about solving it using sliding window. For example:
Given an array consisting of n integers, find the average of all contiguous subarray of given length k
Example:
1 |
|
Explanation
-
First, we want to create a sliding window. So, we create two pointers
windowStart
andwindowEnd
and they both initialize to 0. -
We start iterate the
windowEnd
first, and in each iteration, we add the current number into thewindowSum
. Once the window length is equal tok
, we calculate the average of thewindowSum
and add the average result to the result array, then subtractwindowStart
and movewindowStart
1 step forward. OncewindowEnd
hit the end of iteration, we finish and return the result array.
Solution
1 |
|
Maximum Sum Subarray of Size K
Given an array of positive numbers and a positive number k
, find the maximum sum of any contiguous subarray of size k
.
Example 1:
1 |
|
1 |
|
Explanation
- Using the sliding window technique. We iterate the
windowEnd
first, in each iteration, we addarr[windowEnd]
to thewindowSum
. Start fromwindowEnd >= k-1
, we updated the maximum result bymax(res, windowSum)
, then subtractarr[windowStart]
from thewindowSum
and movewndowStart
1 step forward.
Solution
1 |
|
Smallest Subarray with a given sum
Given an array of positive numbers and a positive number ‘S’, find the length of the smallest contiguous subarray whose sum is greater than or equal to ‘S’. Return 0, if no such subarray exists.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Explanation
- Using the sliding window technique, in each iteration, we add the current number to the
windowSum
. While thewindowSum
is greater than or equal toS
, we update the result, then subtractarr[windowStart]
and move thewindowStart
1 step forward.
Solution
1 |
|
Longest Substring with K Distinct Characters
Given a string, find the length of the longest substring in it with no more than K distinct characters.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Explanation
- First, we need to create a character frequency character hashmap. Looping the input string character, we first update the character frequency hashmap. Then we check the size of the hashmap. While the hashmap has size more than
K
, we subtract 1 from the characterstr[windowStart]
’s frequency’ in the hashmap, if updating its frequency, its frequency becomes 0, then we remove this character from the hashmap. Outside the while loop, we update the resultmax(res, windowEnd - windowStart + 1)
.
Solution
1 |
|
LeetCode 904. Fruit Into Baskets
In a row of trees, the i
-th tree produces fruit with type tree[i]
.
You start at any tree of your choice, then repeatedly perform the following steps:
- Add one piece of fruit from this tree to your baskets. If you cannot, stop.
- Move to the next tree to the right of the current tree. If there is no tree to the right, stop.
Note that you do not have any choice after the initial choice of starting tree: you must perform step 1, then step 2, then back to step 1, then step 2, and so on until you stop.
You have two baskets, and each basket can carry any quantity of fruit, but you want each basket to only carry one type of fruit each.
What is the total amount of fruit you can collect with this procedure?
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Example 4:
1 |
|
Note:
1 |
|
Explanation
- We can use sliding window technique to solve this problem. First, since we can only have 2 fruit types, so we need to create a hashmap, the key is fruit type, the value is its frequency. While the hashmap has key size more than 2, then we need to subtract
tree[windowStart]
’s frequency and movewindowStart
1 step forward. After the while loop, we can count how many fruit we pick bywindowEnd - windowStart + 1
.
Solution
1 |
|
LeetCode 3. Longest Substring Without Repeating Characters
Given a string, find the length of the longest substring without repeating characters.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Explanation
-
We can also solve this problem using sliding window technique. Think of we will maintain a window that contains all unique characters. First initialize
windowStart
andwindowEnd
to 0. Also, initialize a hashset to record the window’s unique characters. -
Loop the
windowEnd
from index 0 to the last index of the input string. While the set contains the current iterated character, we remove the window’s left characterstr[windowStart]
and movewindowStart
1 step forward, repeat this while loop until the set doesn’t contains the incoming iterated character. Next, we add the iterated character into the set, then calculate the result bemax(res, windowEnd - windowStart + 1)
.
Solution
1 |
|
LeetCode 424. Longest Repeating Character Replacement
Given a string s
that consists of only uppercase English letters, you can perform at most k
operations on that string.
In one operation, you can choose any character of the string and change it to any other uppercase English character.
Find the length of the longest sub-string containing all repeating letters you can get after performing the above operations.
Note: Both the string’s length and k will not exceed 10^4.
Example 1:
1 |
|
Example 2:
1 |
|
Explanation
-
We can use Sliding Window technique to solve this problem. First think of if there is no restriction of
k
, and we need to find the minimum number of replacement to form a string that is made of only 1 character. To solve this, we use the length of the string subtract the maximum frequency of a character. Now, if we havek
, then we are looking for substring’s length subtract the maximum frequency of characters in this substring, and the difference is less than or equals tok
. We need to return the maximum length of this substring. The substring is like a window. -
Initialize
windowStart = 0
. LoopwindowEnd
from the beginning character to the last character, the window’s length iswindowEnd - windowStart + 1
. In each iteration, we increase the frequency of the iterated character. Then, we update themaxCnt
which is the maximum frequency. Because of the limitation ofk
, while the window length subtract the maximum frequencymaxCnt
is greater thank
, we need to increasewindowStart
by 1 so that this iteration’s window length is equals to the last iteration’s window length, also we update the frequency of the characterarr[windowStart]
by subtract 1. We are not changing themaxCnt
because we want the window length be as large as possible, so ifmaxCnt
is greater, then the number of characters we are going to change will be smaller, in other words, the window length will be larger. Outside the while loop, we update the maximum of the window lengthres = max(res, windowEnd-windowStart+1)
. -
For example, if the input string is
zzzabc
andk = 1
. When we iterate to index 3, themaxCnt = 3
, the window lengthwindowEnd - windowStart + 1 = 4
,windowEnd - windowStart + 1 - maxCnt = 4 - 3 = 1
which is not greater thank
, so we skip the while loop, and update the result bewindowEnd - windowStart + 1 = 4
. When we iterate to index 4, sincewindowEnd - windowStart + 1 = 5
, and5 - 3 = 2 > k
, we increasewindowStart
, so this time the window length is same as the last iteration which is 4. So we are keeping the maximum window length bemaxCnt + i
wherei <= k
.
Solution
1 |
|
LeetCode 1004. Max Consecutive Ones III
Given an array A of 0s and 1s, we may change up to K values from 0 to 1.
Return the length of the longest (contiguous) subarray that contains only 1s.
Example 1:
1 |
|
Example 2:
1 |
|
Note:
1 |
|
Explanation
- We can use sliding window technique to solve this problem. Think of the window is the valid subarray that contains 1s and number of 0s less than or equal to K. First, we should create a variable
cnt0
to count how many 0s. LoopwindowEnd
to the end of array, for each iteration, we updatecnt0
first. Whilecnt0 > K
, then we try to slide thewindowStart
forward. First, ifA[windowStart]
is 0, we decreasecnt0
. Then we movewindowStart
1 step forward. Repeat this while loop untilcnt0 <= K
. Outside the while loop, we update the result bemax(res, windowEnd - windowStart + 1)
.
Solution
1 |
|
Two Pointers
Pair with Target Sum
Given an array and a integer sum
. Print all pairs that satisify each pair sum to sum
.
-
Does array contains only positive or negative numbers?
Array contains only positive number.
-
What if the same pair repeats twice, should we print it every time?
Yes, as long as the number have not been used.
-
Is reverse of pair is acceptable e.g. can we print both (4,1) and (1,4) if given sum is 5.
No.
-
Does (3, 3) is a valid pair forgiven sum of 6?
Yes, as long as there are two 3s.
-
How big the array is?
Bigger than computer ram.
Explanation
- Since the array is bigger than computer ram, we cannot use HashMap to store the array. To solve this, we can use two pointer technique. First, we sort the array. Initialize one pointer at the first index, another pointer at the last index. If the two values both pointers point at sum to
sum
, then we print the these two numbers, then we increase the left pointer and decrease the right pointer. Else if the two values both pointers point at less thansum
, then we increase left pointer. Else the values both pointers point at greater thansum
, then we decrease the right pointer.
Solution
1 |
|
LeetCode 26. Remove Duplicates from Sorted Array
Given a sorted array nums, remove the duplicates in-place such that each element appear only once and return the new length.
Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
Example 1:
1 |
|
Example 2:
1 |
|
Clarification:
Confused why the returned value is an integer but your answer is an array?
Note that the input array is passed in by reference, which means modification to the input array will be known to the caller as well.
Internally you can think of this:
1 |
|
Explanation
-
We can create two pointers, the current pointer is pointing at the end of the non-duplicated result array, the fast pointer is iterating every element of the array.
-
Initialize the current pointer at index 0, the fast pointer at index 1. If the fast pointer and current pointer have the same value, then faster pointer move forward. Else, the current pointer’s index + 1 is set to the fast pointer’s value. Iterating until the fast pointer hits the end of the array.
-
At the end, the length will be current pointer index + 1.
Solution
1 |
|
LeetCode 977. Squares of a Sorted Array
Given an array of integers A sorted in non-decreasing order, return an array of the squares of each number, also in sorted non-decreasing order.
Example 1:
1 |
|
Example 2:
1 |
|
Note:
1 |
|
Explanation
-
First, we need to use a for loop to find out the minimum absolue value’s index, and we named this index
minAbsoluteIndex
. Then we make a left pointer points tominAbsoluteIndex
, and a right pointer points tominAbsoluteIndex + 1
. But if theminAbsoluteIndex
is the last index, then we make left pointer beminAbsoluteIndex - 1
, right pointer beminAbsoluteIndex
. -
While the
leftPtr >= 0
andrightPtr < n
, we compare the absolue value of both pointed value in the array. If the left pointer’s absolute value is smaller, then we calculate its square and put into the result array and moveleftPtr
to the 1 step left. Else we put the right poitner’s value’s square into the result array and moverightPtr
1 step right. Repeat this while loop until one of the pointer is out of bound. Then we put the non out of bound pointer’s value’s square into result. -
We can also first find out if the first number of the input array is equal or greater than 0, then we simply one loop and each iteration we put the square of the iterated number into the result array. If the last number of the input array is negative, then we simply loop from right to left and each iteration, we put the iterated number’s square into the array. Else, the
minAbsoluteIndex
is the index of the first non-negative number.
Solution
1 |
|
LeetCode 15. 3Sum
Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
The solution set must not contain duplicate triplets.
Example:
1 |
|
Explanation
-
Sort the array.
-
If the first element is greater than 0 or the last element is less than 0, we know that we can’t form a 0.
-
Loop through the array start from the first element, we fix the first element, then use two pointers technique to find two elements that sum to targetVal-fixVal until break out the left < right condition. While looping, we need to ignore the same fix number and left and right values.
Solution
1 |
|
LeetCode 16. 3Sum Closest
Given an array nums of n integers and an integer target, find three integers in nums such that the sum is closest to target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
Example:
1 |
|
Explanation
- Similar to 15. 3Sum, first, sort the array. We need to fix one number, then use two pointers technique to find the sum of 3 elements, and compare the sum with the target to get the
newDiff
. Since we are looking for the closest sum, we need to define adiff
variable as the minimum diff. In other words, ifnewDiff
is less thandiff
, then updatediff
tonewDiff
. Note, we should use absolute value to findnewDiff
.
Solution
1 |
|
LeetCode 259. 3Sum Smaller
Given an array of n integers nums and a target, find the number of index triplets i, j, k
with 0 <= i < j < k < n
that satisfy the condition nums[i] + nums[j] + nums[k] < target
.
Example:
1 |
|
Follow up: Could you solve it in $O(n^2)$ runtime?
Explanation
-
Sort the array, then apply the two pointers technique.
-
Loop
i
from 0 toarr.length - 2
. Inside the loop, initializeleft = i + 1
andright = arr.length - 1
. Whileleft < right
, we can calculate the triplet sum benums[i] + nums[left] + nums[right]
. If the sum is greater or equal than thetarget
, we move the right poitner 1 step left. Else, we can calculate the number of triplet sum less than target usingright - left
. Then we move the left pointer 1 step forward.
Solution
1 |
|
LeetCode 713. Subarray Product Less Than K
Your are given an array of positive integers nums.
Count and print the number of (contiguous) subarrays where the product of all the elements in the subarray is less than k
.
Example 1:
1 |
|
Note:
-
0 < nums.length <= 50000
. -
0 < nums[i] < 1000
. -
0 <= k < 10^6
.
Explanation
-
Since this is a subarray problem, we can think of using sliding window technique or two pointers (slow, fast pointers) technique. In this problem, we will use two pointers technique.
-
If
k
less than or equal to 1, we will return 0 since all elements in the input array are positive. We initializeslow = 0
andfast = 0
. Loopfast
from 0 to the last index of the input array, we can think offast
be the last element of the subarray,slow
be the first element of the subarray. In each iteration, we calculate the production byprod *= nums[fast]
. Ifprod < k
, we can count the number of subarray befast - slow + 1
. Else, whileprod >= k
, we need to updateprod /= nums[slow]
and moveslow
1 step forward.
Solution
1 |
|
LeetCode 75. 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
-
This problem is also called Dutch national flag sorting problem. We can solve this problem using two pointer technique. First, initialize a
left
pointer points at the next index of the placeholder of 0,right
points at the previous index of the placeholder of 2. In other words,left = 0
andright = arr.length - 1
. -
Loop though the
mid
pointer as long as it’s not greater thanright
. In other words, whilemid <= right
. -
If the current element
arr[mid]
is 2, then we swap current element witharr[right]
and decreaseright
. -
Else if the current element
arr[mid]
is 0, then we swap current element witharr[left]
and increaseleft
andmid
. -
Else if the current element is 1, then we increase
mid
.
Solution
1 |
|
Fast & Slow pointers
LeetCode 141. Linked List Cycle
Given a linked list, determine if it has a cycle in it.
To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Follow up:
Can you solve it using $O(1)$ (i.e. constant) memory?
Explanation
-
Both fast and slow pointers points to the head.
-
When fast pointer moves two steps, slow pointer move one step.
-
If fast pointer hits null, then no cycle; else if slow pointer and fast pointer point to the same node, then there’s cycle.
Solution
1 |
|
LeetCode 142. Linked List Cycle II
Given a linked list, return the node where the cycle begins. If there is no cycle, return null
.
To represent a cycle in the given linked list, we use an integer pos
which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.
Note: Do not modify the linked list.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Follow-up:
Can you solve it without using extra space?
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 check if slow pointer and fast pointer point to the same node. If they are not point to the same node, that means fast pointer hit to the end, so we return NULL.
-
Now, fast pointer moves back to the head. slow 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 |
|
LeetCode 202. Happy Number
Write an algorithm to determine if a number is “happy”.
A happy number is a number defined by the following process: Starting with any positive integer, replace the number by the sum of the squares of its digits, and repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1. Those numbers for which this process ends in 1 are happy numbers.
Example:
1 |
|
Explanation
- We can also use two pointer technique to solve this problem. Similar to 141. Linked List Cycle. The difference is in this problem, the cycle must exist. Slow will be the sum of the digit square, in other words,
slow=cal(slow)
, fast will befast=cal(cal(fast))
. When slow is equals to fast, we break out the loop, and check if slow is equals to 1. If it’s 1, we return true; else return false.
Solution
1 |
|
LeetCode 876. Middle of the Linked List
Given a non-empty, singly linked list with head node head, return a middle node of linked list.
If there are two middle nodes, return the second middle node.
Example 1:
1 |
|
Example 2:
1 |
|
Note:
- The number of nodes in the given list will be between 1 and 100.
Explanation
- We can use
slow
andfast
pointer to solve this problem. First initalizeslow
andfast
pointers both point at the inputhead
node. Whilefast
pointer andfast.next
are not NULL, thenslow
pointer move 1 step forward,fast
pointer move 2 step forward. Outside of the while loop, that meansfast
pointer either hit the last node or thelast.next
node. At the same time,slow
pointer is pointing the second middle node.
Solution
1 |
|
Merge Intervals
Merge Intervals
Given a list of intervals, merge all the overlapping intervals to produce a list that has only mutually exclusive intervals.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Explanation
-
Sort the interval by their start time. Put the early start time in the beginning.
-
If
a
overlapsb
(i.e. b.start <= a.end), we need to merge them into a new intervalc
such that:1
2c.start = a.start c.end = max(a.end, b.end)
-
Initialize the first interval be the interval that we want to compare with, let’s named it
myInterval
. Start looping from the second interval to compare withmyInterval
. If the iterated interval cannot merge withmyInterval
, then we addmyInterval
into the result list, else we merge the iterated interval withmyInterval
and named the merge intervalmyInterval
.
Solution
1 |
|
Insert Interval
Given a list of non-overlapping intervals sorted by their start time, insert a given interval at the correct position and merge all necessary intervals to produce a list that has only mutually exclusive intervals.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Explanation
-
Adding all intervals that’s ending before the new interval’s start to the result list.
-
When the iterated interval’s ending is greater than the new interval’s start, we need to merge the iterated interval with the new interval and we think of it as the new interval. Repeat this step while the iterated interval’s start is less than or equal to the new interval’s end.
-
Add the rest of the iterated interval into the result list.
Solution
1 |
|
Intervals Intersection
Given two lists of intervals, find the intersection of these two lists. Each list consists of disjoint intervals sorted on their start time.
Example 1:
1 |
|
Example 2:
1 |
|
Explanation
-
There are four scenarios when the two intervals overlap (2-5). Whenever the two intervals overlap, one of the interval’s start time lies within the other interval.
-
The overlapping interval will be equal to:
1
2start = max(a.start, b.start) end = min(a.end, b.end)
-
After checking if two intervals intersect, we move the index of the interval that has ending pointer smaller forward 1 step. When the index is greater than the corresponding size of the array, we finish and return the result.
Solution
1 |
|
Conflicting Appointments
Write a program to find conflicts in a list of appointments. Let’s say that you are writing a calendar program and you need a method to find conflicting meetings on the schedule.
You have a class
1 |
|
The method signature should look like
1 |
|
So say that your meetings look something like the following
1 |
|
The first meeting doesn’t conflict with any other meetings. The second and third meeting overlap so in the result set hasConflict
will be false
for the first appointment and true
for the second and third.
Source: Conflicting Appointments
Explanation
-
Sort the appointments by their start time.
-
Initialize the first appointment be the latest appointment to compare with the iterated appointment. Loop from the second appointment to the end. If the iterated appointment’s start is less than the latest appointment’s end, then we set both of them be conflict. Also, in each iteration, we update the latest appointment be the appointment that has the latest ending time.
Solution
1 |
|
Cyclic Sort
Cyclic Sort
Given an array of n unique integers where the range is 1 ≤ a[i] ≤ n (n = size of array). Sort the array using Cyclic Sort.
Explanation
-
When array numbers in a given range, we can try solve it using Cyclic Sort.
-
Initiaize a variable
idx
that is the index to check if the current index’s element is in the right position. The correct position for numbernums[idx]
isnums[idx]-1
. We check by comparingnums[idx]
andnums[ nums[idx]-1 ]
. If these two numbers are different, we swap them to putnums[idx]
in the correct position; else we increaseidx
to check the next element; repeat this while loop untilidx
exceed the length of the array.
Solution
1 |
|
LeetCode 268. Missing Number
Given an array containing n distinct numbers taken from 0, 1, 2, ..., n
, find the one that is missing from the array.
Example 1:
1 |
|
Example 2:
1 |
|
Note:
Your algorithm should run in linear runtime complexity. Could you implement it using only constant extra space complexity?
Explanation
-
First, we can use Cyclic Sort to put the elements in its correct position, note in this problem, if the current element is equal to
n
, then we can just ignore it and increase the indexidx
since its correct position will be outside of the array. -
After we sort the array, we can loop from the beginning and compare the element with its index. If they are not equal, then we return the index which is the missing number.
-
If all elements are equal to its index, the missing number will be
n
which is the length of the array.
Solution
1 |
|
LeetCode 448. Find All Numbers Disappeared in an Array
Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.
Find all the elements of [1, n] inclusive that do not appear in this array.
Could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space.
Example:
1 |
|
Explanation
- We can use cyclic sort to solve this problem. If the input array is
[4,3,2,7,8,2,3,1]
, after cyclic sort, it becomes[1, 2, 3, 4, 3, 2, 7, 8]
. Then, we loop through this array and find the missing number which are 5 and 6.
Solution
1 |
|
LeetCode 287. 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(n^2).
- 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, We can use cyclic sort to solve the array. In this problem, after sorting, the last element will the duplicated number since there are n+1 numbers and all numbers are between 1 to n.
Solution 1
1 |
|
Explanation 2
-
Without modify the array, 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 beginning of the cycle, which is the duplicated number.
Solution 2
1 |
|
LeetCode 442. Find All Duplicates in an Array
Given an array of integers, 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.
Find all the elements that appear twice in this array.
Could you do it without extra space and in $O(n)$ runtime?
Example:
1 |
|
Explanation
- We can use cyclic sort to sort this array. After sorting, loop this array fom index 0 to the end, if the element’s value is not equal to
idx + 1
, that means the elementnums[idx]
is duplicated.
Solution
1 |
|
In-place Reversal of a LinkedList
LeetCode 206. Reverse Linked List
Reverse a singly linked list.
Example:
1 |
|
Follow up:
1 |
|
Explanation 1
-
Make an empty ListNode called
pre
and think of it as the head of the already reversed ListNode, make acur
pointer pointing tohead
. -
While
cur
is not empty, first storecur.next
as a temp linked list callednex
, thencur.next = pre
which means appendcur
to the head of the reversed ListNode. Then updatepre = cur
which means now thepre
is the head of the reversed ListNode. Then updatecur = nex
which meanscur
is moving forward 1 step. Repeat untilcur
is NULL, -
Return
pre
.
Solution 1
1 |
|
Explanation 2
- We can also use recursive method to solve this problem. The
newHead
will be the last node of the linked list, then thehead
will be the second last node of the linked list. We makehead.next.next = head
which means now the last node (newHead
)’s next pointing to the second last node and the second last node now is the last node. Then wehead.next = null
to cut off the new last node. Then we returnnewHead
.
Solution 2
1 |
|
LeetCode 92. Reverse Linked List II
Reverse a linked list from position m to n. Do it in one-pass.
Note: 1 ≤ m ≤ n ≤ length of list.
Example:
1 |
|
Explanation
-
First, we need to know mNode and nNode’s correct position.
-
We need to create one more node that is pointing at the previous of
mNode
calledpreM
. For example, linked list is1->2->3->4->5
,m = 2
n = 4
, sopreM
points at element 1,mNode
points at element 2,nNode
points at element 4. Then, we movemNode
to the next ofnNode
, then updatemNode
to its next element, and repeat this process untilmNode
andnNode
point at the same element. We can illustrate this process below:1
2
31->2->3->4->5 1->3->4->2->5 1->4->3->2->5
Solution
1 |
|
LeetCode 25. Reverse Nodes in k-Group
Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.
k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.
Example:
Given this linked list: 1->2->3->4->5
For k = 2, you should return: 2->1->4->3->5
For k = 3, you should return: 3->2->1->4->5
Note:
- Only constant extra memory is allowed.
- You may not alter the values in the list’s nodes, only nodes itself may be changed.
Explanation
-
The last solution use a stack that costs $O(n)$ space. This time, we don’t need extra space. Like the last solution, we need to create a
dummy
node in front of the input node’s head, and need apre
pointer that points to dummy node,last
pointer that points to the $k+1$’s node.1
2
3dummy -> 1 -> 2 -> 3 -> 4 -> 5 | | pre last
-
Now, we need to reverse the nodes between pre (exclusive) and last (exclusive), we can think of this as a sublist.
-
We should starts from the second node in this sublist, which is node
2
. We have acur
pointing to node2
and make it become the first node. Then,cur
pointing to node3
and make node3
pointing to the beginning of the node, and we are done reversing. Also, before we start reverse, we should have atail
node that points to1
because it will eventually be the tail of this sublist. Finally, whencur
equals tolast
, we are done. Before we checking the next $k$ nodes, we need to set thepre
totail
and start moving thelast
$k$ steps next.1
2
3
4
5
6
7
8
9
10
11dummy -> 1 -> 2 -> 3 -> 4 -> 5 | | | | pre tail cur last dummy -> 2 -> 1 -> 3 -> 4 -> 5 | | | | pre tail cur last dummy -> 3 -> 2 -> 1 -> 4 -> 5 | | | pre tail (cur)last
-
For example, in the above second step, we want to move 2 in front of 1, we can set the
nex
pointer pointing to 3, then do the following:1
2
3
4
5
6
7
8
9
10
11
12dummy -> 1 -> 2 -> 3 -> 4 -> 5 | | | | | pre tail cur nex last cur.next = pre.next 2 -> 1 -> 2 -> 3 -> 4 -> 5 pre.next = cur dummy -> 2 -> 1 -> 2 -> 3 -> 4 -> 5 tail.next = nex dummy -> 2 -> 1 -> 3 -> 4 -> 5
Solution
1 |
|
Tree Breadth First Search
LeetCode 102. Binary Tree Level Order Traversal
Given a binary tree, return the level order traversal of its nodes’ values. (ie, from left to right, level by level).
For example:
Given binary tree [3,9,20,null,null,15,7]
,
1 |
|
return its level order traversal as:
1 |
|
Explanation
-
We can use the BFS method. We store each layer’s values into a list, then add this list into the result. The problem now of the BFS is we don’t know the number of elements in each layer. To solve this, we need to record the size of each layer before we pop and push the left child and right child elements into the list, and we pop the number of elements base on this size.
-
From the above example, we first push 3 into the queue, record the size is 1, then we pop 1 element adding to a list, then push its left and right child 9 and 20, now the queue has 2 elements, so we update the size to 2. Then we should pop 2 elements this time, we pop 9, pop 20, adding to a list, and push its left and right child 15 and 7. Now the queue has 2 elements, so we update its size to 2, and we only pop size=2 elements and adding to the list, etc, until the queue is empty.
Solution
1 |
|
LeetCode 107. Binary Tree Level Order Traversal II
Given a binary tree, return the bottom-up level order traversal of its nodes’ values. (ie, from left to right, level by level from leaf to root).
For example:
Given binary tree [3,9,20,null,null,15,7]
,
1 |
|
return its bottom-up level order traversal as:
1 |
|
Explanation
- Same as Binary Tree Level Order Traversal, but this time when we add the sub-list to the result list, we add the sublist in front of the result list.
Solution
1 |
|
LeetCode 103. Binary Tree Zigzag Level Order Traversal
Given a binary tree, return the zigzag level order traversal of its nodes’ values. (ie, from left to right, then right to left for the next level and alternate between).
For example:
Given binary tree [3,9,20,null,null,15,7]
,
1 |
|
return its zigzag level order traversal as:
1 |
|
Explanation
-
Similar to 102. Binary Tree Level Order Traversal, but this time we need to add value from left to right, in the next level, we add values from right to left. Then next level, add values from left to right, next level from right to left.
-
When the current level is from left to right, we can normally pop value from the beginning and add its child to the end (left child first). When the current level is from right to left, we pop values from the end and add its child (right child first) to the beginning.
Solution
1 |
|
LeetCode 637. Average of Levels in Binary Tree
Given a non-empty binary tree, return the average value of the nodes on each level in the form of an array.
Example 1:
1 |
|
Note:
- The range of node’s value is in the range of 32-bit signed integer.
Explanation
- We can solve this problem using level-order traversal, in other words, BFS. For each level, we use a variable
sum
to sum all the numbers on the same level. After we finish iterating all numbers on the same level, we then calculate the average bysum
divide the numbers of that level.
Solution
1 |
|
111. 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:
Given binary tree [3,9,20,null,null,15,7]
,
1 |
|
return its minimum depth = 2.
Explanation
- If the leaf node is next to the root node, then we can stop there. In other words, if the
popNode
doesn’t have left and right nodes, we can return this level’s depth. We can use level-order traversal to solve this problem.
Solution
1 |
|
Level Order Successor
Given a binary tree and a node in the binary tree, find Levelorder successor of the given node. That is, the node that appears after the given node in the level order traversal of the tree.
Note: The task is not just to print the data of the node, you have to return the complete node from the tree.
Examples:
1 |
|
Source: Level Order Successor of a node in Binary Tree
Explanation
-
First we check if the root node is the given node. If true, then we return its left node, if there’s no left node, we return its right node; if there’s also no right node, we return NULL.
-
If the root node is not the given node, we do level-order traversal. When the
pollNode
is the given node, we break out the while loop and return the first node of the queue.
Solution
1 |
|
LeetCode 117. Populating Next Right Pointers in Each Node II
Given a binary tree
1 |
|
Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL
.
Initially, all next pointers are set to NULL
.
Follow up:
-
You may only use constant extra space.
-
Recursive approach is fine, you may assume implicit stack space does not count as extra space for this problem.
Example 1:
1 |
|
Constraints:
-
The number of nodes in the given tree is less than 6000.
-
-100 <= node.val <= 100
Explanation 1
-
We can use level-order traversal to solve this problem. Initially, we push the root node to the queue, then we also push the
NULL
node to the queue to mark it as the end of the current level. While the queue is not empty, we loopqueue.size() - 1
times since the queue size will be 2 at the beginning, but 1 of the node is just the NULL node. -
In each iteration, we poll a node from the queue. Then assign
pollNode.next
to bequeue.peek()
since the first node of inside the queue will always be the next node of thepollNode
. After looping all nodes from the current level, in other words, after loopingqueue.size() - 1
times, we poll the NULL node out from the queue and push the NULL node to the end of the queue.
Solution 1
1 |
|
Explanation 2
-
This solution uses O(1) space and it is iterating level by level.
-
First, we create a dummy node that is used to pointing before the first element of each level. We create a pointer
cur = dummy
that is used to iterate the current level’s element. -
Then, if the left subnode exists,
cur.next
connects it, then iteratecur = cur.next
. If the right subnode exists,cur.next
connects it, then iteratecur = cur.next
. Now, the root’s left and right subnodes are connected. -
Then, we move
curRoot
to the right. After we move, ifcurRoot
is not exist, then it means we finish connecting to current root node’s sub node. We then resetcurRoot
to dummy’s next node. -
We cut off
dummy.next = null
, andcur
reset pointing todummy
. We setdummy
’s next to null because we want thecur
pointer’s next to NULL so that we can usecur.next
to point to the first element in the next level.
Solution 2
1 |
|
Tree Depth First Search
LeetCode 112. Path Sum
Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum.
Note: A leaf is a node with no children.
Example:
Given the below binary tree and sum = 22
,
1 |
|
return true, as there exist a root-to-leaf path 5->4->11->2
which sum is 22.
Explanation
- We can use recursion to solve this problem. In the recrsive method, we pass the root and sum as parameters. If the root is null, then we return false. If the root has not left and no right child and its value is equals to the sum, then we return true. Then, we can recursively call this method for the left subtree and right subtree.
Solution
1 |
|
LeetCode 113. Path Sum II
Given a binary tree and a sum, find all root-to-leaf paths where each path’s sum equals the given sum.
Note: A leaf is a node with no children.
Example:
Given the below binary tree and sum = 22
,
1 |
|
Return:
1 |
|
Explanation
-
We can use recusive backtracking to solve this, so we create a helper function and pass a temp list and result list as the parameters besides the root node and sum.
-
Inside the helper function, the base case is if the root node is NULL, we just return nothing. Then, we add the current root node’s value to the temp list.
-
Then we check if the current node’s value equal to the sum and also there’s no left and right node, then we add temp list to the result list.
-
Next, we recrusively call the helper function with the left and right child nodes with the updated
sum=sum-root.val
. Then, we should remove the last element of the temp list in order to backtract to the parent node.
Solution
1 |
|
LeetCode 129. 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 recursive DFS to solve this problem. First, we create a
sum
variable to hold the path sum, and since we are using recursion, in order to make sure thesum
is the latest updated sum, we allocate a memory space, so we use an array that has size 1 to save the sum. -
In the helper function, we pass the
root
,sum
, and also the current sum, which is 0 initially. Inside the helper function, the base case is if theroot
is NULL, we just return nothing. Next, we update thecurSum = curSum * 10 + root.val
. Now, we check if the current TreeNode is the leaf, if it’s a leaf node, then we addcurSum
tosum
. Next, we recursively check the left and right child node. After checking the left and right child node, we need to backtrack thecurSum /= 10
to remove the the current node’s value fromcurSum
.
Solution
1 |
|
Path With Given Sequence
Given a binary tree and an array, the task is to find if the given array sequence is present as a root to leaf path in given tree.
Examples :
1 |
|
Source: Check if there is a root to leaf path with given sequence
Explanation
-
We can use pre-order traversal to traverse the tree. We will pass the root node, the array, and also the current index which initialize to 0 into the helper function.
-
Inside the helper function, we first check if the current root node is valid. Then the base case is if the current root node is not equal to the current element of the array, we return false; or the current index is greater than the size of the array, we also return false.
-
If the current node is leaf node and its value is equal to the current element and also the last element of the array, we return true.
-
Else the root node’s value is equal to the current element of the array, but it’s not the leaf node, we will recursively calling the helper function with the left child and index plus 1, and calling the helper function with the right child and index plus 1.
Solution
1 |
|
LeetCode 437. Path Sum III
You are given a binary tree in which each node contains an integer value.
Find the number of paths that sum to a given value.
The path does not need to start or end at the root or a leaf, but it must go downwards (traveling only from parent nodes to child nodes).
The tree has no more than 1,000 nodes and the values are in the range -1,000,000 to 1,000,000.
Example:
1 |
|
Explanation
-
We can use DFS to solve this problem. In the helper function, we will pass the
root
,sum
, and also the result variableres[0] = {0}
as parameters. -
Inside the helper function, the base case is if the root is NULL, we just return nothing. If the root’s value is equal to the
sum
, then we increaseres
. -
Next, we will recursively call the helper function with left, right child node with updated
sum = sum - root.val
. -
Under the main function, we should also consider that the left child as root, and right child as root, so we return
res
plus the result ofpathSum(root.left, sum)
andpathSum(root.right, sum)
.
Solution
1 |
|
Two Heaps
LeetCode 295. Find Median from Data Stream
Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value.
For example,
[2,3,4]
, the median is 3
[2,3]
, the median is (2 + 3) / 2 = 2.5
Design a data structure that supports the following two operations:
-
void addNum(int num) - Add a integer number from the data stream to the data structure.
-
double findMedian() - Return the median of all elements so far.
Example:
1 |
|
Follow up:
-
If all integer numbers from the stream are between 0 and 100, how would you optimize it?
-
If 99% of all integer numbers from the stream are between 0 and 100, how would you optimize it?
Explanation
-
Initialize a
minHeap
andmaxHeap
to each store half of the numbers. If the number we are adding are 6, 8, 10, 7, 9, 11, 13, 12. Then,maxHeap
stores the number are10, 9, 8, 7, 6
;minHeap
stores the number will be11, 12, 13, 14, 15
. To find the median, if these two heaps has the same length, we can just sum both peek heap’s number and divide by 2, in other words,(10+11)/2.0
. When adding number, we store to theminHeap
first, if these two heap’s size is different, we can just peek theminHeap
’s number as the result. -
When adding number, we store it to
minHeap
first, then we pop outminHeap
’s number and store it tomaxHeap
. IfmaxHeap
’s size is greater thanminHeap
, we will popmaxHeap
’s element back tominHeap
. This ensures that elements in theminHeap
are greater thanmaxHeap
. SomaxHeap
stores the number are10, 9, 8, 7, 6
;minHeap
stores the number will be11, 12, 13, 14, 15
.
Solution
1 |
|
LeetCode 480. Sliding Window Median
Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value.
Examples:
[2,3,4]
, the median is 3
[2,3]
, the median is (2 + 3) / 2 = 2.5
Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position. Your job is to output the median array for each window in the original array.
For example,
Given nums = [1,3,-1,-3,5,3,6,7]
, and k = 3.
1 |
|
Therefore, return the median sliding window as [1,-1,-1,3,5,6]
.
Note:
You may assume k
is always valid, ie: k
is always smaller than input array’s size for non-empty array.
Explanation
-
To find a median number, we can use two heaps to split the window elements. One is
maxHeap
to store the numbers that are less than the median, another one isminHeap
to store the numbers that are equal or only one more than the size ofmaxHeap
. -
For example, if the input
nums = [5, 6, 7, 8, 9]
, and window lengthk = 3
.1
2
3
4
5maxHeap: []; minHeap: [5] maxHeap: [5]; minHeap: [6] maxHeap: [5]; minHeap: [6, 7] maxHeap: [6, 5]; minHeap: [7, 8] maxHeap: [6, 5]; minHeap: [7, 8, 9]
-
We create a
getMedian
function. In this function, if both heaps are empty, then we return 0 as the median result. Else if their heap size is different, in other words, theminHeap
has size one more than themaxHeap
, we will peek theminHeap
as the median element. Else if both heap has the same size, then we peek both heaps and divide the sum of both peek element by 2 as the median. -
When we iterate the input element, how do we know which heap we are going to add into. We can compare the current element with the result of
getMedian
. If the current element is greater than the median value, we add intominHeap
, elsemaxHeap
. Then we balance both heaps. -
When the window length is equals to
k
we need to remove the most left side element of the window from eitherminHeap
ormaxHeap
. So if this element is less than the median result of thegetMedian
function, we remove from themaxHeap
, else theminHeap
. Then, we need to balance both heaps. -
Note, when we create the
maxHeap
, the comparator function should be(a, b) -> b.compareTo(a)
, not(a, b) -> b - a
because the input elements can be all negative.
Solution
1 |
|
LeetCode 502. IPO
Suppose LeetCode will start its IPO soon. In order to sell a good price of its shares to Venture Capital, LeetCode would like to work on some projects to increase its capital before the IPO. Since it has limited resources, it can only finish at most k distinct projects before the IPO. Help LeetCode design the best way to maximize its total capital after finishing at most k distinct projects.
You are given several projects. For each project i, it has a pure profit Pi and a minimum capital of Ci is needed to start the corresponding project. Initially, you have W capital. When you finish a project, you will obtain its pure profit and the profit will be added to your total capital.
To sum up, pick a list of at most k distinct projects from given projects to maximize your final capital, and output your final maximized capital.
Example 1:
1 |
|
Note:
-
You may assume all numbers in the input are non-negative integers.
-
The length of Profits array and Capital array will not exceed 50,000.
-
The answer is guaranteed to fit in a 32-bit signed integer.
Explanation
-
First, we create two heaps. One heap is
maxProfit<Integer>
which is for storing all profits that we are able to purchase, in other words, their corresponding capital is less than or equal toW
; and it sorts by max profit in front. Another heap iscapitalProfit<[capital, profit]>
, which is for storing pair of capital and profit that we are not able to purchase, in other words, their corresponding capital is greater thanW
; and it sorts by small capital in front. -
First looping over all capital, and update the two heaps we created. Then we loop
k
times, in each iteration, we updateW
by poll the first profit frommaxProfit
. Then, whileW
is greater than or equal to the first pair’s capital ofcapitalProfit
, we poll this pair out, and push its profit intomaxProfit
, untilW
is smaller than the first pair ofcapitalProfit
. Repeat this for loop.
Solution
1 |
|
Subsets
Subsets
Given a set with distinct elements, find all of its distinct subsets.
Example 1:
1 |
|
Example 2:
1 |
|
Explanation
To generate all subsets of the given set, we can use the Breadth First Search (BFS) approach. We can start with an empty set, iterate through all numbers one-by-one, and add them to existing sets to create new subsets.
Let’s take the example-2 mentioned above to go through each step of our algorithm:
Given set: [1, 5, 3]
-
Start with an empty set: [[]]
-
Add the first number (1) to all the existing subsets to create new subsets: [[], [1]];
-
Add the second number (5) to all the existing subsets: [[], [1], [5], [1,5]];
-
Add the third number (3) to all the existing subsets: [[], [1], [5], [1,5], [3], [1,3], [5,3], [1,5,3]].
Here is the visual representation of the above steps:
Since the input set has distinct elements, the above steps will ensure that we will not have any duplicate subsets.
Solution
1 |
|
Source: Subsets
Subsets With Duplicates
Given a set of numbers that might contain duplicates, find all of its distinct subsets.
Example 1:
1 |
|
Example 2:
1 |
|
Explanation
This problem follows the Subsets pattern and we can follow a similar Breadth First Search (BFS) approach. The only additional thing we need to do is handle duplicates. Since the given set can have duplicate numbers, if we follow the same approach discussed in Subsets, we will end up with duplicate subsets, which is not acceptable. To handle this, we will do two extra things:
-
Sort all numbers of the given set. This will ensure that all duplicate numbers are next to each other.
-
Follow the same BFS approach but whenever we are about to process a duplicate (i.e., when the current and the previous numbers are same), instead of adding the current number (which is a duplicate) to all the existing subsets, only add it to the subsets which were created in the previous step.
Let’s take Example-2 mentioned above to go through each step of our algorithm:
1 |
|
-
Start with an empty set: [[]]
-
Add the first number (1) to all the existing subsets to create new subsets: [[], [1]];
-
Add the second number (3) to all the existing subsets: [[], [1], [3], [1,3]].
-
The next number (3) is a duplicate. If we add it to all existing subsets we will get:
1
[[], [1], [3], [1,3], [3], [1,3], [3,3], [1,3,3]]
1
2We got two duplicate subsets: [3], [1,3] Whereas we only needed the new subsets: [3,3], [1,3,3]
To handle this instead of adding (3) to all the existing subsets, we only add it to the new subsets which were created in the previous (3rd) step:
1
[[], [1], [3], [1,3], [3,3], [1,3,3]]
-
Finally, add the forth number (5) to all the existing subsets: [[], [1], [3], [1,3], [3,3], [1,3,3], [5], [1,5], [3,5], [1,3,5], [3,3,5], [1,3,3,5]]
Here is the visual representation of the above steps:
Solution
1 |
|
Time Complexity
Since, in each step, the number of subsets could double (if not duplicate) as we add each element to all the existing subsets, the time complexity of the above algorithm is $O(2^N)$, where N
is the total number of elements in the input set. This also means that, in the end, we will have a total of $O(2^N)$, subsets at the most.
Space Complexity
All the additional space used by our algorithm is for the output list. Since at most we will have a total of $O(2^N)$, subsets, the space complexity of our algorithm is also $O(2^N)$.
Source: Subsets With Duplicates
Permutations
Given a set of distinct numbers, find all of its permutations.
Permutation is defined as the re-arranging of the elements of the set. For example, {1, 2, 3} has the following six permutations:
-
{1, 2, 3}
-
{1, 3, 2}
-
{2, 1, 3}
-
{2, 3, 1}
-
{3, 1, 2}
-
{3, 2, 1}
If a set has n
distinct elements it will have $n!$ permutations.
Example 1:
1 |
|
Explanation
This problem follows the Subsets pattern and we can follow a similar Breadth First Search (BFS) approach. However, unlike Subsets, every permutation must contain all the numbers.
Let’s take the example-1 mentioned above to generate all the permutations. Following a BFS approach, we will consider one number at a time:
-
If the given set is empty then we have only an empty permutation set: []
-
Let’s add the first element (1), the permutations will be: [1]
-
Let’s add the second element (3), the permutations will be: [3,1], [1,3]
-
Let’s add the third element (5), the permutations will be: [5,3,1], [3,5,1], [3,1,5], [5,1,3], [1,5,3], [1,3,5]
Let’s analyze the permutations in the 3rd and 4th step. How can we generate permutations in the 4th step from the permutations of the 3rd step?
If we look closely, we will realize that when we add a new number (5), we take each permutation of the previous step and insert the new number in every position to generate the new permutations. For example, inserting ‘5’ in different positions of [3,1] will give us the following permutations:
-
Inserting ‘5’ before ‘3’: [5,3,1]
-
Inserting ‘5’ between ‘3’ and ‘1’: [3,5,1]
-
Inserting ‘5’ after ‘1’: [3,1,5]
Here is the visual representation of this algorithm:
Solution
1 |
|
Recursive Solution
1 |
|
LeetCode 784. Letter Case Permutation
Given a string S, we can transform every letter individually to be lowercase or uppercase to create another string. Return a list of all possible strings we could create.
1 |
|
Note:
- S will be a string with length between 1 and 12.
- S will consist only of letters or digits.
Explanation
-
We can use BFS is putting the input string to the queue first.
-
Loop
i
through each character of the input string. If the current character is a digit, then we continue. Else, we loopj
the current queue’s size, each time we poll the string out of the queue, then convert it to an array and update the indexi
character to lower case and append the updated string to the queue, similarlly, we also update the indexi
character to upper case and append the updated string to the queue. -
At the end, the queue contains all the permutations.
-
For example, if the input string is
abc
, then we have:
1 |
|
Solution
1 |
|
LeetCode 301. Remove Invalid Parentheses
Remove the minimum number of invalid parentheses in order to make the input string valid. Return all possible results.
Note: The input string may contain letters other than the parentheses (
and )
.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Explanation
- We can use BFS to solve this problem. First, add the input string to the queue. While the queue is not empty, we poll the string out, check if the poll string is valid. If the poll string is valid, then we add it to the result list and mark the variable
found
be true. Next, iffound
is true, wecontinue
poll the queue. Else iffound
is false, then we loop through every character of the poll string. What we want is in each iteration, we remove a current iterated character to make a new string, then add this new string to the queue, and repeat until the queue is empty.
Solution
1 |
|
LeetCode 320. Generalized Abbreviation
Write a function to generate the generalized abbreviations of a word.
Note: The order of the output does not matter.
Example:
1 |
|
Explanation
-
We can solve this problem using BFS. First, we append an empty string to the queue.
-
Loop through every iterated character of the input string. Under each iteration, we loop every poll string in the queue. For each poll string, if the poll string ends with number, we will abbreviate the last number of the poll string with the iterated character and push back to the queue; we can also not abbreviate by just appending the iterated character to the end of the poll string and push back to the queue. Else if the poll string does not end with number, we will abbreviate by appending 1 to the end of the poll string and push back to the queue; we can also not abbreviate by just appending the iterated character to the end of the poll string and push back to the queue.
-
After we finish looping every character of the input string, we just return the queue which contains all the abbreviations.
Solution
1 |
|
Modified Binary Search
LeetCode 704. 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
.
Source: Three Smart Ways to Use Binary Search in Coding Interviews
Solution
1 |
|
Ceiling of a Number
Given a sorted array of integers and an element K
, return the index of the celing of K
.
Ceiling of K
is the smallest element in an array greater than or equal to K
.
Example 1:
1 |
|
Explanation
- We can use binary search to solve this problem. While
left <= right
, if the middle index number is the ceilingarr[mid] >= target
, then we updateright = mid - 1
, else we updateleft = mid + 1
. Outside this while loop, we checkarr[left]
if it’s the ceiling, then we return its index, else there’s no ceiling so we return -1.
Solution
1 |
|
LeetCode 744. Find Smallest Letter Greater Than Target
Given a list of sorted characters letters
containing only lowercase letters, and given a target letter target
, find the smallest element in the list that is larger than the given target.
Letters also wrap around. For example, if the target is target = 'z'
and letters = ['a', 'b']
, the answer is 'a'
.
Examples:
1 |
|
Note:
-
letters
has a length in range [2, 10000]. -
letters
consists of lowercase letters, and contains at least 2 unique letters. -
target
is a lowercase letter.
Explanation
- We can use binary search to find the first greater element in a sorted array. While
left <= right
, ifarr[mid] <= target
, then we updateleft = mid + 1
; else we updateright = mid - 1
. Outside the while loop, we returnarr[left]
. In this problem, since the array is wrapped around, we can returnarr[left % arr.size()]
.
Solution
1 |
|
LeetCode 34. Find First and Last Position of Element in Sorted Array
Given an array of integers nums
sorted in ascending order, find the starting and ending position of a given target
value.
Your algorithm’s runtime complexity must be in the order of O(\log n)
.
If the target is not found in the array, return [-1, -1]
.
Example 1:
1 |
|
Example 2:
1 |
|
Explanation
-
Since we need to use $O(log n)$ runtime to solve this problem, we can use binary search to find the fist position, and use the binary search again to find the last position of the target.
-
To find the first position of the target, while
left <= right
, ifnums[mid] >= target
, we should moveright
to the left byright = mid - 1
; else moveleft
byleft = mid + 1
. Outside the while loop,left
is pointing to the first position of the target. Before we returnleft
, we need to check ifleft
is less than the size ofarr
. -
To find the last position of the target, while
left <= right
, ifnums[mid] <= target
, we should moveleft
to the right byleft = mid + 1
; else moveright
byright = mid - 1
. Outside the while loop,right
is pointing to the last position of the target. Before we returnright
, we need to check ifright
is greater than or equal to 0.
Solution
1 |
|
LeetCode 702. 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 |
|
Note:
-
You may assume that all elements in the array are unique.
-
The value of each element in the array will be in the range
[-9999, 9999]
.
Explanation
- Since the array has infinity size, we should first find the proper bounds of the array that the target is in between. Initially, we define
left = 0
andright = 1
, whilereader.get(right) < target
, we should exponentially increase the bound’s size, in other words, double the size untiltarget
is in between the bound.
Solution
1 |
|
Minimum Difference Element
Given an array of numbers sorted in ascending order. Find the element in the array that has the minimum difference with the given key. Assume there will be only 1 result.
Explanation
- We can use binary search to solve this problem. If the
arr[mid] == target
, then we immediately returnarr[mid]
. Else ifarr[mid] < target
, then besides updateleft = mid + 1
, we also calculate the difference betweenarr[mid]
andtarget
, if the difference is less thanminDiff
, then we update theminDiff
and the result bearr[mid]
. Similarlly, ifarr[mid] > target
, then besides updateright = mid - 1
, we also calculate the difference betweenarr[mid]
andtarget
, if the difference is less thanminDiff
, then we update theminDiff
and the result bearr[mid]
.
Solution
1 |
|
LeetCode 162. Find Peak Element
A peak element is an element that is greater than its neighbors.
Given an input array nums
, where nums[i] ≠ nums[i+1]
, find a peak element and return its index.
The array may contain multiple peaks, in that case return the index to any one of the peaks is fine.
You may imagine that nums[-1] = nums[n] = -∞
.
Example 1:
1 |
|
Example 2:
1 |
|
Note:
Your solution should be in logarithmic complexity.
Explanation
-
First if the input array has size 1, then we return index 0 since
nums[-1] = nums[n] = -∞
. -
We can use binary search to find the maximum element. We use
while (left < right)
since we comparenums[mid]
andnums[mid+1]
. Ifnums[mid+1]
is greater, then we updateleft = mid + 1
; else ifnums[mid] <= nums[mid+1]
, then we updateright = mid
. Outside the while loop,nums[left]
is pointing to the maximum element.
Solution
1 |
|
Bitwise XOR
LeetCode 136. Single Number
Given a non-empty array of integers, every element appears twice except for one. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
Example 1:
1 |
|
Example 2:
1 |
|
Explanation
- We can use
XOR
to solve this problem. We know that0 XOR 0 = 0
,1 XOR 1 = 0
,0 XOR 1 = 1 XOR 0 = 1
. For example, we can initialize the res is0000
first, loop through all the numbers, if the first number is1010
thenres XOR num = 0000 XOR 1010 = 1010
. If the second number is also1010
, thenres = res XOR num = 1010 XOR 1010 = 0000
; If the third number is1100
, then theres = res XOR num = 0000 XOR 1100 = 1100
. So we return the third number.
Solution
1 |
|
LeetCode 260. Single Number III
Given an array of numbers nums
, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once.
Example:
1 |
|
Note:
-
The order of the result is not important. So in the above example,
[5, 3]
is also correct. -
Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity?
Explanation
-
This problem asks us to find the two numbers (let say
a
andb
) that are appear only once and they are different. If we want to use the XOR method by 136. Single Number, we need to seperate these two numbers into two different groups then apply the XOR method. -
If we XOR all the numbers in the array, then the result will be
xo = a ^ b
because all other numbers are the same and appear twice and they will eventually become zero. Now, we want to seperate the array into two groups. Note, thexo
cannot be zero here sincea
andb
are different. We can use a bit as a seperate point, which is thexo
right most non-zero bit as a seperate point. Becausea
andb
on that bit will have different value. Note, the seperate point number will be only that bit is 1, other bit are 0. For example00100
. -
We use this seperate number (let say
diff
) to AND all the numbers in the array. If the current iterated number AND this seperate number equals 0, then it’s one group; else equal 1, will be another group, sincea
andb
on that bit are different. -
We can use the XOR method to find that appeared only once number in a group to find
a
, and use the same method to findb
in antoher group. -
How do we find
diff
? After we XOR all numbers in the array to getxo
, we use the formuladiff = ~(xo-1) & xo
to getdiff
. For example, ifxo
is 101100, then it subtract one equals 101011, not 101011 equals 010100. Then 010100 AND 101100 becomes 000100, which has only the right most 1 bit ofxo
.
Solution
1 |
|
LeetCode 1009. 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
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 |
|
Top ‘K’ Elements
LeetCode 215. Kth Largest Element in an Array
Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.
Example 1:
1 |
|
Example 2:
1 |
|
Note:
You may assume k is always valid, 1 ≤ k ≤ array’s length.
Explanation
-
We can use quick sort’s partition function to solve this problem in $O(1)$ time complexity because partition function return us the correct index, where all elements on the left side of the index are greather than this index number, all elements are on the right side of this index number are less than this index number. Note, we are sorting from largest to smallest.
-
First, we make a left pointer and right pointer that point to index 0 and the right most index. If the partition function return us
p
which equals tok-1
, then we returnnums[k-1]
. Else ifk-1
is greather thanp
, then left pointer moves top+1
, else ifk-1
is smaller thanp
, then right pointer moves top-1
. -
Inside the partition function, we first mark the first element as pivot. Left pointer moves one step forward, which is
left+1
, right poitner is the last index. While left pointer is smaller or equal to the right pointer, we start a while loop. If the left pointer number is smaller than the value of pivot and right pointer value is greather than pivot value, swap the left pointer and right pointer value. Then, if the left pointer value is greater or equal to the pivot value, then left pointer move right one step. If the right pointer value is smaller or equal than pivot, then right pointer value move left one step. -
Out of the while loop, we swap pivot and the right pointer. Now, pivot is at its correct index. We finally return its index, which is the right pointer.
Solution
1 |
|
Kth Smallest Number
Given an array and a number k where k is smaller than the size of the array, we need to find the k’th smallest element in the given array. It is given that all array elements are distinct.
Examples:
1 |
|
Source: K’th Smallest/Largest Element in Unsorted Array Set 1
Explanation
- Loop through the array, putting the first k elements into the max-heap. For the rest of numbers in the array, in each iteration, we compare the iterated number with the top or maximum number of the max-heap. If the iterated number is smaller, then we extract out the top element of the max-heap, and put the iterated number into the max-heap.
Solution
1 |
|
LeetCode 973. K Closest Points to Origin
We have a list of points
on the plane. Find the K
closest points to the origin (0, 0)
.
(Here, the distance between two points on a plane is the Euclidean distance.)
You may return the answer in any order. The answer is guaranteed to be unique (except for the order that it is in.)
Example 1:
1 |
|
Example 2:
1 |
|
Note:
1 |
|
Explanation
- This problem asks us to find the first K short distance points and return them without sorting, so we can use quick select method to solve this problem in $O(N)$ average time complexity.
Solution
1 |
|
LeetCode 1167. Minimum Cost to Connect Sticks
You have some sticks
with positive integer lengths.
You can connect any two sticks of lengths X
and Y
into one stick by paying a cost of X + Y
. You perform this action until there is one stick remaining.
Return the minimum cost of connecting all the given sticks
into one stick in this way.
Example 1:
1 |
|
Example 2:
1 |
|
Constraints:
-
1 <= sticks.length <= 10^4
-
1 <= sticks[i] <= 10^4
Explanation
-
Everytime we want to connect the two shortest sticks first, then put the connected sticks back, and repeat this process.
-
We can use min-heap to solve this problem. First put the array of integers into a min-heap. While the heap has size more than 1, we want to extract 2 minimum integers out of the heap and sum them, update the result, then put the sum back to the heap.
Solution
1 |
|
LeetCode 347. Top K Frequent Elements
Given a non-empty array of integers, return the k most frequent elements.
Example 1:
1 |
|
Example 2:
1 |
|
Note:
-
You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
-
Your algorithm’s time complexity must be better than O(n log n), where n is the array’s size.
Explanation
-
We can use bucket sort with $O(n)$ runtime to solve this problem.
-
First, we create a hashmap to store each number and its frequency. Then, we find out the maximum frequency, and use the maximum frequency as the length of a new array. The array will have length maximum frequency plus one, since we want the maximum frequency is the last index of this array.
-
Each array element will be a new array list. Then, we loop through the HashMap, put the entry’s frequency as the array’s index, number will add it to the list
arr[i]
. -
Now, we can loop from the back of the array to front, for each arraylist
arr[i]
, we store their number into ourres
list until theres
list has sizek
.
Solution
1 |
|
LeetCode 451. Sort Characters By Frequency
Given a string, sort it in decreasing order based on the frequency of characters.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Explanation
-
We can also use bucket sort to solve this problem. First, we store the character and its frequency to a HashMap. Next, we create an array of list. Iterate the HashMap, for each entry, its frequency will be the array’s index, its key, in other words, the character will be added to the list on that index.
-
Next, we iterate the array from right to left, if the element on the current index is null, that means there’s no list, so we continue. Else, the current index has a list, then we append the list’s character the number of index times to the StringBuilder.
Solution
1 |
|
LeetCode 703. Kth Largest Element in a Stream
Design a class to find the kth largest element in a stream. Note that it is the kth largest element in the sorted order, not the kth distinct element.
Your KthLargest class will have a constructor which accepts an integer k and an integer array nums, which contains initial elements from the stream. For each call to the method KthLargest.add, return the element representing the kth largest element in the stream.
Example:
1 |
|
Note:
You may assume that nums’ length ≥ k-1 and k ≥ 1.
Explanation
- Similar to LeetCode 215. Kth Largest Element in an Array, the difference is in this problem, the size of the stream is unknown. We can solve it using a min heap with size
k
. If the heap has size more thank
, we pop out the min value to maintain all elements in the heap are theK
largest elements.
Solution
1 |
|
LeetCode 658. Find K Closest Elements
Given a sorted array, two integers k and x, find the k closest elements to x in the array. The result should also be sorted in ascending order. If there is a tie, the smaller elements are always preferred.
Example 1:
1 |
|
Example 2:
1 |
|
Note:
-
The value k is positive and will always be smaller than the length of the sorted array.
-
Length of the given array is positive and will not exceed 104
-
Absolute value of elements in the array and x will not exceed 104
UPDATE (2017/9/19):
The arr parameter had been changed to an array of integers (instead of a list of integers). Please reload the code definition to get the latest changes.
Explanation
-
Since the array is sorted, we can use binary search. We are trying to use binary search to find the starting index of the result array. So the range of the starting index will be
left=0
toright=arr.length-k
inclusive. -
While
left < right
, we calculate themid
as the starting index of the result array andarr[mid+k]
as the nextk
positions’ starting index. Then we compare the difference betweenx-arr[mid]
andarr[mid+k]-x
. If the difference betweenarr[mid]
andx
is greater, we moveleft
to the right side. Else we moveright
to the left side. -
When
left == right
, that means we find the starting index of the result array. So we starting from this index and loop till indexleft + k
and adding all these iterated elements to the result array.
Solution
1 |
|
Maximum Distinct Elements
Given an array arr[]
containing n elements. The problem is to find maximum number of distinct elements (non-repeating) after removing k
elements from the array.
Note: 1 <= k <= n.
Example:
1 |
|
Source: Maximum distinct elements after removing k elements
Explanation
-
Create a hashmap and store all the array elements’ frequency.
-
Loop through the hashmap, if the entry has frequency 1, then we increase the result. Else, we push the entry’s frequency into a min-heap.
-
While
k > 0
and the min-heap is not empty, we extract the minimum frequency out and decrease it by 1. If the updated extracted frequency is equal to 1, then we increase the result; else we push back the updated extracted frequency into the min-heap. -
Outside the while loop, we return the result.
Solution
1 |
|
Sum of Elements
Given an array of integers and two numbers k1
and k2
. Find the sum of all elements between given two k1
’th and k2
’th smallest elements of the array. It may be assumed that (1 <= k1 < k2 <= n
) and all elements of array are distinct.
Examples :
1 |
|
Source: Sum of all elements between k1’th and k2’th smallest elements
Explanation 1
- Sort the array. Then loop through the array from index
k1
to indexk2-2
inclusive and sum the iterated elements.
Solution 1
1 |
|
Explanation 2
-
Create a min-heap for all array elements. (This takes O(n) time).
-
Extract the minimum element k1 times (This takes O(k1 Log n) time).
-
Extract the minimum element k2 – k1 – 1 times and sum all these extracted elements. (This takes O ((k2 – k1) * Log n) time).
Solution 2
1 |
|
LeetCode 767. Reorganize String
Given a string S, check if the letters can be rearranged so that two characters that are adjacent to each other are not the same.
If possible, output any possible result. If not possible, return the empty string.
Example 1:
1 |
|
Example 2:
1 |
|
Note:
S
will consist of lowercase letters and have length in range[1, 500]
.
Explanation
-
First getting every character’s frequency. Then we append the highest frequency character to the result StringBuilder first, the second highest frequency frequency character to the result StringBuilder second. After we appending these two characters, we update their frequency and repeat this process.
-
To achieve the above implementation, we need to create a new class which grouping the character and its frequency, and we need a priority queue to store the grouping and sorting by highest frequency in front.
-
The result will be an empty string only if any of the character frequency is higher than half of the string length. So before we append the grouping to the priority queue, we check if the result will be an empty string.
Solution
1 |
|
K-way merge
LeetCode 23. Merge k Sorted Lists
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
Example:
1 |
|
Explanation 1
-
We can use divide and conquer method to solve this problem. For example, if we have 6
ListNode
, then we can solve ListNode1 with ListNode4, ListNode2 with ListNode5, ListNode3 with ListNode6. -
Then, we have 3
ListNode
need to sort. We then sort ListNode1 with ListNode3. -
Then, we have 2
ListNode
need to sort. We then sort ListNode1 with ListNode2. -
Finally, we return the result of ListNode1.
-
Since there are $k$ ListNode in the array, similarly to merge sort, we divide $k$ ListNode takes $\log(k)$ time, and there are total of $kn$ nodes to compare, so the total time complexity is $kn\log(k)$. The space complexity is $log(k)$ because of the recursive stack.
Solution 1
1 |
|
Explanation 2
-
We can create a min-heap by using the PriorityQueue data structure to store all ListNode. If there are $k$ ListNode inside the input array, then we store all $k$ ListNode. They are sorted by their first Node value.
-
We create a
res
ListNode, then extract the minimum ListNode and put it’s value into theres
ListNode. If the extracted ListNode’s next node is not empty, put it back to the priority queue. Repeat this process until the priority queue is empty. -
Finally return the
res
ListNode. -
Since there are $k$ ListNode in the array, and there are $n$ ListNode in each ListNode, so there are total of $kn$ elements in the array. Because each element adding to the queue costs $log(k)$ time, so the total time complexity is $kn\log(k)$. The space complexity is $O(k)$ because of the min-heap size will have maximum $k$ ListNodes.
Solution 2
1 |
|
Kth Smallest Number in M Sorted Lists
Given M sorted arrays of possibly different sizes, find K-th smallest value in the merged array.
Examples:
1 |
|
Explanation
-
Create a min-heap of size M, then put the first element of every sorted list into the min-heap.
-
Loop K-1 times, in each iteration, we pop the minimum element out of the heap and insert the pop element’s next element into the min-heap.
-
After looping K-1 times, the Kth smallest element will be the top element in the min-heap.
Solution
1 |
|
Kth Smallest Number in a Sorted Matrix
Given an N ∗ N matrix where each row and column is sorted in ascending order, find the Kth smallest element in the matrix.
Example 1:
1 |
|
Explanation 1
-
As each row (or column) of the given matrix can be seen as a sorted list, we essentially need to find the Kth smallest number in
N
sorted lists. -
We can create a class
Node
to record the row and column. Row is the index for the sublist, col is the index for the element in the sublist. We also create a min-heap to store theNode
and sort by their element from smallest to largest. -
We put the first element as a new Node of each sublist into the min-heap. While the min-heap is not empty, we extract the minimum Node out, then update the result be
matrix[Node.row][Node.col]
. Then increase the counter, if the counter isK
, then we break out this while loop and return the result. Else, we increase the extracted Node’s col, check if the updated col is less than its corresponding subist’s length, then we push the updated extracted Node back into the min-heap. -
Time complexity. First, we inserted at most
K
or one element from each of theN
rows, which will take $O(min(K, N))$. Then we went through at mostK
elements in the matrix and remove/add one element in the heap in each step. As we can’t have more thanN
elements in the heap in any condition, therefore, the overall time complexity of the above algorithm will be $O(min(K, N) + K log N)$. -
Space complexity. The space complexity will be $O(N)$ because, in the worst case, our min-heap will be storing one number from each of the
N
rows.
Solution 1
1 |
|
Explanation 2
-
We apply the Binary Search on the “number range” instead of the “index range”. As we know that the smallest number of our matrix is at the top left corner and the biggest number is at the bottom right corner. These two numbers can represent the “range” i.e., the start and the end for the Binary Search.
-
Start the Binary Search with
start = matrix[0][0]
andend = matrix[n-1][n-1]
. -
Find
middle
of thestart
and theend
. This middle number is NOT necessarily an element in the matrix. -
Count all the numbers smaller than or equal to
middle
in the matrix. As the matrix is sorted, we can do this in $O(N)$. -
While counting, we can keep track of the “smallest number greater than the
middle
” (let’s call itn1
) and at the same time the “biggest number less than or equal to themiddle
” (let’s call itn2
). These two numbers will be used to adjust the “number range” for the Binary Search in the next iteration. -
If the count is equal to
K
,n1
will be our required number as it is the “biggest number less than or equal to themiddle
”, and is definitely present in the matrix. -
If the count is less than
K
, we can updatestart = n2
to search in the higher part of the matrix and if the count is greater thanK
, we can updateend = n1
to search in the lower part of the matrix in the next iteration.
Solution 2
1 |
|
Source: Kth Smallest Number in a Sorted Matrix (Hard)
LeetCode 632. Smallest Range Covering Elements from K Lists
You have k
lists of sorted integers in ascending order. Find the smallest range that includes at least one number from each of the k
lists.
We define the range [a,b] is smaller than range [c,d] if b-a < d-c
or a < c
if b-a == d-c
.
Explanation
-
First, we put all the sublists’ first number into a min-heap. While we putting the first number, we also record the maximum number
curMax
. After finishing putting the first numbers, we can calculate thediff
which is the maximum number subtract the top number of the min-heap. Also, we can initalize the result range be the min-heap’s top number and thecurMax
. -
Now, while the min-heap’s top element is not the last element in its corresponding list, we extract out the minimum number from the min-heap. Then we get the next number from the extracted number’s list, and compare it with
curMax
to updatecurMax
. After comparing, we put that next number into the min-heap. Then, we calculate thenewDiff
bycurMax
subtract the top element of the min-heap. If thenewDiff
is less thandiff
, then we updatediff = newDiff
and the result range be top element of the min-heap andcurMax
. -
The time complexity is the O(N * log K) where N is the maximum size of the sublists and K is the nubmer of sub-lists.
Solution
1 |
|
0/1 Knapsack (Dynamic Programming)
0/1 Knapsack
Given weights and values of n
items, put these items in a knapsack of capacity W
to get the maximum total value in the knapsack. In other words, given two integer arrays val[0..n-1]
and weight[0..n-1]
which represent values and weights associated with n
items respectively. Also given an integer W
which represents knapsack capacity, find out the maximum value subset of val[]
such that sum of the weights of this subset is smaller than or equal to W
. You cannot break an item, either pick the complete item, or don’t pick it (0-1 property).
Source: 0-1 Knapsack Problem DP-10
Explanation
-
I had written a post about Knapsack Problem which is explained in detail.
-
Dynamic Programming is an algorithmic paradigm that solves a given complex problem by breaking it into subproblems and stores the results of subproblems to avoid computing the same results again. Following are the two main properties of a problem that suggests that the given problem can be solved using Dynamic programming.
-
Overlapping Subproblems
-
Optimal Substructure
Overlapping Subproblems: Dynamic Programming is mainly used when solutions of same subproblems are needed again and again. In dynamic programming, computed solutions to subproblems are stored in a table so that these don’t have to be recomputed.
Optimal Substructure: A given problems has Optimal Substructure Property if optimal solution of the given problem can be obtained by using optimal solutions of its subproblems.
-
-
We can use dynamic programming to solve this problem. We create a 2 dimensional array
dp[i][j]
which represents the the maximum value we can make by putting the firsti
item in a knapsack withj
capacity. We have:-
dp[i][0] = dp[0][j] = 0
-
dp[i][j] = dp[i-1][j]
ifweight[i] > j
-
dp[i][j] = max(dp[i-1][j], dp[i-1][j - weight[i]] + val[i])
ifj >= weight[i]
-
Source:
Overlapping Subproblems Property in Dynamic Programming DP-1
Optimal Substructure Property in Dynamic Programming DP-2
Solution
1 |
|
LeetCode 416. Partition Equal Subset Sum
Given a non-empty array containing only positive integers, find if the array can be partitioned into two subsets such that the sum of elements in both subsets is equal.
Note:
-
Each of the array element will not exceed 100.
-
The array size will not exceed 200.
Example 1:
1 |
|
Example 2:
1 |
|
Explanation
-
This problem is asking for all the numbers in the array, can any of these numbers form the sum
sum / 2
. This is a 0-1 knapsack problem. Dynamic state isboolean[][] dp[i][j]
and it represents for the firsti
numbers, they can form the sumj
or not. -
Dynamic init is first row are false,
dp[0][c] = false
wherec != 0
because for the first 0 number, we cannot form any sum.dp[r][0] = true
because if the sum is 0, then for the first any number we can always form the sum 0. -
Dynamic function. For every number, we either choose it to form the sum
j
or not choose it. If we don’t choose the current number, then we havedp[r][c] = dp[r-1][c]
. If we choose the current number, then we havedp[r][c] = dp[r-1][c-curNum]
wherecurNum = nums[r-1]
. -
Dynamic result is
dp[nums.length][sum / 2]
.
Solution
1 |
|
Subset Sum
Given a set of non-negative integers, and a value sum, determine if there is a subset of the given set with sum equal to given sum.
Example
1 |
|
Source:
Perfect Sum Problem (Print all subsets with given sum)
Explanation
- Same as Partition Equal Subset Sum, we can create a two dimensional array
dp[i][j]
which represents for the firsti
number, if any of them can form the sumj
. At the end, we will returndp[nums.length][sum]
.
Solution
1 |
|
Minimum Subset Sum Difference
Given a set of positive integers, write a function to divide it into two sets S1 and S2 such that the absolute difference between their sums is minimum.
If there is a set S
with n
elements, then if we assume Subset1 has m
elements, Subset2 must have n-m
elements and the value of abs(sum(Subset1) – sum(Subset2))
should be minimum.
Example 1:
1 |
|
Example 2:
1 |
|
Source: 724. Minimum Partition
Explanation
-
Since we want the difference between
S1
’s sum andS2
’s sum be minimum, thenS1
’s sum andS2
’s sum should be closed to equal. In other words,S1
’s sum andS2
’s sum should be closed tototalSum / 2
. -
For all the elements of the array, loop from
i = totalSum / 2
down toi = 1
, can we find a subset sum equal toi
. If we can find the subset sum equal toi
, then we haveS1
’s sum bei
andS2
’s sum betotalSum - i
. Their difference will betotalSum - i - i
.
Solution
1 |
|
Perfect Sum Problem (Print all subsets with given sum)
Given an array of integers and a sum, the task is to print all subsets of given array with sum equal to given sum.
Example
1 |
|
Source: Perfect Sum Problem (Print all subsets with given sum)
Explanation
-
First, we need to build the 2 dimensional dp table using the bottom up method. Then we will use backtracking method to print all the subsets. In the backtracking helper method, we will pass the dp table, the target sum, the current index (we will start from the last index back to the first index and we will start from the bottom right cornor), the result list, the sub list, and the nums array.
-
In the backtracking method, the base case is if the sum is equals to 0, then we add the current list to the result list. If the index is less than 0, or the target sum is less than 0, then we return.
-
After checking the base case, if the
dp[index][target]
is true, then it means we can form thetarget
using numbers betweennums[0]
tonums[index]
inclusive. Ifdp[index][target]
is false, then we return out since it can’t form thetarget
. So when it’s true, we only consider two cases. Either includenums[index]
in the subset or not. In other words, when not include, it’s recursively calling the helper method withindex - 1
, and other parameters are the same. If we include, we addnums[index]
to the sublist, then recursively calling the helper method withtarget = target - nums[index]
andindex = index - 1
. Next we also need to backtrack to remove the last added element from the sublist.
Solution
1 |
|
LeetCode 494. Target Sum
You are given a list of non-negative integers, a1, a2, …, an, and a target, S. Now you have 2 symbols + and -. For each integer, you should choose one from +
and -
as its new symbol.
Find out how many ways to assign symbols to make sum of integers equal to target S.
Example 1:
1 |
|
Note:
-
The length of the given array is positive and will not exceed 20.
-
The sum of elements in the given array will not exceed 1000.
-
Your output answer is guaranteed to be fitted in a 32-bit integer.
Explanation 1
- This problem asks us to find the sum of all elements (we can make these elements positive or negative) equals to
S
. We can use recursion to solve this problem. First, think about if we plus the first numbernums[i]
, then the rest of the number should sum up toS-nums[i]
. So, it’s the same problem as the original problem. So now theS
becomesS-nums[i]
, the first number becomesnums[i+1]
. The base case is ifi == nums.length
, then at means we already try all elements, so we check ifS == 0
then we increaseres
. Similarlly, if we minus the first number, then the rest of the number should equals toS + nums[i]
.
Solution 1
1 |
|
Explanation 2
-
We can optimize the runtime for solution1. Starting at index
start
, we can record how many ways to form a sumS1
andS2
, etc. So we need to create an array of HashMap,dp[start]
is a HashMap, the key is the sum, the value is the number of ways to form that sum. -
The helper function will return an int. The base case is when
start == nums.length
, we check ifS
equals to 0. If it is, then we return 1, else return 0. Same as explanation1, we have two cases, either plus the first number or minus the first number, sodp[start].get(S)
will equals to the sum of recursive result of both cases.
Solution 2
1 |
|
Explanation 3
The recursive solution is very slow, because its runtime is exponential.
The original problem statement is equivalent to:
Find a subset of nums
that need to be positive, and the rest of them negative, such that the sum is equal to target
.
Let P
be the positive subset and N
be the negative subset. For example:
Given nums = [1, 2, 3, 4, 5]
and target = 3
then one possible solution is +1-2+3-4+5 = 3
.
Here positive subset is P = [1, 3, 5]
and negative subset is N = [2, 4]
Then let’s see how this can be converted to a subset sum problem:
1 |
|
So the original problem has been converted to a subset sum problem as follows:
Find a subset P
of nums
such that sum(P) = (target + sum(nums)) / 2
Note that the above formula has proved that target + sum(nums)
must be even.
We can use that fact to quickly identify inputs that do not have a solution.
Solution 3
1 |
|
Topological Sort (Graph)
Topological Sort
Topological sorting for Directed Acyclic Graph (DAG) is a linear ordering of vertices such that for every directed edge u->v
, vertex u
comes before v
in the ordering. Topological Sorting for a graph is not possible if the graph is not a DAG.
For example, a topological sorting of the following graph is “5 4 2 3 1 0”. There can be more than one topological sorting for a graph. For example, another topological sorting of the following graph is “4 5 2 0 3 1”. The first vertex in topological sorting is always a vertex with in-degree as 0 (a vertex with no incoming edges). One example for Topological Sort is build dependency problem. If dependencyA depends on dependencyB and dependencyC, then dependencyA can be resolved anytime after dependencyB and dependencyC are resolved.
Topological Sorting vs Depth First Traversal (DFS):
For example, in the given graph, the vertex ‘5’ should be printed before vertex ‘0’, but unlike DFS, in topological sort, the vertex ‘4’ should also be printed before vertex ‘0’. So Topological sorting is different from DFS. For example, a DFS of the shown graph is “5 2 3 1 0 4”, but it is not a topological sorting.
Source: Topological Sorting
Explanation 1
-
I had written a post about Topological Sort which is explained in detail.
-
Using queue method. First, we need to have an adjacent list. For example
adjancentList[v] = {a, b, c}
means before we visita
orb
orc
, we first visitv
. Then we update every vertex’s number ofinDegree
or dependencies. For example,inDegree[a] = 1
means before we visit vertexa
, we need to visit 1 other vertex. -
Next, we push all vertex that has 0 dependencies to the queue. While the queue is not empty, we poll the current vertex out and add to the result list. Then we subtract 1 of the
inDegree
for every vertex in the poll vertex’s adjancentList. For example, if we poll thev
out, then we updateinDegree[a] -= 1
,inDegree[b] -= 1
andinDegree[c] -= 1
. After updating, if any of these vertex has 0 indegree, we push it to the queue. -
Outside of the queue, if the result list has the same size as the number of vertex, then we return the result list.
Solution 1
1 |
|
Explanation 2
-
We can also use stack method to solve this problem.
-
Loop through every vertex, if the iterated vertex is not visited, then we pass it to the recursively helper method.
-
In the helper method, we first mark the current vertex as visited. Then we loop through its adjacent vertices and call these adjacent vertices with the helper method. Outside of the this loop, we push the vertex to the stack. In other words, a vertex is pushed to stack only when all of its adjacent vertices (and their adjacent vertices and so on) are already in stack.
-
In the main method, we print the stack from top to bottom.
Solution 2
1 |
|
LeetCode 207. Course Schedule
There are a total of n
courses you have to take, labeled from 0
to n-1
.
Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]
Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?
Example 1:
1 |
|
Example 2:
1 |
|
Note:
-
The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented.
-
You may assume that there are no duplicate edges in the input prerequisites.
Explanation 1
-
First, we need to build an adjancent list and the
inDegree
array. -
Push all the courses that have
inDegree
0, in other words, the courses that have no prerequisite to the queue. While the queue is not empty, we poll the course out and increae the counter, update the indegree of its adjancent list’s courses. If any of these updated course hasinDegree
0, we push it to the queue. -
Outside the queue, we check if the counter is equal to the number of courses. If the counter is equal to the number of courses, that means we can visit all the courses, so we return true, else return false.
Solution 1
1 |
|
Explanation 2
-
We can also use DFS to solve this problem. First, we make a directed graph as above. Also, we need to make a one dimensional array
visit[]
which is used to record if the classi
is visited or not. We use0
as unvisit,1
as visit,-1
as conflict. Since we use DFS, we can think of checking the classes linearly, if these classes make a circle, then it’s conflict and we return false. -
We loop through all the classes, for each class, we think of it as a starting point and use the helper function to check it.
-
In the helper function, before we DFS into the deeper class, we mark the class in the
visit
array-1
. So the base case is if the class is already mark as-1
, then it means we make a circle, and we immediatly returnfalse
. After checking all the classes in indexi
, in other word, sublist ofgraph[i]
, we mark classi
as visit1
. So the base case add one more condition, ifvisit[i]
is 1, then we immediately returntrue
since we confirm that base on starting point classi
, all its advanced class do not make a circle.
Solution 2
1 |
|
LeetCode 210. Course Schedule II
There are a total of n courses you have to take, labeled from 0
to n-1
.
Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]
Given the total number of courses and a list of prerequisite pairs, return the ordering of courses you should take to finish all courses.
There may be multiple correct orders, you just need to return one of them. If it is impossible to finish all courses, return an empty array.
Example 1:
1 |
|
Example 2:
1 |
|
Note:
-
The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented.
-
You may assume that there are no duplicate edges in the input prerequisites.
Explanation 1
- Using the same queue method as LeetCode 207. Course Schedule, all we need to do is create a result array. When we poll the course out of the queue, we add it to the result array. At the end, if the counter is equal to the number of courses, then we return the result array.
Solution 1
1 |
|
Explanation 2
-
Using the same stack method as LeetCode 207. Course Schedule, all we need to do is creating a stack and pass it to the helper method. After we
visited[curCourse] = 1
, we then push thecurCourse
to the stack. -
At the end, we pop the stack and add the pop course to the result array.
Solution 2
1 |
|
All Tasks Scheduling Orders
Given a Directed Acyclic Graph (DAG), print all topological sorts of the graph.
Example:
1 |
|
Explanation
-
We can use backtracking method to print all the paths. First, we build the adjancent list and the inDegree list. Then we call a helper method by passing the graph, the number of vertexes, the visited array, and the list of path.
-
In the helper method, we loop through all the vertexes, if the current vertex has inDegree 0 and it’s not visited, then we add it to the path and mark it as visited. Also we loop through its adjancent vertexes and update their inDegree subtract 1. Then we recursively call the helper method. After calling the recursive helper method, we need to backtrack. So we restore the current vertex’s adjancent vertexes’ inDegree plus 1, remove the current vertex from the path list, and mark it as not visited.
-
In the helper method, after looping through all the vertexes, if the path list has size N, then we print the path list.
Solution
1 |
|
Source:
All Topological Sorts of a Directed Acyclic Graph
Find all Possible Topological Orderings of a DAG
LeetCode 269. Alien Dictionary
There is a new alien language which uses the latin alphabet. However, the order among letters are unknown to you. You receive a list of non-empty words from the dictionary, where words are sorted lexicographically by the rules of this new language. Derive the order of letters in this language.
Example 1:
1 |
|
Example 2:
1 |
|
Example 3:
1 |
|
Note:
-
You may assume all letters are in lowercase.
-
You may assume that if a is a prefix of b, then a must appear before b in the given dictionary.
-
If the order is invalid, return an empty string.
-
There may be multiple valid order of letters, return any one of them is fine.
Explanation
- We can use Topological Sort to solve this problem. First, we need to build the adjancent list array and the inDegree array. How do we know the dependencies? We can loop through the input list, and each time we compare the current iterated word
words[i]
with its next wordwords[i + 1]
. For example, by comparingwrt
andwrf
, if the character is different, then we have the dependencies thatt
is beforef
.
Solution
1 |
|
Miscellaneous
LeetCode 668. Kth Smallest Number in Multiplication Table
Nearly every one have used the Multiplication Table. But could you find out the k-th
smallest number quickly from the multiplication table?
Given the height m
and the length n of a m * n
Multiplication Table, and a positive integer k
, you need to return the k-th
smallest number in this table.
Example 1:
1 |
|
Example 2:
1 |
|
Note:
-
The
m
andn
will be in the range [1, 30000]. -
The
k
will be in the range [1, m * n]
Explanation
-
Similar to Kth Smallest Number in a Sorted Matrix, we can use binary search method to solve this problem. The range will be 1 to
m * n
. -
First, we know the smallest number
left
is 1, the larget numberright
ism * n
. Whileleft < right
, we can calculate themid
. Next, we want to calculate how many numbers less than or equal tomid
and let say it’s calledcnt
. -
We can compare
mid
with the bottom left number, and we usei=m, j=1
to define the position of the bottom left number’s row and column. If the bottom left number is less than or equal tomid
, then we move the bottom left number to the right, in other word,j += 1
, and updatenumLessEqualMid += i
. Else we move the bottom left number 1 row up, which isi -= 1
. Repeat this process whilei >= 1 && j <= n
. -
If
cnt
is less thank
, then we need to updateleft = mid + 1
, else we updateright = mid
. Repeat this process whileleft < right
. -
Outside of the while loop when
left
isright
are equal, we can just returnleft
as our answer.
Solution
1 |
|