Program Creek Coding Interview
Program Creek Coding Interview
Java
Program Creek
3 Isomorphic Strings 21
4 Word Ladder 23
5 Word Ladder II 25
8 Wildcard Matching 33
10 Merge Intervals 39
11 Insert Interval 41
12 Two Sum 43
15 3Sum 49
16 4Sum 53
17 3Sum Closest 55
20 Valid Parentheses 61
2 | 531
Contents
22 Implement strStr() 65
26 Valid Palindrome 77
27 ZigZag Conversion 81
28 Add Binary 83
30 Triangle 87
31 Contains Duplicate 89
32 Contains Duplicate II 91
58 Candy 149
68 Get Target Number Using Number List and Arithmetic Operations 169
135 Construct Binary Tree from Inorder and Postorder Traversal 329
136 Construct Binary Tree from Preorder and Inorder Traversal 331
170 Solution Sort a linked list using insertion sort in Java 411
Every title in the PDF is linked back to the original blog. When it is clicked, it opens
the original post in your browser. If you want to discuss any problem, please go to the
post and leave your comment there.
I’m not an expert and some solutions may not be optimal. So please leave your
comment if you see any problem or have a better solution. I will reply your comment
as soon as I can.
This collection is updated from time to time. Please check out this link for the lat-
est version: http://www.programcreek.com/2012/11/top-10-algorithms-for-coding-
interview/
You may have been using Java for a while. Do you think a simple Java array question
can be a challenge? Let’s use the following problem to test.
Problem: Rotate an array of n elements to the right by k steps. For example, with n
= 7 and k = 3, the array [1,2,3,4,5,6,7] is rotated to [5,6,7,1,2,3,4]. How many different
ways do you know to solve this problem?
In a straightforward way, we can create a new array and then copy elements to the
new array. Then change the original array by using System.arraycopy().
public void rotate(int[] nums, int k) {
if(k > nums.length)
k=k%nums.length;
int j=0;
for(int i=k; i<nums.length; i++){
result[i] = nums[j];
j++;
}
Space is O(n) and time is O(n). You can check out the difference between Sys-
tem.arraycopy() and Arrays.copyOf().
13 | 531
1 Rotate Array in Java
Can we do this in O(1) space and in O(n) time? The following solution does.
Assuming we are given 1,2,3,4,5,6 and order 2. The basic idea is:
1. Divide the array two parts: 1,2,3,4 and 5, 6
2. Reverse first part: 4,3,2,1,5,6
3. Reverse second part: 4,3,2,1,6,5
4. Reverse the whole array: 5,6,1,2,3,4
reverse(arr, 0, a-1);
reverse(arr, a, arr.length-1);
reverse(arr, 0, arr.length-1);
Evaluate the value of an arithmetic expression in Reverse Polish Notation. Valid op-
erators are +, -, *, /. Each operand may be an integer or another expression. For
example:
["2", "1", "+", "3", "*"] -> ((2 + 1) * 3) -> 9
["4", "13", "5", "/", "+"] -> (4 + (13 / 5)) -> 6
This problem can be solved by using a stack. We can loop through each element in the
given array. When it is a number, push it to the stack. When it is an operator, pop two
numbers from the stack, do the calculation, and push back the result.
The following is the code. However, this code contains compilation errors in leet-
code. Why?
public class Test {
17 | 531
2 Evaluate Reverse Polish Notation
returnValue = Integer.valueOf(stack.pop());
return returnValue;
}
}
The problem is that switch string statement is only available from JDK 1.7. Leetcode
apparently use a JDK version below 1.7.
If you want to use switch statement, you can convert the above by using the following
code which use the index of a string "+-*/".
public class Solution {
public int evalRPN(String[] tokens) {
int returnValue = 0;
for(String t : tokens){
if(!operators.contains(t)){
stack.push(t);
}else{
int a = Integer.valueOf(stack.pop());
int b = Integer.valueOf(stack.pop());
int index = operators.indexOf(t);
switch(index){
case 0:
stack.push(String.valueOf(a+b));
break;
case 1:
stack.push(String.valueOf(b-a));
break;
case 2:
stack.push(String.valueOf(a*b));
break;
case 3:
stack.push(String.valueOf(b/a));
break;
}
}
}
returnValue = Integer.valueOf(stack.pop());
return returnValue;
}
}
Given two strings s and t, determine if they are isomorphic. Two strings are isomor-
phic if the characters in s can be replaced to get t.
For example,"egg" and "add" are isomorphic, "foo" and "bar" are not.
3.1 Analysis
We need to define a method which accepts a map & a value, and returns the value’s
key in the map.
if(s.length() != t.length())
return false;
return true;
}
21 | 531
3 Isomorphic Strings
return null;
}
Given two words (start and end), and a dictionary, find the length of shortest transfor-
mation sequence from start to end, such that only one letter can be changed at a time
and each intermediate word must exist in the dictionary. For example, given:
start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]
One shortest transformation is "hit" ->"hot" ->"dot" ->"dog" ->"cog", the program
should return its length 5.
4.1 Analysis
UPDATED on 06/07/2015.
So we quickly realize that this is a search problem, and breath-first search guarantees
the optimal solution.
class WordNode{
String word;
int numSteps;
23 | 531
4 Word Ladder
wordDict.add(endWord);
while(!queue.isEmpty()){
WordNode top = queue.remove();
String word = top.word;
if(word.equals(endWord)){
return top.numSteps;
}
arr[i]=temp;
}
}
}
return 0;
}
}
Given two words (start and end), and a dictionary, find all shortest transformation
sequence(s) from start to end, such that: 1) Only one letter can be changed at a time,
2) Each intermediate word must exist in the dictionary.
For example, given: start = "hit", end = "cog", and dict = ["hot","dot","dog","lot","log"],
return:
[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]
5.1 Analysis
class WordNode{
String word;
int numSteps;
WordNode pre;
25 | 531
5 Word Ladder II
dict.add(end);
int minStep = 0;
int preNumSteps = 0;
while(!queue.isEmpty()){
WordNode top = queue.remove();
String word = top.word;
int currNumSteps = top.numSteps;
if(word.equals(end)){
if(minStep == 0){
minStep = top.numSteps;
}
preNumSteps = currNumSteps;
arr[i]=temp;
}
}
return result;
}
}
There are two sorted arrays A and B of size m and n respectively. Find the median of the
two sorted arrays. The overall run time complexity should be O(log (m+n)).
if ((m + n) % 2 != 0) // odd
return (double) findKth(A, B, (m + n) / 2, 0, m - 1, 0, n - 1);
else { // even
return (findKth(A, B, (m + n) / 2, 0, m - 1, 0, n - 1)
+ findKth(A, B, (m + n) / 2 - 1, 0, m - 1, 0, n - 1)) * 0.5;
}
}
29 | 531
6 Median of Two Sorted Arrays
Solution 1 is a general solution to find the kth element. We can also come up with a
simpler solution which only finds the median of two sorted arrays for this particular
problem. Thanks to Gunner86. The description of the algorithm is awesome!
1) Calculate the medians m1 and m2 of the input arrays ar1[] and ar2[]
respectively.
2) If m1 and m2 both are equal then we are done, and return m1 (or m2)
3) If m1 is greater than m2, then median is present in one of the below two
subarrays.
a) From first element of ar1 to m1 (ar1[0...|_n/2_|])
b) From m2 to last element of ar2 (ar2[|_n/2_|...n-1])
4) If m2 is greater than m1, then median is present in one of the below two
subarrays.
a) From m1 to last element of ar1 (ar1[|_n/2_|...n-1])
b) From first element of ar2 to m2 (ar2[0...|_n/2_|])
5) Repeat the above process until size of both the subarrays becomes 2.
6) If size of the two arrays is 2 then use below formula to get the median.
Median = (max(ar1[0], ar2[0]) + min(ar1[1], ar2[1]))/2
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.
For example, given [3,2,1,5,6,4] and k = 2, return 5.
Note: You may assume k is always valid, 1 ≤ k ≤ array’s length.
Time is O(nlog(n))
This problem can also be solve by using the quickselect approach, which is similar to
quicksort.
public int findKthLargest(int[] nums, int k) {
if (k < 1 || nums == null) {
return 0;
}
while (true) {
31 | 531
7 Kth Largest Element in an Array
if (left == right) {
break;
}
if (k == left + 1) {
return pivot;
} else if (k < left + 1) {
return getKth(k, nums, start, left - 1);
} else {
return getKth(k, nums, left + 1, end);
}
}
We can use a min heap to solve this problem. The heap stores the top k elements.
Whenever the size is greater than k, delete the min. Time complexity is O(nlog(k)).
Space complexity is O(k) for storing the top k numbers.
public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> q = new PriorityQueue<Integer>(k);
for(int i: nums){
q.offer(i);
if(q.size()>k){
q.poll();
}
}
return q.peek();
}
Implement wildcard pattern matching with support for ’?’ and ’*’.
return j == p.length();
}
33 | 531
9 Regular Expression Matching in Java
Implement regular expression matching with support for ’.’ and ’*’.
’.’ Matches any single character. ’*’ Matches zero or more of the preceding element.
The matching should cover the entire input string (not partial).
The function prototype should be: bool isMatch(const char *s, const char *p)
Some examples: isMatch("aa","a") return false isMatch("aa","aa") return true isMatch("aaa","aa")
return false isMatch("aa", "a*") return true isMatch("aa", ".*") return true isMatch("ab",
".*") return true isMatch("aab", "c*a*b") return true
9.1 Analysis
First of all, this is one of the most difficulty problems. It is hard to think through all
different cases. The problem should be simplified to handle 2 basic cases:
For the 1st case, if the first char of pattern is not ".", the first char of pattern and
string should be the same. Then continue to match the remaining part.
For the 2nd case, if the first char of pattern is "." or first char of pattern == the first i
char of string, continue to match the remaining part.
if(p.length() == 0)
return s.length() == 0;
}else{
35 | 531
9 Regular Expression Matching in Java
int i = -1;
while(i<len && (i < 0 || p.charAt(0) == ’.’ || p.charAt(0) ==
s.charAt(i))){
if(isMatch(s.substring(i+1), p.substring(2)))
return true;
i++;
}
return false;
}
}
}
// special case
if (p.length() == 1) {
return false;
} else {
return isMatch(s.substring(1), p.substring(1));
}
}
//case 2.2: a char & ’*’ can stand for 1 or more preceding element,
//so try every sub string
int i = 0;
while (i<s.length() && (s.charAt(i)==p.charAt(0) || p.charAt(0)==’.’)){
if (isMatch(s.substring(i + 1), p.substring(2))) {
return true;
}
i++;
}
return false;
}
}
Problem:
Given a collection of intervals, merge all overlapping intervals.
For example,
Given [1,3],[2,6],[8,10],[15,18],
return [1,6],[8,10],[15,18].
The key to solve this problem is defining a Comparator first to sort the arraylist of
Intevals. And then merge some intervals.
The take-away message from this problem is utilizing the advantage of sorted list/ar-
ray.
class Interval {
int start;
int end;
Interval() {
start = 0;
end = 0;
}
Interval(int s, int e) {
start = s;
end = e;
}
}
39 | 531
10 Merge Intervals
result.add(prev);
return result;
}
}
Problem:
Given a set of non-overlapping & sorted intervals, insert a new interval into the intervals
(merge if necessary).
Example 1:
Given intervals [1,3],[6,9], insert and merge [2,5] in as [1,5],[6,9].
Example 2:
Given [1,2],[3,5],[6,7],[8,10],[12,16], insert and merge [4,9] in as
[1,2],[3,10],[12,16].
41 | 531
11 Insert Interval
/**
* Definition for an interval.
* public class Interval {
* int start;
* int end;
* Interval() { start = 0; end = 0; }
* Interval(int s, int e) { start = s; end = e; }
* }
*/
public class Solution {
public ArrayList<Interval> insert(ArrayList<Interval> intervals, Interval
newInterval) {
result.add(newInterval);
return result;
}
}
Given an array of integers, find two numbers such that they add up to a specific target
number.
The function twoSum should return indices of the two numbers such that they add
up to the target, where index1 must be less than index2. Please note that your returned
answers (both index1 and index2) are not zero-based.
For example:
Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2
This problem is pretty straightforward. We can simply examine every possible pair of
numbers in this integer array.
Time complexity in worst case: O(n2̂).
public static int[] twoSum(int[] numbers, int target) {
int[] ret = new int[2];
for (int i = 0; i < numbers.length; i++) {
for (int j = i + 1; j < numbers.length; j++) {
if (numbers[i] + numbers[j] == target) {
ret[0] = i + 1;
ret[1] = j + 1;
}
}
}
return ret;
}
Can we do better?
43 | 531
12 Two Sum
return result;
}
}
Time complexity depends on the put and get operations of HashMap which is nor-
mally O(1).
Time complexity of this solution is O(n).
int i = 0;
int j = numbers.length - 1;
while (i < j) {
int x = numbers[i] + numbers[j];
if (x < target) {
++i;
} else if (x > target) {
j--;
} else {
return new int[] { i + 1, j + 1 };
}
}
return null;
}
45 | 531
14 Two Sum III Data structure design
Design and implement a TwoSum class. It should support the following operations:
add and find.
add - Add the number to an internal data structure. find - Find if there exists any
pair of numbers which sum is equal to the value.
For example,
add(1);
add(3);
add(5);
find(4) -> true
find(7) -> false
Since the desired class need add and get operations, HashMap is a good option for
this purpose.
public class TwoSum {
private HashMap<Integer, Integer> elements = new HashMap<Integer,
Integer>();
47 | 531
14 Two Sum III Data structure design
}
}
Problem:
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0?
Find all unique triplets in the array which gives the sum of zero.
Note: Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
The solution set must not contain duplicate triplets.
For example, given array S = {-1 0 1 2 -1 -4},
Naive solution is 3 loops, and this gives time complexity O(n3̂). Apparently this is not
an acceptable solution, but a discussion can start from here.
public class Solution {
public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
//sort array
Arrays.sort(num);
each.add(num[i]);
each.add(num[j]);
each.add(num[k]);
result.add(each);
each.clear();
}
49 | 531
15 3Sum
}
}
}
return result;
}
}
* The solution also does not handle duplicates. Therefore, it is not only time ineffi-
cient, but also incorrect.
Result:
Submission Result: Output Limit Exceeded
A better solution is using two pointers instead of one. This makes time complexity of
O(n2̂).
To avoid duplicate, we can take advantage of sorted arrays, i.e., move pointers by
>1 to use same element only once.
public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
if (num.length < 3)
return result;
// sort array
Arrays.sort(num);
int start = i + 1;
int end = num.length - 1;
result.add(temp);
start++;
end--;
//avoid duplicate solutions
while (start < end && num[end] == num[end + 1])
end--;
}
}
return result;
}
16.1 Thoughts
while (k < l) {
int sum = num[i] + num[j] + num[k] + num[l];
53 | 531
16 4Sum
temp.add(num[j]);
temp.add(num[k]);
temp.add(num[l]);
if (!hashSet.contains(temp)) {
hashSet.add(temp);
result.add(temp);
}
k++;
l--;
}
}
}
}
return result;
}
Here is the hashCode method of ArrayList. It makes sure that if all elements of two
lists are the same, then the hash code of the two lists will be the same. Since each
element in the ArrayList is Integer, same integer has same hash code.
int hashCode = 1;
Iterator<E> i = list.iterator();
while (i.hasNext()) {
E obj = i.next();
hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
}
Given an array S of n integers, find three integers in S such that the sum is closest to a
given number, target. Return the sum of the three integers. You may assume that each
input would have exactly one solution.
For example, given array S = {-1 2 1 -4}, and target = 1.
The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
17.1 Analysis
This problem is similar to 2 Sum. This kind of problem can be solved by using a
similar approach, i.e., two pointers from both left and right.
Arrays.sort(nums);
55 | 531
17 3Sum Closest
return result;
}
18.1 Analysis
// calculate value
while (str.length() > i && str.charAt(i) >= ’0’ && str.charAt(i) <= ’9’) {
result = result * 10 + (str.charAt(i) - ’0’);
57 | 531
18 String to Integer (atoi)
i++;
}
if (flag == ’-’)
result = -result;
Given two sorted integer arrays A and B, merge B into A as one sorted array.
Note: You may assume that A has enough space to hold additional elements from
B. The number of elements initialized in A and B are m and n respectively.
19.1 Analysis
The key to solve this problem is moving element of A and B backwards. If B has some
elements left after A is done, also need to handle that case.
The takeaway message from this problem is that the loop condition. This kind of
condition is also used for merging two sorted linked list.
The loop condition also can use m+n like the following.
59 | 531
19 Merge Sorted Array
while (k >= 0) {
if (j < 0 || (i >= 0 && A[i] > B[j]))
A[k--] = A[i--];
else
A[k--] = B[j--];
}
}
Given a string containing just the characters ’(’, ’)’, ’’, ’’, ’[’ and ’]’, determine if the
input string is valid. The brackets must close in the correct order, "()" and "()[]" are all
valid but "(]" and "([)]" are not.
20.1 Analysis
if (map.keySet().contains(curr)) {
stack.push(curr);
} else if (map.values().contains(curr)) {
if (!stack.empty() && map.get(stack.peek()) == curr) {
stack.pop();
} else {
return false;
}
}
}
return stack.empty();
}
61 | 531
21 Longest Valid Parentheses
Given a string containing just the characters ’(’ and ’)’, find the length of the longest
valid (well-formed) parentheses substring.
For "(()", the longest valid parentheses substring is "()", which has length = 2. An-
other example is ")()())", where the longest valid parentheses substring is "()()", which
has length = 4.
21.1 Analysis
This problem is similar with Valid Parentheses, which can be solved by using a stack.
return result;
63 | 531
21 Longest Valid Parentheses
Problem:
Implement strStr(). Returns the index of the first occurrence of needle in haystack, or -1
if needle is not part of haystack.
if(needle.length() == 0)
return 0;
int m = i;
for(int j=0; j<needle.length(); j++){
if(needle.charAt(j)==haystack.charAt(m)){
if(j==needle.length()-1)
return i;
m++;
}else{
break;
}
}
}
return -1;
}
65 | 531
22 Implement strStr()
return 0;
int h = haystack.length();
int n = needle.length();
if (n > h)
return -1;
if (n == 0)
return 0;
while (i <= h - n) {
int success = 1;
for (int j = 0; j < n; j++) {
if (needle.charAt(0) != haystack.charAt(i)) {
success = 0;
i++;
break;
} else if (needle.charAt(j) != haystack.charAt(i + j)) {
success = 0;
i = i + j - next[j - 1];
break;
}
}
if (success == 1)
return i;
}
return -1;
}
if (needle.charAt(index) == needle.charAt(i)) {
next[i] = next[i - 1] + 1;
} else {
next[i] = 0;
}
}
return next;
}
Given an array of n positive integers and a positive integer s, find the minimal length
of a subarray of which the sum ≥ s. If there isn’t one, return 0 instead.
For example, given the array [2,3,1,2,4,3] and s = 7, the subarray [4,3] has the minimal
length of 2 under the problem constraint.
23.1 Analysis
We can use 2 points to mark the left and right boundaries of the sliding window. When
the sum is greater than the target, shift the left pointer; when the sum is less than the
target, shift the right pointer.
int start=0;
int sum=0;
int i=0;
boolean exists = false;
while(i<=nums.length){
if(sum>=s){
exists=true; //mark if there exists such a subarray
if(start==i-1){
return 1;
}
}else{
if(i==nums.length)
break;
69 | 531
23 Minimum Size Subarray Sum
sum = sum+nums[i];
i++;
}
}
if(exists)
return result;
else
return 0;
}
int i = 0;
int sum = nums[0];
if(j<nums.length){
sum = sum + nums[j];
}else{
return result;
}
}
}else{
//if sum is large enough, move left cursor
if(sum >= s){
result = Math.min(j-i+1, result);
sum = sum - nums[i];
i++;
if(j<nums.length){
sum = sum + nums[j];
}else{
if(i==0){
return 0;
}else{
return result;
}
}
}
}
}
return result;
}
Given a sorted array and a target value, return the index if the target is found. If not,
return the index where it would be if it were inserted in order. You may assume no
duplicates in the array.
Here are few examples.
[1,3,5,6], 5 -> 2
[1,3,5,6], 2 -> 1
[1,3,5,6], 7 -> 4
[1,3,5,6], 0 -> 0
24.1 Solution 1
Naively, we can just iterate the array and compare target with ith and (i+1)th element.
Time complexity is O(n)
public class Solution {
public int searchInsert(int[] A, int target) {
if(A==null) return 0;
return A.length;
}
}
24.2 Solution 2
This also looks like a binary search problem. We should try to make the complexity to
be O(log(n)).
public class Solution {
public int searchInsert(int[] A, int target) {
73 | 531
24 Search Insert Position
if(A==null||A.length==0)
return 0;
return searchInsert(A,target,0,A.length-1);
}
if(target==A[mid])
return mid;
else if(target<A[mid])
return start<mid?searchInsert(A,target,start,mid-1):start;
else
return end>mid?searchInsert(A,target,mid+1,end):(end+1);
}
}
Given an unsorted array of integers, find the length of the longest consecutive elements
sequence.
For example, given [100, 4, 200, 1, 3, 2], the longest consecutive elements sequence
should be [1, 2, 3, 4]. Its length is 4.
Your algorithm should run in O(n) complexity.
25.1 Analysis
Because it requires O(n) complexity, we can not solve the problem by sorting the array
first. Sorting takes at least O(nlogn) time.
We can use a HashSet to add and remove elements. HashSet is implemented by using
a hash table. Elements are not ordered. The add, remove and contains methods have
constant time complexity O(1).
public static int longestConsecutive(int[] num) {
// if array is empty, return 0
if (num.length == 0) {
return 0;
}
while (set.contains(left)) {
count++;
set.remove(left);
left--;
}
75 | 531
25 Longest Consecutive Sequence
while (set.contains(right)) {
count++;
set.remove(right);
right++;
}
return max;
}
After an element is checked, it should be removed from the set. Otherwise, time
complexity would be O(mn) in which m is the average length of all consecutive se-
quences.
To clearly see the time complexity, I suggest you use some simple examples and
manually execute the program. For example, given an array 1,2,4,5,3, the program
time is m. m is the length of longest consecutive sequence.
26.1 Thoughts
From start and end loop though the string, i.e., char array. If it is not alpha or num-
ber, increase or decrease pointers. Compare the alpha and numeric characters. The
solution below is pretty straightforward.
int i=0;
int j=len-1;
while(i<j){
char left, right;
77 | 531
26 Valid Palindrome
right = charArray[j];
}
if(i >= j)
break;
left = charArray[i];
right = charArray[j];
if(!isSame(left, right)){
return false;
}
i++;
j--;
}
return true;
}
int index = 0;
while (index < len / 2) {
stack.push(s.charAt(index));
index++;
}
if (len % 2 == 1)
index++;
return true;
}
In the discussion below, April and Frank use two pointers to solve this problem. This
solution looks really simple.
public class ValidPalindrome {
public static boolean isValidPalindrome(String s){
if(s==null||s.length()==0) return false;
s = s.replaceAll("[^a-zA-Z0-9]", "").toLowerCase();
System.out.println(s);
return true;
}
System.out.println(isValidPalindrome(str));
}
}
And then read line by line: "PAHNAPLSIIGYIR" Write the a method convert("PAYPALISHIRING",
3) which returns "PAHNAPLSIIGYIR".
81 | 531
27 ZigZag Conversion
}
}
return sb.toString();
}
Given two binary strings, return their sum (also a binary string).
For example, a = "11", b = "1", the return is "100".
int pa = a.length()-1;
int pb = b.length()-1;
int flag = 0;
StringBuilder sb = new StringBuilder();
while(pa >= 0 || pb >=0){
int va = 0;
int vb = 0;
if(flag == 1){
83 | 531
28 Add Binary
sb.append("1");
}
Very simple question. We just need a flag to mark the start of letters from the end. If
a letter starts and the next character is not a letter, return the length.
public int lengthOfLastWord(String s) {
if(s==null || s.length() == 0)
return 0;
int result = 0;
int len = s.length();
return result;
}
85 | 531
30 Triangle
Given a triangle, find the minimum path sum from top to bottom. Each step you may
move to adjacent numbers on the row below.
For example, given the following triangle
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
This solution gets wrong answer! I will try to make it work later.
public class Solution {
public int minimumTotal(ArrayList<ArrayList<Integer>> triangle) {
if (triangle.size() == 1) {
return Math.min(minTotal, triangle.get(0).get(0));
}
int a, b;
87 | 531
30 Triangle
}else{
a = temp[j] + triangle.get(i + 1).get(j);
b = temp[j] + triangle.get(i + 1).get(j + 1);
return minTotal;
}
}
return total[0];
}
Given an array of integers, find if the array contains any duplicates. Your function
should return true if any value appears at least twice in the array, and it should return
false if every element is distinct.
return false;
}
89 | 531
32 Contains Duplicate II
Given an array of integers and an integer k, return true if and only if there are two
distinct indices i and j in the array such that nums[i] = nums[j] and the difference
between i and j is at most k.
91 | 531
32 Contains Duplicate II
map.put(nums[i], i);
}
return false;
}
Given an array of integers, find out whether there are two distinct indices i and j in
the array such that the difference between nums[i] and nums[j] is at most t and the
difference between i and j is at most k.
set.add(c);
if (i >= k)
set.remove(nums[i - k]);
}
return false;
}
93 | 531
33 Contains Duplicate III
if (!subSet.isEmpty())
return true;
set.add((long) nums[j]);
if (j >= k) {
set.remove((long) nums[j - k]);
}
}
return false;
}
Given a sorted array, 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 in place with constant memory.
For example, given input array A = [1,1,2], your function should return length = 2,
and A is now [1,2].
34.1 Thoughts
The problem is pretty straightforward. It returns the length of array with unique
elements, but the original array need to be changed also. This problem should be
reviewed with Remove Duplicates from Sorted Array II.
34.2 Solution 1
int j = 0;
int i = 1;
return j + 1;
}
This method returns the number of unique elements, but does not change the orig-
inal array correctly. For example, if the input array is 1, 2, 2, 3, 3, the array will be
changed to 1, 2, 3, 3, 3. The correct result should be 1, 2, 3. Because array’s size can
95 | 531
34 Remove Duplicates from Sorted Array
not be changed once created, there is no way we can return the original array with
correct results.
34.3 Solution 2
int j = 0;
int i = 1;
return B;
}
34.4 Solution 3
If we only want to count the number of unique elements, the following method is
good enough.
// Count the number of unique elements
public static int countUnique(int[] A) {
int count = 0;
for (int i = 0; i < A.length - 1; i++) {
if (A[i] == A[i + 1]) {
count++;
}
}
return (A.length - count);
}
Follow up for "Remove Duplicates": What if duplicates are allowed at most twice?
For example, given sorted array A = [1,1,1,2,2,3], your function should return length
= 5, and A is now [1,1,2,2,3].
Given the method signature "public int removeDuplicates(int[] A)", it seems that we
should write a method that returns a integer and that’s it. After typing the following
solution:
public class Solution {
public int removeDuplicates(int[] A) {
if(A == null || A.length == 0)
return 0;
if(curr == pre){
if(!flag){
flag = true;
continue;
}else{
count++;
}
}else{
pre = curr;
flag = false;
}
}
99 | 531
35 Remove Duplicates from Sorted Array II
We can not change the given array’s size, so we only change the first k elements of the
array which has duplicates removed.
public class Solution {
public int removeDuplicates(int[] A) {
if (A == null || A.length == 0)
return 0;
if (curr == pre) {
if (!flag) {
flag = true;
A[o++] = curr;
continue;
} else {
count++;
}
} else {
pre = curr;
A[o++] = curr;
flag = false;
}
}
return prev + 1;
}
}
Given a string, find the length of the longest substring without repeating characters.
For example, the longest substring without repeating letters for "abcabcbb" is "abc",
which the length is 3. For "bbbbb" the longest substring is "b", with the length of 1.
The first solution is like the problem of "determine if a string has all unique characters"
in CC 150. We can use a flag array to track the existing characters for the longest
substring without repeating characters.
public int lengthOfLongestSubstring(String s) {
if(s==null)
return 0;
boolean[] flag = new boolean[256];
int result = 0;
int start = 0;
char[] arr = s.toCharArray();
103 | 531
36 Longest Substring Without Repeating Characters
return result;
}
This solution is from Tia. It is easier to understand than the first solution.
The basic idea is using a hash table to track existing characters and their posi-
tion. When a repeated character occurs, check from the previously repeated character.
However, the time complexity is higher - O(n3̂).
public static int lengthOfLongestSubstring(String s) {
if(s==null)
return 0;
char[] arr = s.toCharArray();
int pre = 0;
When loop hits the second "a", the HashMap contains the following:
a 0
b 1
c 2
d 3
The index i is set to 0 and incremented by 1, so the loop start from second element
again.
In this solution, a hashmap is used to track the unique elements in the map. When a
third character is added to the map, the left pointer needs to move right.
You can use "abac" to walk through this solution.
public int lengthOfLongestSubstringTwoDistinct(String s) {
int max=0;
HashMap<Character,Integer> map = new HashMap<Character, Integer>();
int start=0;
if(map.size()>2){
max = Math.max(max, i-start);
while(map.size()>2){
char t = s.charAt(start);
int count = map.get(t);
if(count>1){
map.put(t, count-1);
}else{
map.remove(t);
}
start++;
}
105 | 531
37 Longest Substring Which Contains 2 Unique Characters
}
}
return max;
}
Now if this question is extended to be "the longest substring that contains k unique
characters", what should we do?
if(map.size()>k){
max = Math.max(max, i-start);
while(map.size()>k){
char t = s.charAt(start);
int count = map.get(t);
if(count>1){
map.put(t, count-1);
}else{
map.remove(t);
}
start++;
}
}
}
return max;
}
Time is O(n).
You are given a string, s, and a list of words, words, that are all of the same length.
Find all starting indices of substring(s) in s that is a concatenation of each word in
words exactly once and without any intervening characters.
For example, given: s="barfoothefoobarman" & words=["foo", "bar"], return [0,9].
38.1 Analysis
This problem is similar (almost the same) to Longest Substring Which Contains 2
Unique Characters.
Since each word in the dictionary has the same length, each of them can be treated
as a single character.
//frequency of words
HashMap<String, Integer> map = new HashMap<String, Integer>();
for(String w: words){
if(map.containsKey(w)){
map.put(w, map.get(w)+1);
}else{
map.put(w, 1);
}
}
109 | 531
38 Substring with Concatenation of All Words
count++;
while(currentMap.get(sub)>map.get(sub)){
String left = s.substring(start, start+len);
currentMap.put(left, currentMap.get(left)-1);
count--;
start = start + len;
}
if(count==words.length){
result.add(start); //add to result
return result;
}
Given a string S and a string T, find the minimum window in S which will contain all
the characters in T in complexity O(n).
For example, S = "ADOBECODEBANC", T = "ABC", Minimum window is "BANC".
if(target.containsKey(c)){
if(map.containsKey(c)){
if(map.get(c)<target.get(c)){
count++;
}
map.put(c,map.get(c)+1);
}else{
map.put(c,1);
count++;
111 | 531
39 Minimum Window Substring
}
}
if(count == t.length()){
char sc = s.charAt(left);
while (!map.containsKey(sc) || map.get(sc) > target.get(sc)) {
if (map.containsKey(sc) && map.get(sc) > target.get(sc))
map.put(sc, map.get(sc) - 1);
left++;
sc = s.charAt(left);
}
return result;
}
This problem is pretty straightforward. We first split the string to words array, and
then iterate through the array and add each element to a new string. Note: String-
Builder should be used to avoid creating too many Strings. If the string is very long,
using String is not scalable since String is immutable and too many objects will be
created and garbage collected.
class Solution {
public String reverseWords(String s) {
if (s == null || s.length() == 0) {
return "";
}
113 | 531
41 Find Minimum in Rotated Sorted
Array
Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1
2 4 5 6 7 might become 4 5 6 7 0 1 2).
Find the minimum element.You may assume no duplicate exists in the array.
41.1 Analysis
This problem is a binary search and the key is breaking the array to two parts, so that
we only need to work on half of the array each time.
If we pick the middle element, we can compare the middle element with the leftmost
(or rightmost) element. If the middle element is less than leftmost, the left half should
be selected; if the middle element is greater than the leftmost (or rightmost), the right
half should be selected. Using recursion or iteration, this problem can be solved in
time log(n).
In addition, in any rotated sorted array, the rightmost element should be less than
the left-most element, otherwise, the sorted array is not rotated and we can simply
pick the leftmost element as the minimum.
// not rotated
if (num[left] < num[right]) {
return num[left];
115 | 531
41 Find Minimum in Rotated Sorted Array
// go right side
} else if (num[middle] > num[left]) {
return findMin(num, middle, right);
// go left side
} else {
return findMin(num, left, middle);
}
}
int left=0;
int right=nums.length-1;
//not rotated
if(nums[left]<nums[right])
return nums[left];
return nums[left];
}
42.1 Problem
Follow up for "Find Minimum in Rotated Sorted Array": What if duplicates are al-
lowed?
Would this affect the run-time complexity? How and why?
This is a follow-up problem of finding minimum element in rotated sorted array with-
out duplicate elements. We only need to add one more condition, which checks if
the left-most element and the right-most element are equal. If they are we can simply
drop one of them. In my solution below, I drop the left element whenever the left-most
equals to the right-most.
public int findMin(int[] num) {
return findMin(num, 0, num.length-1);
}
117 | 531
42 Find Minimum in Rotated Sorted Array II
}else{
return findMin(num, left, middle);
}
}
Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1
2 4 5 6 7 might become 4 5 6 7 0 1 2).
You are given a target value to search. If found in the array return its index, other-
wise return -1. You may assume no duplicate exists in the array.
public int binarySearch(int[] nums, int left, int right, int target){
if(left>right)
return -1;
if(target == nums[mid])
return mid;
119 | 531
43 Search in Rotated Sorted Array
int left = 0;
int right= nums.length-1;
while(left<=right){
int mid = left + (right-left)/2;
if(target==nums[mid])
return mid;
if(nums[left]<=nums[mid]){
if(nums[left]<=target&& target<nums[mid]){
right=mid-1;
}else{
left=mid+1;
}
}else{
if(nums[mid]<target&& target<=nums[right]){
left=mid+1;
}else{
right=mid-1;
}
}
}
return -1;
}
Follow up for "Search in Rotated Sorted Array": what if duplicates are allowed? Write
a function to determine if a given target is in the array.
while(left<=right){
int mid = (left+right)/2;
if(nums[mid]==target)
return true;
if(nums[left]<nums[mid]){
if(nums[left]<=target&& target<nums[mid]){
right=mid-1;
}else{
left=mid+1;
}
}else if(nums[left]>nums[mid]){
if(nums[mid]<target&&target<=nums[right]){
left=mid+1;
}else{
right=mid-1;
}
}else{
left++;
}
}
return false;
}
121 | 531
45 Min Stack
Design a stack that supports push, pop, top, and retrieving the minimum element in
constant time.
push(x) – Push element x onto stack. pop() – Removes the element on top of the
stack. top() – Get the top element. getMin() – Retrieve the minimum element in the
stack.
45.1 Analysis
UPDATED ON 6/17/2015
To make constant time of getMin(), we need to keep track of the minimum element
for each element in the stack.
Define a node class that holds element value, min value, and pointer to elements below
it.
class Node {
int value;
int min;
Node next;
Node(int x) {
value = x;
next = null;
min = x;
}
}
class MinStack {
Node head;
123 | 531
45 Min Stack
head = temp;
}
}
return head.value;
}
return head.min;
}
}
Given an array of size n, find the majority element. The majority element is the element
that appears more than b n/2 c times. (assume that the array is non-empty and the
majority element always exist in the array.)
We can sort the array first, which takes time of nlog(n). Then scan once to find the
longest consecutive substrings.
public class Solution {
public int majorityElement(int[] num) {
if(num.length==1){
return num[0];
}
Arrays.sort(num);
int prev=num[0];
int count=1;
for(int i=1; i<num.length; i++){
if(num[i] == prev){
count++;
if(count > num.length/2) return num[i];
}else{
count=1;
prev = num[i];
}
}
return 0;
}
}
Thanks to SK. His/her solution is much efficient and simpler. Since the majority al-
ways take more than a half space, the middle element is guaranteed to be the majority.
Sorting array takes nlog(n). So the time complexity of this solution is nlog(n). Cheers!
125 | 531
46 Majority Element
Arrays.sort(num);
return num[num.length / 2];
}
return result;
}
Given an integer array of size n, find all elements that appear more than b n/3 c times.
The algorithm should run in linear time and in O(1) space.
return result;
}
for(int i: nums){
127 | 531
47 Majority Element II
c1=c2=0;
for(int i: nums){
if(i==n1.intValue()){
c1++;
}else if(i==n2.intValue()){
c2++;
}
}
if(c1>nums.length/3)
result.add(n1);
if(c2>nums.length/3)
result.add(n2);
return result;
}
Given an array and a value, remove all instances of that value in place and return the
new length. (Note: The order of elements can be changed. It doesn’t matter what you
leave beyond the new length.)
j++;
}
return i;
}
129 | 531
49 Largest Rectangle in Histogram
Given n non-negative integers representing the histogram’s bar height where the width
of each bar is 1, find the area of largest rectangle in the histogram.
49.1 Analysis
The key to solve this problem is to maintain a stack to store bars’ indexes. The stack
only keeps the increasing bars.
131 | 531
49 Largest Rectangle in Histogram
int max = 0;
int i = 0;
while (!stack.isEmpty()) {
int p = stack.pop();
int h = height[p];
int w = stack.isEmpty() ? i : i - stack.peek() - 1;
max = Math.max(h * w, max);
}
return max;
}
50.1 Problem
Write a function to find the longest common prefix string amongst an array of strings.
50.2 Analysis
To solve this problem, we need to find the two loop conditions. One is the length of
the shortest string. The other is iteration over every element of the string array.
int minLen=Integer.MAX_VALUE;
for(String str: strs){
if(minLen > str.length())
minLen = str.length();
}
if(minLen == 0) return "";
if(strs[i].charAt(j) != prev){
return strs[i].substring(0, j);
}
}
}
return strs[0].substring(0,minLen);
}
133 | 531
51 Largest Number
Given a list of non negative integers, arrange them such that they form the largest
number.
For example, given [3, 30, 34, 5, 9], the largest formed number is 9534330. (Note:
The result may be very large, so you need to return a string instead of an integer.)
51.1 Analysis
This problem can be solve by simply sorting strings, not sorting integer. Define a
comparator to compare strings by concat() right-to-left or left-to-right.
}
});
return sb.toString();
}
135 | 531
52 Simplify Path
//stack.push(path.substring(0,1));
int start = 0;
for(int i=1; i<path.length(); i++){
if(path.charAt(i) == ’/’){
stack.push(path.substring(start, i));
start = i;
}else if(i==path.length()-1){
stack.push(path.substring(start));
}
}
if(top.equals("/.") || top.equals("/")){
//nothing
}else if(top.equals("/..")){
back++;
}else{
if(back > 0){
137 | 531
52 Simplify Path
back--;
}else{
result.push(top);
}
}
}
return sb.toString();
}
53.1 Problem
Compare two version numbers version1 and version2. If version1 >version2 return 1,
if version1 <version2 return -1, otherwise return 0. You may assume that the version
strings are non-empty and contain only digits and the . character. The . character does
not represent a decimal point and is used to separate number sequences. Here is an
example of version numbers ordering:
0.1 < 1.1 < 1.2 < 13.37
The tricky part of the problem is to handle cases like 1.0 and 1. They should be equal.
public int compareVersion(String version1, String version2) {
String[] arr1 = version1.split("\\.");
String[] arr2 = version2.split("\\.");
int i=0;
while(i<arr1.length || i<arr2.length){
if(i<arr1.length && i<arr2.length){
if(Integer.parseInt(arr1[i]) < Integer.parseInt(arr2[i])){
return -1;
}else if(Integer.parseInt(arr1[i]) > Integer.parseInt(arr2[i])){
return 1;
}
} else if(i<arr1.length){
if(Integer.parseInt(arr1[i]) != 0){
return 1;
}
} else if(i<arr2.length){
if(Integer.parseInt(arr2[i]) != 0){
return -1;
}
}
i++;
}
return 0;
139 | 531
53 Compare Version Numbers
There are N gas stations along a circular route, where the amount of gas at station i is
gas[i].
You have a car with an unlimited gas tank and it costs cost[i] of gas to travel from
station i to its next station (i+1). You begin the journey with an empty tank at one of
the gas stations.
Return the starting gas station’s index if you can travel around the circuit once,
otherwise return -1.
54.1 Analysis
To solve this problem, we need to understand and use the following 2 facts: 1) if the
sum of gas >= the sum of cost, then the circle can be completed. 2) if A can not reach
C in a the sequence of A–>B–>C, then B can not make it either.
Proof of fact 2:
If gas[A] < cost[A], then A can not even reach B.
So to reach C from A, gas[A] must >= cost[A].
Given that A can not reach C, we have gas[A] + gas[B] < cost[A] + cost[B],
and gas[A] >= cost[A],
Therefore, gas[B] < cost[B], i.e., B can not reach C.
141 | 531
54 Gas Station
Given numRows, generate the first numRows of Pascal’s triangle. For example, given
numRows = 5, the result should be:
[
[1],
[1,1],
[1,2,1],
[1,3,3,1],
[1,4,6,4,1]
]
cur.add(1); //first
for (int j = 0; j < pre.size() - 1; j++) {
cur.add(pre.get(j) + pre.get(j + 1)); //middle
}
cur.add(1);//last
result.add(cur);
pre = cur;
}
return result;
}
143 | 531
56 Pascal’s Triangle II
Given an index k, return the kth row of the Pascal’s triangle. For example, when k =
3, the row is [1,3,3,1].
56.1 Analysis
This problem is related to Pascal’s Triangle which gets all rows of Pascal’s triangle. In
this problem, only one row is required to return.
if (rowIndex < 0)
return result;
result.add(1);
for (int i = 1; i <= rowIndex; i++) {
for (int j = result.size() - 2; j >= 0; j--) {
result.set(j + 1, result.get(j) + result.get(j + 1));
}
result.add(1);
}
return result;
}
145 | 531
57 Container With Most Water
57.1 Problem
Given n non-negative integers a1, a2, ..., an, where each represents a point at coordi-
nate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai)
and (i, 0). Find two lines, which together with x-axis forms a container, such that the
container contains the most water.
57.2 Analysis
Initially we can assume the result is 0. Then we scan from both sides. If leftHeight
<rightHeight, move right and find a value that is greater than leftHeight. Similarily,
if leftHeight >rightHeight, move left and find a value that is greater than rightHeight.
Additionally, keep tracking the max value.
int max = 0;
int left = 0;
int right = height.length - 1;
147 | 531
57 Container With Most Water
return max;
}
There are N children standing in a line. Each child is assigned a rating value. You are
giving candies to these children subjected to the following requirements:
1. Each child must have at least one candy. 2. Children with a higher rating get
more candies than their neighbors.
What is the minimum candies you must give?
58.1 Analysis
149 | 531
58 Candy
return result;
}
Given n non-negative integers representing an elevation map where the width of each
bar is 1, compute how much water it is able to trap after raining.
For example, given [0,1,0,2,1,0,1,3,2,1,2,1], return 6.
59.1 Analysis
This problem is similar to Candy. It can be solve by scanning from both sides and
then get the total.
if(height==null || height.length<=2)
return result;
151 | 531
59 Trapping Rain Water
right[i]=height[i];
max = height[i];
}
}
//calculate totoal
for(int i=0; i<height.length; i++){
result+= Math.min(left[i],right[i])-height[i];
}
return result;
}
60.1 Problem
The count-and-say sequence is the sequence of integers beginning as follows: 1, 11, 21,
1211, 111221, ...
1 is read off as "one 1" or 11.
11 is read off as "two 1s" or 21.
21 is read off as "one 2, then one 1" or 1211.
The problem can be solved by using a simple iteration. See Java solution below:
public String countAndSay(int n) {
if (n <= 0)
return null;
while (i < n) {
StringBuilder sb = new StringBuilder();
int count = 1;
for (int j = 1; j < result.length(); j++) {
if (result.charAt(j) == result.charAt(j - 1)) {
count++;
} else {
sb.append(count);
sb.append(result.charAt(j - 1));
count = 1;
}
}
sb.append(count);
sb.append(result.charAt(result.length() - 1));
result = sb.toString();
i++;
}
153 | 531
60 Count and Say
return result;
}
Given a sorted array of integers, 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]. For example, given [5, 7, 7, 8, 8, 10] and
target value 8, return [3, 4].
61.1 Analysis
Based on the requirement of O(log n), this is a binary search problem apparently.
return arr;
}
public void binarySearch(int[] nums, int left, int right, int target, int[]
arr){
if(right<left)
return;
155 | 531
61 Search for a Range
if(nums[mid]<target){
binarySearch(nums, mid+1, right, target, arr);
}else if(nums[mid]>target){
binarySearch(nums, left, mid-1, target, arr);
}else{
arr[0]=mid;
arr[1]=mid;
62.1 Analysis
This problem can be solved by using a stack. We keep pushing element to the stack,
when ’)" is met, calculate the expression up to the first "(".
if (i == arr.length - 1) {
stack.push(sb.toString());
}
} else {
if (sb.length() > 0) {
stack.push(sb.toString());
sb = new StringBuilder();
}
if (arr[i] != ’)’) {
stack.push(new String(new char[] { arr[i] }));
157 | 531
62 Basic Calculator
} else {
// when meet ’)’, pop and calculate
ArrayList<String> t = new ArrayList<String>();
while (!stack.isEmpty()) {
String top = stack.pop();
if (top.equals("(")) {
break;
} else {
t.add(0, top);
}
}
int temp = 0;
if (t.size() == 1) {
temp = Integer.valueOf(t.get(0));
} else {
for (int j = t.size() - 1; j > 0; j = j - 2) {
if (t.get(j - 1).equals("-")) {
temp += 0 - Integer.valueOf(t.get(j));
} else {
temp += Integer.valueOf(t.get(j));
}
}
temp += Integer.valueOf(t.get(0));
}
stack.push(String.valueOf(temp));
}
}
}
int temp = 0;
for (int i = t.size() - 1; i > 0; i = i - 2) {
if (t.get(i - 1).equals("-")) {
temp += 0 - Integer.valueOf(t.get(i));
} else {
temp += Integer.valueOf(t.get(i));
}
}
temp += Integer.valueOf(t.get(0));
return temp;
}
Given an array of strings, return all groups of strings that are anagrams.
63.1 Analysis
An anagram is a type of word play, the result of rearranging the letters of a word or
phrase to produce a new word or phrase, using all the original letters exactly once; for
example Torchwood can be rearranged into Doctor Who.
If two strings are anagram to each other, their sorted sequence is the same.
Updated on 5/1/2016.
if(map.containsKey(ns)){
map.get(ns).add(str);
}else{
ArrayList<String> al = new ArrayList<String>();
al.add(str);
map.put(ns, al);
}
}
result.addAll(map.values());
return result;
}
159 | 531
63 Group Anagrams
If average length of verbs is m and words array length is n, then the time is O(n*m*log(m)).
64.1 Analysis
We can solve this problem by using one of the methods which is used to solve the
longest palindrome substring problem.
Specifically, we can start from the center and scan two sides. If read the left bound-
ary, then the shortest palindrome is identified.
return result;
}
161 | 531
64 Shortest Palindrome
return sb.append(s).toString();
}
Find the total area covered by two rectilinear rectangles in a 2D plane. Each rectangle
is defined by its bottom left corner and top right corner coordinates.
65.1 Analysis
This problem can be converted as a overlap internal problem. On the x-axis, there are
(A,C) and (E,G); on the y-axis, there are (F,H) and (B,D). If they do not have overlap,
the total area is the sum of 2 rectangle areas. If they have overlap, the total area should
minus the overlap area.
public int computeArea(int A, int B, int C, int D, int E, int F, int G, int
H) {
if(C<E||G<A )
return (G-E)*(H-F) + (C-A)*(D-B);
if(D<F || H<B)
return (G-E)*(H-F) + (C-A)*(D-B);
163 | 531
66 Summary Ranges
Given a sorted integer array without duplicates, return the summary of its ranges for
consecutive numbers.
For example, given [0,1,2,4,5,7], return ["0->2","4->5","7"].
66.1 Analysis
if(nums.length==1){
result.add(nums[0]+"");
}
if(i==nums.length-1){
result.add(nums[i]+"");
}
first = nums[i];
}
165 | 531
66 Summary Ranges
pre = nums[i];
}
return result;
}
67.1 Analysis
This problem can be converted to be finding if there is a sequence such that the_smallest_so_far
<the_second_smallest_so_far <current. We use x, y and z to denote the 3 number re-
spectively.
if (x >= z) {
x = z;// update x to be a smaller value
} else if (y >= z) {
y = z; // update y to be a smaller value
} else {
return true;
}
}
return false;
}
167 | 531
68 Get Target Number Using Number List
and Arithmetic Operations
Given a list of numbers and a target number, write a program to determine whether
the target number can be calculated by applying "+-*/" operations to the number list?
You can assume () is automatically added when necessary.
For example, given 1,2,3,4 and 21, return true. Because (1+2)*(3+4)=21
68.1 Analysis
This is a partition problem which can be solved by using depth first search.
int i = 0;
int j = list.size() - 1;
return false;
}
169 | 531
68 Get Target Number Using Number List and Arithmetic Operations
return result;
}
return result;
}
Write a function that takes a string as input and reverse only the vowels of a string.
this is a simple problem which can be solved by using two pointers scanning from
beginning and end of the array.
public String reverseVowels(String s) {
ArrayList<Character> vowList = new ArrayList<Character>();
vowList.add(’a’);
vowList.add(’e’);
vowList.add(’i’);
vowList.add(’o’);
vowList.add(’u’);
vowList.add(’A’);
vowList.add(’E’);
vowList.add(’I’);
vowList.add(’O’);
vowList.add(’U’);
int i=0;
int j=s.length()-1;
while(i<j){
if(!vowList.contains(arr[i])){
i++;
continue;
}
if(!vowList.contains(arr[j])){
j--;
continue;
}
char t = arr[i];
arr[i]=arr[j];
arr[j]=t;
i++;
j--;
171 | 531
69 Reverse Vowels of a String
You are playing the following Flip Game with your friend: Given a string that con-
tains only these two characters: + and -, you and your friend take turns to flip two
consecutive "++" into "–". The game ends when a person can no longer make a move
and therefore the other person will be the winner.
Write a function to compute all possible states of the string after one valid move.
if(s==null)
return result;
return result;
}
173 | 531
71 Flip Game II
You are playing the following Flip Game with your friend: Given a string that con-
tains only these two characters: + and -, you and your friend take turns to flip two
consecutive "++" into "–". The game ends when a person can no longer make a move
and therefore the other person will be the winner.
Write a function to determine if the starting player can guarantee a win.
For example, given s = "++++", return true. The starting player can guarantee a win
by flipping the middle "++" to become "+–+".
return canWinHelper(s.toCharArray());
}
arr[i]=’+’;
arr[i+1]=’+’;
//if there is a flip which makes the other player lose, the first
play wins
if(!win){
return true;
}
}
}
return false;
}
175 | 531
71 Flip Game II
Roughly, the time is n*n*...n, which is O(nn̂). The reason is each recursion takes O(n)
and there are totally n recursions.
Given an array nums, write a function to move all 0’s to the end of it while maintaining
the relative order of the non-zero elements.
For example, given nums = [0, 1, 0, 3, 12], after calling your function, nums should
be [1, 3, 12, 0, 0].
177 | 531
73 Valid Anagram
return true;
}
If the inputs contain unicode characters, an array with length of 26 is not enough.
public boolean isAnagram(String s, String t) {
if(s.length()!=t.length())
179 | 531
73 Valid Anagram
return false;
if(map.size()>0)
return false;
return true;
}
Given a string, we can "shift" each of its letter to its successive letter, for example: "abc"
->"bcd". We can keep "shifting" which forms the sequence: "abc" ->"bcd" ->... ->"xyz".
Given a list of strings which contains only lowercase alphabets, group all strings
that belong to the same shifting sequence, return:
[
["abc","bcd","xyz"],
["az","ba"],
["acef"],
["a","z"]
]
for(String s: strings){
char[] arr = s.toCharArray();
if(arr.length>0){
int diff = arr[0]-’a’;
for(int i=0; i<arr.length; i++){
if(arr[i]-diff<’a’){
arr[i] = (char) (arr[i]-diff+26);
}else{
arr[i] = (char) (arr[i]-diff);
}
}
}
181 | 531
74 Group Shifted Strings
}
}
result.addAll(map.values());
return result;
}
We can solve this problem by using a counter, and then sort the counter by value.
public class Solution {
public List<Integer> topKFrequent(int[] nums, int k) {
List<Integer> result = new ArrayList<Integer>();
for(int i: nums){
if(counter.containsKey(i)){
counter.put(i, counter.get(i)+1);
}else{
counter.put(i, 1);
}
}
int i=0;
for(Map.Entry<Integer, Integer> entry: sortedMap.entrySet()){
result.add(entry.getKey());
i++;
if(i==k)
break;
}
return result;
}
}
183 | 531
75 Top K Frequent Elements
if(diff==0){
return 1;
}else{
return diff;
}
}
}
A peak element is an element that is greater than its neighbors. Given an input array
where num[i] 6= num[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 num[-1] = num[n] = -∞. For example, in array [1, 2, 3, 1], 3 is
a peak element and your function should return the index number 2.
76.1 Thoughts
This is a very simple problem. We can scan the array and find any element that is
greater can its previous and next. The first and last element are handled separately.
if(curr > prev && curr > next && curr > max){
index = i;
max = curr;
}
}
return index;
}
}
185 | 531
77 Word Pattern
Given a pattern and a string str, find if str follows the same pattern. Here follow means
a full match, such that there is a bijection between a letter in pattern and a non-empty
word in str.
if(pattern.length()!=arr.length)
return false;
if(map.containsKey(c)){
if(!map.get(c).equals(s))
return false;
}else{
if(map.containsValue(s))
return false;
map.put(c, s);
}
}
return true;
}
187 | 531
78 Set Matrix Zeroes
78.1 Analysis
This problem should be solved in place, i.e., no other array should be used. We can
use the first column and the first row to track if a row/column should be set to 0.
Since we used the first row and first column to mark the zero row/column, the
original values are changed.
Step 1: First row contains zero = true; First column contains zero = false;
189 | 531
78 Set Matrix Zeroes
if(firstRowZero){
for(int i=0; i<matrix[0].length; i++)
matrix[0][i] = 0;
}
}
}
If more than one row and column left, it can form a circle and we process the circle.
Otherwise, if only one row or column left, we process that column or row ONLY.
public class Solution {
public ArrayList<Integer> spiralOrder(int[][] matrix) {
ArrayList<Integer> result = new ArrayList<Integer>();
int m = matrix.length;
int n = matrix[0].length;
int x=0;
int y=0;
193 | 531
79 Spiral Matrix
break;
}
//left - move up
for(int i=0;i<m-1;i++){
result.add(matrix[x--][y]);
}
x++;
y++;
m=m-2;
n=n-2;
}
return result;
}
}
We can also recursively solve this problem. The solution’s performance is not better
than Solution or as clear as Solution 1. Therefore, Solution 1 should be preferred.
public class Solution {
public ArrayList<Integer> spiralOrder(int[][] matrix) {
if(matrix==null || matrix.length==0)
return new ArrayList<Integer>();
return spiralOrder(matrix,0,0,matrix.length,matrix[0].length);
}
if(m<=0||n<=0)
return result;
//left - move up
if(n>1){
for(int i=0;i<m-1;i++){
result.add(matrix[x--][y]);
}
}
if(m==1||n==1)
result.addAll(spiralOrder(matrix, x, y, 1, 1));
else
result.addAll(spiralOrder(matrix, x+1, y+1, m-2, n-2));
return result;
}
}
Given an integer n, generate a square matrix filled with elements from 1 to n2 in spiral
order. For example, given n = 4,
[
[1, 2, 3, 4],
[12, 13, 14, 5],
[11, 16, 15, 6],
[10, 9, 8, 7]
]
int x=0;
int y=0;
int step = 0;
for(int i=0;i<total;){
while(y+step<n){
i++;
result[x][y]=i;
y++;
}
y--;
x++;
while(x+step<n){
i++;
result[x][y]=i;
x++;
}
x--;
y--;
while(y>=0+step){
i++;
197 | 531
80 Spiral Matrix II
result[x][y]=i;
y--;
}
y++;
x--;
step++;
while(x>=0+step){
i++;
result[x][y]=i;
x--;
}
x++;
y++;
}
return result;
}
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix
has properties:
1) Integers in each row are sorted from left to right. 2) The first integer of each row
is greater than the last integer of the previous row.
For example, consider the following matrix:
[
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
int m = matrix.length;
int n = matrix[0].length;
int start = 0;
int end = m*n-1;
while(start<=end){
int mid=(start+end)/2;
int midX=mid/n;
int midY=mid%n;
if(matrix[midX][midY]==target)
return true;
199 | 531
81 Search a 2D Matrix
if(matrix[midX][midY]<target){
start=mid+1;
}else{
end=mid-1;
}
}
return false;
}
}
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix
has the following properties:
Integers in each row are sorted in ascending from left to right. Integers in each
column are sorted in ascending from top to bottom.
For example, consider the following matrix:
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
In a naive approach, we can use the matrix boundary to reduce the search space. Here
is a simple recursive implementation.
public boolean searchMatrix(int[][] matrix, int target) {
int i1=0;
int i2=matrix.length-1;
int j1=0;
int j2=matrix[0].length-1;
public boolean helper(int[][] matrix, int i1, int i2, int j1, int j2, int
target){
if(i1>i2||j1>j2)
return false;
for(int j=j1;j<=j2;j++){
if(target < matrix[i1][j]){
return helper(matrix, i1, i2, j1, j-1, target);
}else if(target == matrix[i1][j]){
return true;
201 | 531
82 Search a 2D Matrix II
}
}
for(int i=i1;i<=i2;i++){
if(target < matrix[i][j1]){
return helper(matrix, i1, i-1, j1, j2, target);
}else if(target == matrix[i][j1]){
return true;
}
}
for(int j=j1;j<=j2;j++){
if(target > matrix[i2][j]){
return helper(matrix, i1, i2, j+1, j2, target);
}else if(target == matrix[i2][j]){
return true;
}
}
for(int i=i1;i<=i2;i++){
if(target > matrix[i][j2]){
return helper(matrix, i1, i+1, j1, j2, target);
}else if(target == matrix[i][j2]){
return true;
}
}
return false;
}
int i=m;
int j=0;
}
}
return false;
}
In the following solution, a new 2-dimension array is created to store the rotated
matrix, and the result is assigned to the matrix at the end. This is WRONG! Why?
public class Solution {
public void rotate(int[][] matrix) {
if(matrix == null || matrix.length==0)
return ;
int m = matrix.length;
matrix = result;
}
}
The problem is that Java is pass by value not by refrence! "matrix" is just a reference
to a 2-dimension array. If "matrix" is assigned to a new 2-dimension array in the
method, the original array does not change. Therefore, there should be another loop
to assign each element to the array referenced by "matrix". Check out "Java pass by
value."
public class Solution {
public void rotate(int[][] matrix) {
if(matrix == null || matrix.length==0)
return ;
int m = matrix.length;
205 | 531
83 Rotate Image
By using the relation "matrix[i][j] = matrix[n-1-j][i]", we can loop through the matrix.
public void rotate(int[][] matrix) {
int n = matrix.length;
for (int i = 0; i < n / 2; i++) {
for (int j = 0; j < Math.ceil(((double) n) / 2.); j++) {
int temp = matrix[i][j];
matrix[i][j] = matrix[n-1-j][i];
matrix[n-1-j][i] = matrix[n-1-i][n-1-j];
matrix[n-1-i][n-1-j] = matrix[j][n-1-i];
matrix[j][n-1-i] = temp;
}
}
}
Determine if a Sudoku is valid. The Sudoku board could be partially filled, where
empty cells are filled with the character ’.’.
207 | 531
84 Valid Sudoku
if (board[i][j] != ’.’) {
if (m[(int) (board[i][j] - ’1’)]) {
return false;
}
m[(int) (board[i][j] - ’1’)] = true;
}
}
}
return true;
}
Given a m x n grid filled with non-negative numbers, find a path from top left to
bottom right which minimizes the sum of all numbers along its path.
A native solution would be depth-first search. It’s time is too expensive and fails the
online judgement.
public int minPathSum(int[][] grid) {
return dfs(0,0,grid);
}
if(i<grid.length-1){
return grid[i][j] + dfs(i+1, j, grid);
}
if(j<grid[0].length-1){
return grid[i][j] + dfs(i, j+1, grid);
}
return 0;
}
209 | 531
85 Minimum Path Sum
int m = grid.length;
int n = grid[0].length;
return dp[m-1][n-1];
}
A robot is located at the top-left corner of a m x n grid. It can only move either down
or right at any point in time. The robot is trying to reach the bottom-right corner of
the grid.
How many possible unique paths are there?
if(i<m-1){
return dfs(i+1,j,m,n);
}
if(j<n-1){
return dfs(i,j+1,m,n);
}
return 0;
}
211 | 531
86 Unique Paths
//left column
for(int i=0; i<m; i++){
dp[i][0] = 1;
}
//top row
for(int j=0; j<n; j++){
dp[0][j] = 1;
}
return dp[m-1][n-1];
}
int m = obstacleGrid.length;
int n = obstacleGrid[0].length;
if(obstacleGrid[0][0]==1||obstacleGrid[m-1][n-1]==1)
return 0;
//left column
for(int i=1; i<m; i++){
if(obstacleGrid[i][0]==1){
dp[i][0] = 0;
}else{
dp[i][0] = dp[i-1][0];
}
}
//top row
213 | 531
87 Unique Paths II
}
}
return dp[m-1][n-1];
}
Given a 2-d grid map of ’1’s (land) and ’0’s (water), count the number of islands. An
island is surrounded by water and is formed by connecting adjacent lands horizontally
or vertically. You may assume all four edges of the grid are all surrounded by water.
Example 1:
11110
11010
11000
00000
Answer: 1
Example 2:
11000
11000
00100
00011
Answer: 3
The basic idea of the following solution is merging adjacent lands, and the merging
should be done recursively.
public int numIslands(char[][] grid) {
if(grid==null||grid.length==0||grid[0].length==0)
return 0;
int m=grid.length;
int n=grid[0].length;
int count=0;
for(int i=0;i<m; i++){
for(int j=0;j<n; j++){
if(grid[i][j]==’1’){
count++;
merge(grid, i, j);
}
}
}
215 | 531
88 Number of Islands
return count;
}
if(grid[i][j]==’1’){
grid[i][j]=’0’;
merge(grid, i-1,j);
merge(grid, i+1,j);
merge(grid, i,j-1);
merge(grid, i,j+1);
}
}
A 2d grid map of m rows and n columns is initially filled with water. We may perform
an addLand operation which turns the water at position (row, col) into a land. Given a
list of positions to operate, count the number of islands after each addLand operation.
An island is surrounded by water and is formed by connecting adjacent lands hori-
zontally or vertically. You may assume all four edges of the grid are all surrounded by
water.
int[] p = positions[k];
int index = p[0]*n+p[1];
rootArray[index]=index;//set root to be itself for each node
for(int r=0;r<4;r++){
int i=p[0]+directions[r][0];
int j=p[1]+directions[r][1];
if(i>=0&&j>=0&&i<m&&j<n&&rootArray[i*n+j]!=-1){
//get neighbor’s root
int thisRoot = getRoot(rootArray, i*n+j);
if(thisRoot!=index){
rootArray[thisRoot]=index;//set previous root’s root
count--;
}
}
}
217 | 531
89 Number of Islands II
result.add(count);
}
return result;
}
Given a 2D board containing ’X’ and ’O’, capture all regions surrounded by ’X’. A
region is captured by flipping all ’O’s into ’X’s in that surrounded region.
For example,
X X X X
X O O X
X X O X
X O X X
90.1 Analysis
This problem is similar to Number of Islands. In this problem, only the cells on the
boarders can not be surrounded. So we can first merge those O’s on the boarders like
in Number of Islands and replace O’s with ’#’, and then scan the board and replace all
O’s left (if any).
int m = board.length;
int n = board[0].length;
if(board[i][n-1] == ’O’){
219 | 531
90 Surrounded Regions
merge(board, i,n-1);
}
}
if(board[m-1][j] == ’O’){
merge(board, m-1,j);
}
}
if(board[i][j] != ’O’)
return;
board[i][j] = ’#’;
int m = board.length;
int n = board[0].length;
if (board[i][n - 1] == ’O’) {
bfs(board, i, n - 1);
}
}
while (!queue.isEmpty()) {
int cur = queue.poll();
int x = cur / n;
int y = cur % n;
fillCell(board, x - 1, y);
fillCell(board, x + 1, y);
fillCell(board, x, y - 1);
fillCell(board, x, y + 1);
}
}
// add current cell is queue & then process its neighbors in bfs
queue.offer(i * n + j);
board[i][j] = ’#’;
}
}
Given a 2D binary matrix filled with 0’s and 1’s, find the largest rectangle containing
all ones and return its area.
91.1 Analysis
int maxArea = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (matrix[i][j] == ’0’) {
height[i][j] = 0;
} else {
height[i][j] = i == 0 ? 1 : height[i - 1][j] + 1;
}
}
}
return maxArea;
}
int i = 0;
int max = 0;
223 | 531
91 Maximal Rectangle
return max;
}
Given a 2D binary matrix filled with 0’s and 1’s, find the largest square containing all
1’s and return its area.
For example, given the following matrix:
1101
1101
1111
Return 4.
92.1 Analysis
This problem can be solved by dynamic programming. The changing condition is:
t[i][j] = min(t[i][j-1], t[i-1][j], t[i-1][j-1]) + 1. It means the square formed before this
point.
int m = matrix.length;
int n = matrix[0].length;
//top row
for (int i = 0; i < m; i++) {
t[i][0] = Character.getNumericValue(matrix[i][0]);
}
//left column
for (int j = 0; j < n; j++) {
t[0][j] = Character.getNumericValue(matrix[0][j]);
}
//cells inside
for (int i = 1; i < m; i++) {
225 | 531
92 Maximal Square
int max = 0;
//get maximal length
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (t[i][j] > max) {
max = t[i][j];
}
}
}
Given a 2D board and a word, find if the word exists in the grid.
The word can be constructed from letters of sequentially adjacent cell, where "ad-
jacent" cells are those horizontally or vertically neighboring. The same letter cell may
not be used more than once.
For example, given board =
[
["ABCE"],
["SFCS"],
["ADEE"]
]
word = "ABCCED", ->returns true, word = "SEE", ->returns true, word = "ABCB",
->returns false.
93.1 Analysis
return result;
}
public boolean dfs(char[][] board, String word, int i, int j, int k){
int m = board.length;
227 | 531
93 Word Search
int n = board[0].length;
if(board[i][j] == word.charAt(k)){
char temp = board[i][j];
board[i][j]=’#’;
if(k==word.length()-1){
return true;
}else if(dfs(board, word, i-1, j, k+1)
||dfs(board, word, i+1, j, k+1)
||dfs(board, word, i, j-1, k+1)
||dfs(board, word, i, j+1, k+1)){
return true;
}
board[i][j]=temp;
}
return false;
}
Given a 2D board and a list of words from the dictionary, find all words in the board.
Each word must be constructed from letters of sequentially adjacent cell, where
"adjacent" cells are those horizontally or vertically neighboring. The same letter cell
may not be used more than once in a word.
For example, given words = ["oath","pea","eat","rain"] and board =
[
[’o’,’a’,’a’,’n’],
[’e’,’t’,’a’,’e’],
[’i’,’h’,’k’,’r’],
[’i’,’f’,’l’,’v’]
]
Return ["eat","oath"].
Similar to Word Search, this problem can be solved by DFS. However, this solution
exceeds time limit.
public List<String> findWords(char[][] board, String[] words) {
ArrayList<String> result = new ArrayList<String>();
int m = board.length;
int n = board[0].length;
229 | 531
94 Word Search II
result.add(word);
}
}
return result;
}
if (board[i][j] == word.charAt(k)) {
char temp = board[i][j];
board[i][j] = ’#’;
if (k == word.length() - 1) {
return true;
} else if (dfs(board, word, i - 1, j, k + 1)
|| dfs(board, word, i + 1, j, k + 1)
|| dfs(board, word, i, j - 1, k + 1)
|| dfs(board, word, i, j + 1, k + 1)) {
board[i][j] = temp;
return true;
}
} else {
return false;
}
return false;
}
If the current candidate does not exist in all words’ prefix, we can stop backtracking
immediately. This can be done by using a trie structure.
public class Solution {
Set<String> result = new HashSet<String>();
int m=board.length;
int n=board[0].length;
if(i<0 || j<0||i>=m||j>=n){
return;
}
if(visited[i][j])
return;
if(!trie.startsWith(str))
return;
if(trie.search(str)){
result.add(str);
}
visited[i][j]=true;
dfs(board, visited, str, i-1, j, trie);
dfs(board, visited, str, i+1, j, trie);
dfs(board, visited, str, i, j-1, trie);
dfs(board, visited, str, i, j+1, trie);
visited[i][j]=false;
}
}
//Trie Node
class TrieNode{
public TrieNode[] children = new TrieNode[26];
public String item = "";
}
//Trie
class Trie{
public TrieNode root = new TrieNode();
Given a positive integer n, break it into the sum of at least two positive integers and
maximize the product of those integers. Return the maximum product you can get.
For example, given n = 2, return 1 (2 = 1 + 1); given n = 10, return 36 (10 = 3 + 3 +
4).
Let dp[i] to be the max production value for breaking the number i. Since dp[i+j] can
be i*j, dp[i+j] = max(max(dp[i], i) * max(dp[j], j)), dp[i+j]).
public int integerBreak(int n) {
int[] dp = new int[n+1];
return dp[n];
}
If we see the breaking result for some numbers, we can see repeated pattern like the
following:
2 -> 1*1
3 -> 1*2
4 -> 2*2
5 -> 3*2
6 -> 3*3
7 -> 3*4
8 -> 3*3*2
9 -> 3*3*3
10 -> 3*3*4
11 -> 3*3*3*2
233 | 531
95 Integer Break
We only need to find how many 3’s we can get when n>4. If n
public int integerBreak(int n) {
if(n==2) return 1;
if(n==3) return 2;
if(n==4) return 4;
int result=1;
if(n%3==0){
int m = n/3;
result = (int) Math.pow(3, m);
}else if(n%3==2){
int m=n/3;
result = (int) Math.pow(3, m) * 2;
}else if(n%3==1){
int m=(n-4)/3;
result = (int) Math.pow(3, m) *4;
}
return result;
}
Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined
by its upper left corner (row1, col1) and lower right corner (row2, col2).
96.1 Analysis
Since the assumption is that there are many calls to sumRegion method, we should
use some extra space to store the intermediate results. Here we define an array sum[][]
which stores the sum value from (0,0) to the current cell.
int m = matrix.length;
int n = matrix[0].length;
sum = new int[m][n];
}
}
}
public int sumRegion(int row1, int col1, int row2, int col2) {
if(this.sum==null)
235 | 531
96 Range Sum Query 2D Immutable
return 0;
int bottomLeftX=row2;
int bottomLeftY= col1;
int result=0;
}else if(col1==0){
result = sum[row2][col2]
-sum[topRightX-1][topRightY];
}else{
result = sum[row2][col2]
-sum[topRightX-1][topRightY]
-sum[bottomLeftX][bottomLeftY-1]
+sum[row1-1][col1-1];
}
return result;
}
}
Given an integer matrix, find the length of the longest increasing path.
From each cell, you can either move to four directions: left, right, up or down. You
may NOT move diagonally or move outside of the boundary
return longest;
}
237 | 531
97 Longest Increasing Path in a Matrix
}
}
return longest;
}
if(x>=0&&y>=0&&x<matrix.length&&y<matrix[0].length&&matrix[x][y]>matrix[i][j]){
mem[i][j]=Math.max(mem[i][j], dfs(matrix, x, y, mem));
}
}
return ++mem[i][j];
}
}
@SuppressWarnings("unchecked")
public Stack(int cap) {
this.CAP = cap;
this.arr = (E[]) new Object[cap];
}
public E pop() {
if(this.size == 0){
return null;
}
this.size--;
E result = this.arr[top];
this.arr[top] = null;//prevent memory leaking
this.top--;
return result;
}
239 | 531
98 Implement a Stack Using an Array in Java
this.size++;
this.arr[++top] = e;
return false;
}
sb.setLength(sb.length()-2);
return sb.toString();
}
System.out.println(stack);
stack.pop();
System.out.println(stack);
stack.pop();
System.out.println(stack);
}
}
Output:
hello, world
hello
null
It turns out I don’t need to improve anything. There are some naming differences but
overall my method is ok.
This example occurs twice in "Effective Java". In the first place, the stack example is
used to illustrate memory leak. In the second place, the example is used to illustrate
when we can suppress unchecked warnings.
Do you wonder how to implement a queue by using an array?
You are given two linked lists representing two non-negative numbers. The digits are
stored in reverse order and each of their nodes contain a single digit. Add the two
numbers and return it as a linked list.
Input: (2 ->4 ->3) + (5 ->6 ->4) Output: 7 ->0 ->8
if(p2 != null){
carry += p2.val;
p2 = p2.next;
}
if(carry==1)
p3.next=new ListNode(1);
return newHead.next;
}
}
What if the digits are stored in regular order instead of reversed order?
Answer: We can simple reverse the list, calculate the result, and reverse the result.
243 | 531
100 Reorder List
Given a singly linked list L: L0→L1→ ... →Ln-1→Ln, reorder it to: L0→Ln→L1→Ln-
1→L2→Ln-2→...
For example, given 1,2,3,4, reorder it to 1,4,2,3. You must do this in-place without
altering the nodes’ values.
100.1 Analysis
• Break list in the middle to two lists (use fast & slow pointers)
• Reverse the order of the second list
• Merge two list back together
ListNode(int x) {
val = x;
next = null;
}
}
245 | 531
100 Reorder List
n3.next = n4;
printList(n1);
reorderList(n1);
printList(n1);
}
//use a fast and slow pointer to break the link to two parts.
while (fast != null && fast.next != null && fast.next.next!= null) {
//why need third/second condition?
System.out.println("pre "+slow.val + " " + fast.val);
slow = slow.next;
fast = fast.next.next;
System.out.println("after " + slow.val + " " + fast.val);
}
ListNode p1 = head;
ListNode p2 = second;
p1.next = p2;
p2.next = temp1;
p1 = temp1;
p2 = temp2;
}
}
}
return pre;
}
The three steps can be used to solve other problems of linked list. A little diagram
may help better understand them.
Reverse List:
Merge List:
101.1 Analysis
If we have 2 pointers - fast and slow. It is guaranteed that the fast one will meet the
slow one if there exists a circle.
if(slow == fast)
return true;
}
return false;
}
}
251 | 531
102 Copy List with Random Pointer
A linked list is given such that each node contains an additional random pointer which
could point to any node in the list or null.
Return a deep copy of the list.
• copy every node, i.e., duplicate every node, and insert it to the list
• copy random pointers for all newly created nodes
• break the list to two
if (head == null)
return null;
RandomListNode p = head;
253 | 531
102 Copy List with Random Pointer
p.next = temp.next;
if (temp.next != null)
temp.next = temp.next.next;
p = p.next;
}
return newHead;
}
The break list part above move pointer 2 steps each time, you can also move one at
a time which is simpler, like the following:
while(p != null && p.next != null){
RandomListNode temp = p.next;
p.next = temp.next;
p = temp;
}
From Xiaomeng’s comment below, we can use a HashMap which makes it simpler.
public RandomListNode copyRandomList(RandomListNode head) {
if (head == null)
return null;
HashMap<RandomListNode, RandomListNode> map = new HashMap<RandomListNode,
RandomListNode>();
RandomListNode newHead = new RandomListNode(head.label);
RandomListNode p = head;
RandomListNode q = newHead;
map.put(head, newHead);
p = p.next;
while (p != null) {
RandomListNode temp = new RandomListNode(p.label);
map.put(p, temp);
q.next = temp;
q = temp;
p = p.next;
}
p = head;
q = newHead;
while (p != null) {
if (p.random != null)
q.random = map.get(p.random);
else
q.random = null;
p = p.next;
q = q.next;
}
return newHead;
}
Merge two sorted linked lists and return it as a new list. The new list should be made
by splicing together the nodes of the first two lists.
103.1 Analysis
The key to solve the problem is defining a fake head. Then compare the first elements
from each list. Add the smaller one to the merged list. Finally, when one of them is
empty, simply append it to the merged list, since it is already sorted.
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode p1 = l1;
ListNode p2 = l2;
257 | 531
103 Merge Two Sorted Lists
p = p.next;
}
if(p1 != null)
p.next = p1;
if(p2 != null)
p.next = p2;
return fakeHead.next;
}
}
104.1 Problem
Given a singly linked list, group all odd nodes together followed by the even nodes.
Please note here we are talking about the node number and not the value in the nodes.
The program should run in O(1) space complexity and O(nodes) time complexity.
Example:
Given 1->2->3->4->5->NULL,
return 1->3->5->2->4->NULL.
104.2 Analysis
This problem can be solved by using two pointers. We iterate over the link and move
the two pointers.
259 | 531
104 Odd Even Linked List
p1.next = p2.next;
p1 = p1.next;
p2.next = p1.next;
p2 = p2.next;
}
p1.next = connectNode;
return result;
}
Given a sorted linked list, delete all duplicates such that each element appear only
once.
For example,
Given 1->1->2, return 1->2.
Given 1->1->2->3->3, return 1->2->3.
105.1 Thoughts
The key of this problem is using the right loop condition. And change what is nec-
essary in each loop. You can use different iteration conditions like the following 2
solutions.
105.2 Solution 1
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode deleteDuplicates(ListNode head) {
if(head == null || head.next == null)
return head;
while(p != null){
if(p.val == prev.val){
prev.next = p.next;
p = p.next;
//no change prev
261 | 531
105 Remove Duplicates from Sorted List
}else{
prev = p;
p = p.next;
}
}
return head;
}
}
105.3 Solution 2
ListNode p = head;
return head;
}
}
Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only
distinct numbers from the original list.
For example, given 1->1->1->2->3, return 2->3.
ListNode p = t;
while(p.next!=null&&p.next.next!=null){
if(p.next.val == p.next.next.val){
int dup = p.next.val;
while(p.next!=null&&p.next.val==dup){
p.next = p.next.next;
}
}else{
p=p.next;
}
return t.next;
}
263 | 531
107 Partition List
Given a linked list and a value x, partition it such that all nodes less than x come
before nodes greater than or equal to x.
You should preserve the original relative order of the nodes in each of the two
partitions.
For example, given 1->4->3->2->5->2 and x = 3, return 1->2->2->4->3->5.
ListNode p = head;
ListNode prev = fakeHead1;
ListNode p2 = fakeHead2;
while(p != null){
if(p.val < x){
p = p.next;
prev = prev.next;
}else{
p2.next = p;
prev.next = p.next;
p = prev.next;
p2 = p2.next;
}
}
prev.next = fakeHead2.next;
return fakeHead1.next;
265 | 531
107 Partition List
}
}
Design and implement a data structure for Least Recently Used (LRU) cache. It should
support the following operations: get and set.
get(key) - Get the value (will always be positive) of the key if the key exists in the
cache, otherwise return -1. set(key, value) - Set or insert the value if the key is not
already present. When the cache reached its capacity, it should invalidate the least
recently used item before inserting a new item.
108.1 Analysis
The key to solve this problem is using a double linked list which enables us to quickly
move nodes.
The LRU cache is a hash table of keys and double linked nodes. The hash table
makes the time of get() to be O(1). The list of double linked nodes make the nodes
adding/removal operations O(1).
267 | 531
108 LRU Cache
return -1;
}
if(n.next!=null){
n.next.pre = n.pre;
}else{
end = n.pre;
}
if(head!=null)
head.pre = n;
head = n;
if(end ==null)
end = head;
}
}else{
setHead(created);
}
map.put(key, created);
}
}
}
109.1 Problem
Write a program to find the node at which the intersection of two singly linked lists
begins.
For example, the following two linked lists:
A: a1 -> a2
->
c1 -> c2 -> c3
->
B: b1 -> b2 -> b3
First calculate the length of two lists and find the difference. Then start from the longer
list at the diff offset, iterate though 2 lists and find the node.
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int len1 = 0;
int len2 = 0;
ListNode p1=headA, p2=headB;
if (p1 == null || p2 == null)
return null;
while(p1 != null){
len1++;
p1 = p1.next;
271 | 531
109 Intersection of Two Linked Lists
}
while(p2 !=null){
len2++;
p2 = p2.next;
}
int diff = 0;
p1=headA;
p2=headB;
}
p1 = p1.next;
p2 = p2.next;
}
return null;
}
}
Remove all elements from a linked list of integers that have value val.
Example
Given: 1 --> 2 --> 6 --> 3 --> 4 --> 5 --> 6, val = 6
Return: 1 --> 2 --> 3 --> 4 --> 5
The key to solve this problem is using a helper node to track the head of the list.
public ListNode removeElements(ListNode head, int val) {
ListNode helper = new ListNode(0);
helper.next = head;
ListNode p = helper;
while(p.next != null){
if(p.next.val == val){
ListNode next = p.next;
p.next = next.next;
}else{
p = p.next;
}
}
return helper.next;
}
273 | 531
111 Swap Nodes in Pairs
Given a linked list, swap every two adjacent nodes and return its head.
For example, given 1->2->3->4, you should return the list as 2->1->4->3.
Your algorithm should use only constant space. You may not modify the values in
the list, only nodes itself can be changed.
Use two template variable to track the previous and next node of each pair.
public ListNode swapPairs(ListNode head) {
if(head == null || head.next == null)
return head;
return h.next;
}
275 | 531
112 Reverse Linked List
ListNode p1 = head;
ListNode p2 = head.next;
head.next = null;
while(p1!= null && p2!= null){
ListNode t = p2.next;
p2.next = p1;
p1 = p2;
if (t!=null){
p2 = t;
}else{
break;
}
}
return p2;
}
277 | 531
112 Reverse Linked List
second.next = head;
return rest;
}
113.1 Analysis
int i=0;
ListNode p = head;
while(p!=null){
i++;
if(i==m-1){
prev = p;
}
if(i==m){
first.next = p;
}
if(i==n){
second.next = p.next;
p.next = null;
}
p= p.next;
}
if(first.next == null)
return head;
279 | 531
113 Reverse Linked List II
p1.next = second.next;
return head;
}
Given a linked list, remove the nth node from the end of list and return its head.
For example, given linked list 1->2->3->4->5 and n = 2, the result is 1->2->3->5.
Calculate the length first, and then remove the nth from the beginning.
public ListNode removeNthFromEnd(ListNode head, int n) {
if(head == null)
return null;
return head;
}
281 | 531
114 Remove Nth Node From End of List
Use fast and slow pointers. The fast pointer is n steps ahead of the slow pointer. When
the fast reaches the end, the slow pointer points at the previous element of the target
element.
public ListNode removeNthFromEnd(ListNode head, int n) {
if(head == null)
return null;
while(fast.next != null){
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return head;
}
Implement the following operations of a stack using queues. push(x) – Push element
x onto stack. pop() – Removes the element on top of the stack. top() – Get the top
element. empty() – Return whether the stack is empty.
Note: only standard queue operations are allowed, i.e., poll(), offer(), peek(), size()
and isEmpty() in Java.
115.1 Analysis
class MyStack {
LinkedList<Integer> queue1 = new LinkedList<Integer>();
LinkedList<Integer> queue2 = new LinkedList<Integer>();
283 | 531
115 Implement Stack using Queues
class MyQueue {
value.push(x);
while(!temp.isEmpty()){
value.push(temp.pop());
}
}
}
285 | 531
116 Implement Queue using Stacks
We can create a new list in reversed order and then compare each node. The time and
space are O(n).
public boolean isPalindrome(ListNode head) {
if(head == null)
return true;
ListNode p = head;
ListNode prev = new ListNode(head.val);
while(p.next != null){
ListNode temp = new ListNode(p.next.val);
temp.next = prev;
prev = temp;
p = p.next;
}
ListNode p1 = head;
ListNode p2 = prev;
while(p1!=null){
if(p1.val != p2.val)
return false;
p1 = p1.next;
p2 = p2.next;
}
return true;
}
We can use a fast and slow pointer to get the center of the list, then reverse the second
list and compare two sublists. The time is O(n) and space is O(1).
287 | 531
117 Palindrome Linked List
secondHead.next = null;
p = p.next;
q = q.next;
return true;
}
There following Java code shows how to implement a queue without using any extra
data structures in Java. We can implement a queue by using an array.
import java.lang.reflect.Array;
import java.util.Arrays;
E[] arr;
int head = -1;
int tail = -1;
int size;
boolean push(E e) {
if (size == arr.length)
return false;
if(tail == -1){
tail = head;
}
289 | 531
118 Implement a Queue using an Array in Java
return true;
}
boolean pop() {
if (size == 0) {
return false;
}
E result = arr[tail];
arr[tail] = null;
size--;
tail = (tail+1)%arr.length;
if (size == 0) {
head = -1;
tail = -1;
}
return true;
}
E peek(){
if(size==0)
return null;
return arr[tail];
}
Write a function to delete a node (except the tail) in a singly linked list, given only
access to that node.
Supposed the linked list is 1 ->2 ->3 ->4 and you are given the third node with value
3, the linked list should become 1 ->2 ->4 after calling your function.
291 | 531
120 Moving Average from Data Stream
Given a stream of integers and a window size, calculate the moving average of all
integers in the sliding window.
LinkedList<Integer> queue;
int size;
return (double)sum/queue.size();
}
}
293 | 531
121 Java PriorityQueue Class Example
The following examples shows the basic operations of PriorityQueue such as offer(),
peek(), poll(), and size().
import java.util.Comparator;
import java.util.PriorityQueue;
295 | 531
121 Java PriorityQueue Class Example
// print size
System.out.println("size: " + pq2.size());
// return highest priority element in the queue without removing it
System.out.println("peek: " + pq2.peek());
// print size
System.out.println("size: " + pq2.size());
// return highest priority element and removes it from the queue
System.out.println("poll: " + pq2.poll());
// print size
System.out.println("size: " + pq2.size());
}
}
Output:
pq1: [1, 3, 5, 8, 4, 7, 6, 10, 9]
pq2: [10, 9, 7, 8, 3, 5, 6, 1, 4]
size: 9
peek: 10
size: 9
poll: 10
size: 8
pq2: [9, 8, 7, 4, 3, 5, 6, 1]
122.1 Analysis
Preorder binary tree traversal is a classic interview problem about trees. The key to
solve this problem is to understand the following:
The key is using a stack to store left and right children, and push right child first so
that it is processed after the left child.
if(root == null)
return returnList;
while(!stack.empty()){
TreeNode n = stack.pop();
returnList.add(n.val);
if(n.right != null){
stack.push(n.right);
}
if(n.left != null){
stack.push(n.left);
}
297 | 531
122 Binary Tree Preorder Traversal
}
return returnList;
}
}
The key to solve inorder traversal of binary tree includes the following:
299 | 531
123 Binary Tree Inorder Traversal
if(root == null)
return lst;
while(!stack.empty() || p != null){
// if no left child
// pop stack, process the node
// then let p point to the right
}else{
TreeNode t = stack.pop();
lst.add(t.val);
p = t.right;
}
}
return lst;
}
}
return result;
}
helper(p.left);
result.add(p.val);
if(p.right!=null)
helper(p.right);
}
}
Updated on 4/28/2016
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
if(root==null)
return result;
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root);
while(!stack.isEmpty()){
TreeNode top = stack.peek();
if(top.left!=null){
stack.push(top.left);
top.left=null;
}else{
result.add(top.val);
stack.pop();
if(top.right!=null){
stack.push(top.right);
}
}
}
return result;
}
Among preoder, inorder and postorder binary tree traversal problems, postorder traver-
sal is the most complicated one.
• The order of "Postorder" is: left child ->right child ->parent node.
• Find the relation between the previously visited node and the current node
• Use a stack to track nodes
As we go down the tree to the lft, check the previously visited node. If the current
node is the left or right child of the previous node, then keep going down the tree, and
add left/right node to stack when applicable. When there is no children for current
node, i.e., the current node is a leaf, pop it from the stack. Then the previous node
become to be under the current node for next loop. You can using an example to walk
through the code.
//Definition for binary tree
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
303 | 531
124 Binary Tree Postorder Traversal
if(root == null)
return lst;
prev = curr;
}
return lst;
}
}
if(root==null) {
return res;
}
while(!stack.isEmpty()) {
TreeNode temp = stack.peek();
if(temp.left==null && temp.right==null) {
TreeNode pop = stack.pop();
res.add(pop.val);
}
else {
if(temp.right!=null) {
stack.push(temp.right);
temp.right = null;
}
if(temp.left!=null) {
stack.push(temp.left);
temp.left = null;
}
}
}
return res;
}
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,#,#,15,7,
3
/ \
9 20
/ \
15 7
125.1 Analysis
It is obvious that this problem can be solve by using a queue. However, if we use one
queue we can not track when each level starts. So we use two queues to track the
current level and the next level.
while(!current.isEmpty()){
TreeNode node = current.remove();
if(node.left != null)
next.add(node.left);
if(node.right != null)
next.add(node.right);
nodeValues.add(node.val);
307 | 531
125 Binary Tree Level Order Traversal
if(current.isEmpty()){
current = next;
next = new LinkedList<TreeNode>();
al.add(nodeValues);
nodeValues = new ArrayList();
}
}
return al;
}
Given a binary tree, return the bottom-up level order traversal of its nodes’ values.
For example, given binary tree 3,9,20,#,#,15,7,
3
/ \
9 20
/ \
15 7
if(root == null){
return result;
}
numberList.add(head.val);
if(head.left != null){
next.offer(head.left);
}
if(head.right!= null){
next.offer(head.right);
}
if(current.isEmpty()){
current = next;
309 | 531
126 Binary Tree Level Order Traversal II
//return Collections.reverse(result);
ArrayList<ArrayList<Integer>> reversedResult = new
ArrayList<ArrayList<Integer>>();
for(int i=result.size()-1; i>=0; i--){
reversedResult.add(result.get(i));
}
return reversedResult;
}
Given a binary tree, return the vertical order traversal of its nodes’ values. (ie, from
top to bottom, column by column).
For each node, its left child’s degree is -1 and is right child’s degree is +1. We can do
a level order traversal and save the degree information.
class Wrapper{
TreeNode node;
int level;
while(!queue.isEmpty()){
Wrapper w = queue.poll();
if(map.containsKey(level)){
map.get(level).add(node.val);
}else{
ArrayList<Integer> t = new ArrayList<Integer>();
t.add(node.val);
311 | 531
127 Binary Tree Vertical Order Traversal
map.put(level, t);
}
if(node.left!=null){
queue.offer(new Wrapper(node.left, level-1));
}
if(node.right!=null){
queue.offer(new Wrapper(node.right, level+1));
}
return result;
}
}
Google: 90
Very funny. Luckily, I can and in 2 ways!
return root;
}
if(p.left!=null)
helper(p.left);
if(p.right!=null)
helper(p.right);
}
if(root!=null){
queue.add(root);
}
while(!queue.isEmpty()){
TreeNode p = queue.poll();
if(p.left!=null)
313 | 531
128 Invert Binary Tree
queue.add(p.left);
if(p.right!=null)
queue.add(p.right);
return root;
}
Given a binary search tree, write a function kthSmallest to find the kth smallest ele-
ment in it. (1 ≤ k ≤ BST’s total elements)
We can inorder traverse the tree and get the kth smallest element. Time is O(n).
public int kthSmallest(TreeNode root, int k) {
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode p = root;
int result = 0;
while(!stack.isEmpty() || p!=null){
if(p!=null){
stack.push(p);
p = p.left;
}else{
TreeNode t = stack.pop();
k--;
if(k==0)
result = t.val;
p = t.right;
}
}
return result;
}
We can let each node track the order, i.e., the number of elements that are less than
itself. Time is O(log(n)).
coming soon...
315 | 531
130 Binary Tree Longest Consecutive
Sequence
Given a binary tree, find the length of the longest consecutive sequence path.
The path refers to any sequence of nodes from some starting node to any node in
the tree along the parent-child connections. The longest consecutive path need to be
from parent to child (cannot be the reverse).
nodeQueue.offer(root);
sizeQueue.offer(1);
int max=1;
while(!nodeQueue.isEmpty()){
TreeNode head = nodeQueue.poll();
int size = sizeQueue.poll();
if(head.left!=null){
int leftSize=size;
if(head.val==head.left.val-1){
leftSize++;
max = Math.max(max, leftSize);
}else{
leftSize=1;
}
nodeQueue.offer(head.left);
sizeQueue.offer(leftSize);
}
if(head.right!=null){
int rightSize=size;
if(head.val==head.right.val-1){
317 | 531
130 Binary Tree Longest Consecutive Sequence
rightSize++;
max = Math.max(max, rightSize);
}else{
rightSize=1;
}
nodeQueue.offer(head.right);
sizeQueue.offer(rightSize);
}
return max;
}
int l = helper(root.left);
int r = helper(root.right);
int fromLeft = 0;
int fromRight= 0;
if(root.left==null){
fromLeft=1;
}else if(root.left.val-1==root.val){
fromLeft = l+1;
}else{
fromLeft=1;
}
if(root.right==null){
fromRight=1;
}else if(root.right.val-1==root.val){
fromRight = r+1;
}else{
fromRight=1;
}
• The left subtree of a node contains only nodes with keys less than the node’s key.
• The right subtree of a node contains only nodes with keys greater than the node’s
key.
• Both the left and right subtrees must also be binary search trees.
All values on the left sub tree must be less than root, and all values on the right sub
tree must be greater than root. So we just check the boundaries for each node.
public boolean isValidBST(TreeNode root) {
return isValidBST(root, Double.NEGATIVE_INFINITY,
Double.POSITIVE_INFINITY);
}
This solution also goes to the left subtree first. If the violation occurs close to the
root but on the right subtree, the method still cost O(n). The second solution below
can handle violations close to root node faster.
321 | 531
131 Validate Binary Search Tree
132.1 Thoughts
Go down through the left, when right is not null, push right to stack.
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
323 | 531
132 Flatten Binary Tree to Linked List
if(p.right != null){
stack.push(p.right);
}
if(p.left != null){
p.right = p.left;
p.left = null;
}else if(!stack.empty()){
TreeNode temp = stack.pop();
p.right=temp;
}
p = p.right;
}
}
}
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.
For example: Given the below binary tree and sum = 22,
5
/ \
4 8
/ / \
11 13 4
/ \ \
7 2 1
return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22.
Add all node to a queue and store sum value of each node to another queue. When it
is a leaf node, check the stored sum value.
For the tree above, the queue would be: 5 - 4 - 8 - 11 - 13 - 4 - 7 - 2 - 1. It will check
node 13, 7, 2 and 1. This is a typical breadth first search(BFS) problem.
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public boolean hasPathSum(TreeNode root, int sum) {
if(root == null) return false;
nodes.add(root);
values.add(root.val);
while(!nodes.isEmpty()){
325 | 531
133 Path Sum
if(curr.left != null){
nodes.add(curr.left);
values.add(sumValue+curr.left.val);
}
if(curr.right != null){
nodes.add(curr.right);
values.add(sumValue+curr.right.val);
}
}
return false;
}
}
Given a binary tree and a sum, find all root-to-leaf paths where each path’s sum equals
the given sum.
For example, given the below binary tree and sum = 22,
5
/ \
4 8
/ / \
11 13 4
/ \ / \
7 2 5 1
134.1 Analysis
327 | 531
134 Path Sum II
Given inorder and postorder traversal of a tree, construct the binary tree.
135.1 Analysis
From the post-order array, we know that last element is the root. We can find the
root in in-order array. Then we can identify the left and right sub-trees of the root
from in-order array.
Using the length of left sub-tree, we can identify left and right sub-trees in post-
order array. Recursively, we can build up the tree.
329 | 531
135 Construct Binary Tree from Inorder and Postorder Traversal
int k = 0;
for (int i = 0; i < inorder.length; i++) {
if (inorder[i] == rootValue) {
k = i;
break;
}
}
return root;
}
Given preorder and inorder traversal of a tree, construct the binary tree.
136.1 Analysis
From the pre-order array, we know that first element is the root. We can find the
root in in-order array. Then we can identify the left and right sub-trees of the root
from in-order array.
Using the length of left sub-tree, we can identify left and right sub-trees in pre-order
array. Recursively, we can build up the tree.
331 | 531
136 Construct Binary Tree from Preorder and Inorder Traversal
if(preStart>preEnd||inStart>inEnd){
return null;
}
return p;
}
Given an array where elements are sorted in ascending order, convert it to a height
balanced BST.
137.1 Thoughts
TreeNode(int x) {
val = x;
}
}
return root;
333 | 531
137 Convert Sorted Array to Binary Search Tree
}
}
Given a singly linked list where elements are sorted in ascending order, convert it to a
height balanced BST.
138.1 Thoughts
If you are given an array, the problem is quite straightforward. But things get a little
more complicated when you have a singly linked list instead of an array. Now you no
longer have random access to an element in O(1) time. Therefore, you need to create
nodes bottom-up, and assign them to its parents. The bottom-up approach enables us
to access the list in its order at the same time as creating nodes.
ListNode(int x) {
val = x;
next = null;
}
}
TreeNode(int x) {
val = x;
}
}
335 | 531
138 Convert Sorted List to Binary Search Tree
h = head;
int len = getLength(head);
return sortedListToBST(0, len - 1);
}
while (p != null) {
len++;
p = p.next;
}
return len;
}
// mid
int mid = (start + end) / 2;
root.left = left;
root.right = right;
return root;
}
}
139.1 Thoughts
LinkedList is a queue in Java. The add() and remove() methods are used to manipulate
the queue.
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public int minDepth(TreeNode root) {
if(root == null){
return 0;
}
nodes.add(root);
counts.add(1);
while(!nodes.isEmpty()){
TreeNode curr = nodes.remove();
int count = counts.remove();
337 | 531
139 Minimum Depth of Binary Tree
if(curr.left != null){
nodes.add(curr.left);
counts.add(count+1);
}
if(curr.right != null){
nodes.add(curr.right);
counts.add(count+1);
}
}
return 0;
}
}
Given a binary tree, find the maximum path sum. The path may start and end at any
node in the tree. For example, given the below binary tree
1
/ \
2 3
the result is 6.
140.1 Analysis
1) Recursively solve this problem 2) Get largest left sum and right sum 2) Compare to
the stored maximum
return current;
}
339 | 531
141 Balanced Binary Tree
141.1 Analysis
TreeNode(int x) {
val = x;
}
}
if (getHeight(root) == -1)
return false;
return true;
}
341 | 531
141 Balanced Binary Tree
return -1;
}
}
142.1 Problem
Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its
center).
For example, this binary tree is symmetric:
1
/ \
2 2
/ \ / \
3 4 4 3
This problem can be solve by using a simple recursion. The key is finding the con-
ditions that return false, such as value is not equal, only one node(left or right) has
value.
public boolean isSymmetric(TreeNode root) {
if (root == null)
return true;
return isSymmetric(root.left, root.right);
}
if (l.val != r.val)
343 | 531
142 Symmetric Tree
return false;
if (!isSymmetric(l.left, r.right))
return false;
if (!isSymmetric(l.right, r.left))
return false;
return true;
}
143.1 Problem
Implement an iterator over a binary search tree (BST). Your iterator will be initialized
with the root node of a BST. Calling next() will return the next smallest number in
the BST. Note: next() and hasNext() should run in average O(1) time and uses O(h)
memory, where h is the height of the tree.
The key to solve this problem is understanding what is BST. Here is a diagram.
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
345 | 531
143 Binary Search Tree Iterator
Given a binary tree, imagine yourself standing on the right side of it, return the values
of the nodes you can see ordered from top to bottom. For example, given the following
binary tree,
1 <---
/ \
2 3 <---
\
5 <---
144.1 Analysis
This problem can be solve by using a queue. On each level of the tree, we add the
right-most element to the results.
347 | 531
144 Binary Tree Right Side View
queue.add(top.right);
}
//add left
if(top.left != null){
queue.add(top.left);
}
}
}
return result;
}
Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given
nodes in the BST.
145.1 Analysis
This problem can be solved by using BST property, i.e., left <parent <right for each
node. There are 3 cases to handle.
return root;
}
349 | 531
146 Lowest Common Ancestor of a
Binary Tree
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the
tree.
Since each node is visited in the worst case, time complexity is O(n).
class Entity{
public int count;
public TreeNode node;
351 | 531
146 Lowest Common Ancestor of a Binary Tree
One way to serialize a binary tree is to use pre-order traversal. When we encounter
a non-null node, we record the node’s value. If it is a null node, we record using a
sentinel value such as #.
9
/ \
3 2
/ \ / \
4 1 # 6
/ \ / \ / \
# # # # # #
For example, the above binary tree can be serialized to the string "9,3,4,#,#,1,#,#,2,#,6,#,#",
where # represents a null node.
Given a string of comma separated values, verify whether it is a correct preorder
traversal serialization of a binary tree. Find an algorithm without reconstructing the
tree.
We can keep removing the leaf node until there is no one to remove. If a sequence
is like "4 # #", change it to "#" and continue. We need a stack so that we can record
previous removed nodes.
353 | 531
147 Verify Preorder Serialization of a Binary Tree
while(stack.size()>=3
&& stack.get(stack.size()-1).equals("#")
&& stack.get(stack.size()-2).equals("#")
&& !stack.get(stack.size()-3).equals("#")){
stack.remove(stack.size()-1);
stack.remove(stack.size()-1);
stack.remove(stack.size()-1);
stack.add("#");
}
This solution is easier to understand. You can use the example tree above to walk
through the algorithm. The basic idea is have 4 pointers to move towards right on two
levels (see comments in the code).
355 | 531
148 Populating Next Right Pointers in Each Node
if(root == null)
return;
while(lastHead!=null){
lastCurrent = lastHead;
while(lastCurrent!=null){
if(currentHead == null){
currentHead = lastCurrent.left;
current = lastCurrent.left;
}else{
current.next = lastCurrent.left;
current = current.next;
}
if(currentHead != null){
current.next = lastCurrent.right;
current = current.next;
}
lastCurrent = lastCurrent.next;
}
149.1 Analysis
Similar to Populating Next Right Pointers in Each Node, we have 4 pointers at 2 levels
of the tree.
while(lastHead!=null){
lastCurrent = lastHead;
while(lastCurrent!=null){
//left child is not null
if(lastCurrent.left!=null) {
357 | 531
149 Populating Next Right Pointers in Each Node II
if(currentHead == null){
currentHead = lastCurrent.left;
current = lastCurrent.left;
}else{
current.next = lastCurrent.left;
current = current.next;
}
}
lastCurrent = lastCurrent.next;
}
Given n, how many structurally unique BST’s (binary search trees) that store values
1...n?
For example, Given n = 3, there are a total of 5 unique BST’s.
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
150.1 Analysis
Let count[i] be the number of unique binary search trees for i. The number of trees are
determined by the number of subtrees which have different root node. For example,
i=0, count[0]=1 //empty tree
359 | 531
150 Unique Binary Search Trees
count[0] = 1;
count[1] = 1;
return count[n];
}
Given n, generate all structurally unique BST’s (binary search trees) that store values
1...n.
For example, Given n = 3, your program should return all 5 unique BST’s shown
below.
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
151.1 Analysis
361 | 531
151 Unique Binary Search Trees II
node.left = left;
node.right = right;
list.add(node);
}
}
}
return list;
}
Given a binary tree containing digits from 0-9 only, each root-to-leaf path could repre-
sent a number. Find the total sum of all root-to-leaf numbers.
For example,
1
/ \
2 3
The root-to-leaf path 1->2 represents the number 12. The root-to-leaf path 1->3
represents the number 13. Return the sum = 12 + 13 = 25.
for(ArrayList<TreeNode> a: all){
StringBuilder sb = new StringBuilder();
for(TreeNode n: a){
sb.append(String.valueOf(n.val));
}
int currValue = Integer.valueOf(sb.toString());
result = result + currValue;
}
return result;
}
363 | 531
152 Sum Root to Leaf Numbers
t.addAll(l);
all.add(t);
}
if(n.left!=null){
l.add(n.left);
dfs(n.left, l, all);
l.remove(l.size()-1);
}
if(n.right!=null){
l.add(n.right);
dfs(n.right, l, all);
l.remove(l.size()-1);
}
// leaf
if(node.left == null && node.right == null) {
sum += num;
return sum;
}
153.1 Analysis
Steps to solve this problem: 1) get the height of left-most part 2) get the height of
right-most part 3) when they are equal, the # of nodes = 2ĥ -1 4) when they are not
equal, recursively get # of nodes from left&right sub-trees
365 | 531
153 Count Complete Tree Nodes
if(left==right){
return (2<<(left-1))-1;
}else{
return countNodes(root.left)+countNodes(root.right)+1;
}
}
int height=0;
while(n.left!=null){
height++;
n = n.left;
}
return height;
}
int height=0;
while(n.right!=null){
height++;
n = n.right;
}
return height;
}
Given a non-empty binary search tree and a target value, find the value in the BST
that is closest to the target.
Recursively traverse down the root. When target is less than root, go left; when target
is greater than root, go right.
public class Solution {
int goal;
double min = Double.MAX_VALUE;
367 | 531
155 Binary Tree Paths
if(root==null)
return finalResult;
for(ArrayList<String> al : results){
StringBuilder sb = new StringBuilder();
sb.append(al.get(0));
for(int i=1; i<al.size();i++){
sb.append("->"+al.get(i));
}
finalResult.add(sb.toString());
}
return finalResult;
}
if(root.left!=null){
ArrayList<String> temp = new ArrayList<String>(curr);
dfs(root.left, list, temp);
369 | 531
155 Binary Tree Paths
if(root.right!=null){
ArrayList<String> temp = new ArrayList<String>(curr);
dfs(root.right, list, temp);
}
}
This is a classic interview question. Another similar problem is "merge k sorted lists".
This problem can be solved by using a heap. The time is O(nlog(n)).
Given m arrays, the minimum elements of all arrays can form a heap. It takes
O(log(m)) to insert an element to the heap and it takes O(1) to delete the minimum
element.
class ArrayContainer implements Comparable<ArrayContainer> {
int[] arr;
int index;
@Override
public int compareTo(ArrayContainer o) {
return this.arr[this.index] - o.arr[o.index];
}
}
int m=0;
int result[] = new int[total];
371 | 531
156 Merge K Sorted Arrays in Java
return result;
}
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its
complexity.
157.1 Analysis
The simplest solution is using PriorityQueue. The elements of the priority queue
are ordered according to their natural ordering, or by a comparator provided at the
construction time (in this case).
import java.util.ArrayList;
import java.util.Comparator;
import java.util.PriorityQueue;
ListNode(int x) {
val = x;
next = null;
}
}
373 | 531
157 Merge k Sorted Lists
else
return -1;
}
});
p = p.next;
}
return head.next;
}
}
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.
158.1 Analysis
First of all, it seems that the best time complexity we can get for this problem is
O(log(n)) of add() and O(1) of getMedian(). This data structure seems highly likely to
be a tree.
We can use heap to solve this problem. In Java, the PriorityQueue class is a priority
heap. We can use two heaps to store the lower half and the higher half of the data
stream. The size of the two heaps differs at most 1.
class MedianFinder {
PriorityQueue<Integer> maxHeap;//lower half
PriorityQueue<Integer> minHeap;//higher half
public MedianFinder(){
maxHeap = new PriorityQueue<Integer>(Collections.reverseOrder());
minHeap = new PriorityQueue<Integer>();
}
375 | 531
158 Find Median from Data Stream
A trie node should contains the character, its children and the flag that marks if it is a
leaf node. You can use this diagram to walk though the Java solution.
class TrieNode {
char c;
HashMap<Character, TrieNode> children = new HashMap<Character, TrieNode>();
boolean isLeaf;
public TrieNode() {}
public Trie() {
root = new TrieNode();
}
377 | 531
159 Implement Trie (Prefix Tree)
TrieNode t;
if(children.containsKey(c)){
t = children.get(c);
}else{
t = new TrieNode(c);
children.put(c, t);
}
children = t.children;
children = t.children;
}else{
return null;
}
}
return t;
}
}
Each trie node can only contains ’a’-’z’ characters. So we can use a small array to store
the character.
class TrieNode {
TrieNode[] arr;
boolean isEnd;
// Initialize your data structure here.
public TrieNode() {
this.arr = new TrieNode[26];
}
public Trie() {
root = new TrieNode();
}
return false;
}
if(p==root)
return null;
return p;
}
}
search(word) can search a literal word or a regular expression string containing only
letters a-z or .. A . means it can represent any one letter.
This problem is similar with Implement Trie. The solution 1 below uses the same
definition of a trie node. To handle the "." case for this problem, we need to search all
possible paths, instead of one path.
TrieNode
class TrieNode{
char c;
HashMap<Character, TrieNode> children = new HashMap<Character, TrieNode>();
boolean isLeaf;
public TrieNode() {}
WordDictionary
public class WordDictionary {
private TrieNode root;
public WordDictionary(){
root = new TrieNode();
}
381 | 531
160 Add and Search Word Data structure design
TrieNode t = null;
if(children.containsKey(c)){
t = children.get(c);
}else{
t = new TrieNode(c);
children.put(c,t);
}
children = t.children;
if(i == word.length()-1){
t.isLeaf = true;
}
}
}
char c = word.charAt(start);
if(children.containsKey(c)){
if(start == word.length()-1 && children.get(c).isLeaf){
return true;
}
return result;
}else{
return false;
}
}
}
class TrieNode{
TrieNode[] arr;
boolean isLeaf;
public TrieNode(){
arr = new TrieNode[26];
}
}
public WordDictionary(){
root = new TrieNode();
}
// Adds a word into the data structure.
public void addWord(String word) {
TrieNode p= root;
for(int i=0; i<word.length(); i++){
char c=word.charAt(i);
int index = c-’a’;
if(p.arr[index]==null){
TrieNode temp = new TrieNode();
p.arr[index]=temp;
p=temp;
}else{
p=p.arr[index];
}
}
p.isLeaf=true;
char c = word.charAt(start);
if (c == ’.’) {
boolean tResult = false;
for (int j = 0; j < 26; j++) {
if (p.arr[j] != null) {
if (dfsSearch(p.arr[j], word, start + 1)) {
tResult = true;
break;
}
}
}
if (tResult)
return true;
} else {
int index = c - ’a’;
if (p.arr[index] != null) {
return dfsSearch(p.arr[index], word, start + 1);
} else {
return false;
}
}
return false;
}
}
Given an integer array nums, find the sum of the elements between indices i and j (i
≤ j), inclusive. The update(i, val) function modifies nums by updating the element at
index i to val.
class TreeNode{
int start;
int end;
int sum;
TreeNode leftChild;
TreeNode rightChild;
385 | 531
161 Range Sum Query Mutable
this.end=right;
this.sum=0;
}
}
if(root.start==root.end&& root.start==i){
root.sum=val;
return;
}
root.sum=root.leftChild.sum+root.rightChild.sum;
}
}
int mid = root.start + (root.end-root.start)/2;
int result = sumRangeHelper(root.leftChild, i, Math.min(mid, j))
+sumRangeHelper(root.rightChild, Math.max(mid+1, i), j);
return result;
}
if(i==j){
return new TreeNode(i, j, nums[i]);
}
current.sum = current.leftChild.sum+current.rightChild.sum;
return current;
}
}
162.1 Analysis
This problem is essentially a problem of processing 2*n edges. Each edge has a x-axis
value and a height value. The key part is how to use the height heap to process each
edge.
class Edge {
int x;
int height;
boolean isStart;
// sort edges
389 | 531
162 The Skyline Problem
return a.isStart ? -1 : 1;
}
});
// process edges
PriorityQueue<Integer> heightHeap = new PriorityQueue<Integer>(10,
Collections.reverseOrder());
if(heightHeap.isEmpty()){
result.add(new int[] {edge.x, 0});
}else if(edge.height > heightHeap.peek()){
result.add(new int[]{edge.x, heightHeap.peek()});
}
}
}
return result;
}
LeetCode Problem:
Clone an undirected graph. Each node in the graph contains a label and a list of its
neighbors.
391 | 531
163 Clone Graph Java
/**
* Definition for undirected graph.
* class UndirectedGraphNode {
* int label;
* ArrayList<UndirectedGraphNode> neighbors;
* UndirectedGraphNode(int x) { label = x; neighbors = new
ArrayList<UndirectedGraphNode>(); }
* };
*/
public class Solution {
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
if(node == null)
return null;
queue.add(node);
map.put(node, newHead);
while(!queue.isEmpty()){
UndirectedGraphNode curr = queue.pop();
ArrayList<UndirectedGraphNode> currNeighbors = curr.neighbors;
}
return newHead;
}
}
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?
For example, given 2 and [[1,0]], there are a total of 2 courses to take. To take course
1 you should have finished course 0. So it is possible.
For another example, given 2 and [[1,0],[0,1]], there are a total of 2 courses to take.
To take course 1 you should have finished course 0, and to take course 0 you should
also have finished course 1. So it is impossible.
164.1 Analysis
395 | 531
164 Course Schedule
}
}
while(!queue.isEmpty()){
int top = queue.remove();
for(int i=0; i<len; i++){
// if a course’s prerequisite can be satisfied by a course in queue
if(prerequisites[i][1]==top){
pCounter[prerequisites[i][0]]--;
if(pCounter[prerequisites[i][0]]==0){
numNoPre++;
queue.add(prerequisites[i][0]);
}
}
}
}
l.add(a[0]);
map.put(a[1], l);
}
}
return true;
}
visit[i]=-1;
if(map.containsKey(i)){
for(int j: map.get(i)){
if(!canFinishDFS(map, visit, j))
return false;
}
}
visit[i]=1;
return true;
}
165.1 Analysis
If we use the DFS solution of Course Schedule, a valid sequence can easily be recorded.
399 | 531
165 Course Schedule II
//initialize result
int[] result = new int[numCourses];
int j=0;
while(!queue.isEmpty()){
int c = queue.remove();
result[j++]=c;
}
}
//return result
if(numNoPre==numCourses){
return result;
}else{
return new int[0];
}
}
Given a list of airline tickets represented by pairs of departure and arrival airports
[from, to], reconstruct the itinerary in order. All of the tickets belong to a man who
departs from JFK. Thus, the itinerary must begin with JFK.
166.1 Analysis
dfs("JFK");
return result;
}
result.addFirst(s);
}
}
401 | 531
167 How Developers Sort in Java?
While analyzing source code of a large number of open source Java projects, I found
Java developers frequently sort in two ways. One is using the sort() method of Col-
lections or Arrays, and the other is using sorted data structures, such as TreeMap and
TreeSet.
403 | 531
167 How Developers Sort in Java?
This approach is very useful, if you would do a lot of search operations for the
collection. The sorted data structure will give time complexity of O(logn), which is
lower than O(n).
There are still bad practices, such as using self-defined sorting algorithm. Take the
code below for example, not only the algorithm is not efficient, but also it is not
readable. This happens a lot in different forms of variations.
double t;
for (int i = 0; i < 2; i++)
for (int j = i + 1; j < 3; j++)
if (r[j] < r[i]) {
t = r[i];
r[i] = r[j];
r[j] = t;
}
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
// merge sort
public static ListNode mergeSortList(ListNode head) {
405 | 531
168 Solution Merge Sort LinkedList in Java
if (countHalf == middle) {
p2.next = null;
r = next;
}
p2 = next;
}
// merge together
ListNode merged = merge(h1, h2);
return merged;
}
if (p1 == null) {
pNew.next = new ListNode(p2.val);
p2 = p2.next;
pNew = pNew.next;
} else if (p2 == null) {
pNew.next = new ListNode(p1.val);
p1 = p1.next;
pNew = pNew.next;
} else {
if (p1.val < p2.val) {
// if(fakeHead)
pNew.next = new ListNode(p1.val);
p1 = p1.next;
pNew = pNew.next;
} else {
pNew.next = new ListNode(p2.val);
p2 = p2.next;
pNew = pNew.next;
}
}
}
// printList(fakeHead.next);
return fakeHead.next;
}
n1.next = n2;
n2.next = n3;
n3.next = n4;
n4.next = n5;
n5.next = n6;
n1 = mergeSortList(n1);
printList(n1);
}
Output:
233445
Quicksort is a divide and conquer algorithm. It first divides a large list into two
smaller sub-lists and then recursively sort the two sub-lists. If we want to sort an array
without any extra space, quicksort is a good option. On average, time complexity is
O(n log(n)).
The basic step of sorting an array are as follows:
• Select a pivot, normally the middle one
• From both ends, swap elements and make all elements on the left less than the
pivot and all elements on the right greater than the pivot
• Recursively sort left part and right part
Here is a very good animation of quicksort.
public class QuickSort {
public static void main(String[] args) {
int[] x = { 9, 2, 4, 7, 3, 7, 10 };
System.out.println(Arrays.toString(x));
int low = 0;
int high = x.length - 1;
409 | 531
169 Quicksort Array in Java
if (i <= j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
}
}
if (high > i)
quickSort(arr, i, high);
}
}
Output:
9 2 4 7 3 7 10 2 3 4 7 7 9 10
Code:
package algorithm.sort;
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
411 | 531
170 Solution Sort a linked list using insertion sort in Java
innerPointer = innerPointer.next;
}
// finally
pointer = next;
}
return newHead;
}
n1.next = n2;
n2.next = n3;
n3.next = n4;
n4.next = n5;
n5.next = n6;
n1 = insertionSortList(n1);
printList(n1);
}
}
Output:
233445
Given an unsorted array, find the maximum difference between the successive ele-
ments in its sorted form.
Try to solve it in linear time/space. Return 0 if the array contains less than 2 ele-
ments. You may assume all elements in the array are non-negative integers and fit in
the 32-bit signed integer range.
171.1 Analysis
We can use a bucket-sort like algorithm to solve this problem in time of O(n) and space
O(n). The basic idea is to project each element of the array to an array of buckets. Each
bucket tracks the maximum and minimum elements. Finally, scanning the bucket list,
we can get the maximum gap.
The key part is to get the interval:
From: interval * (num[i] - min) = 0 and interval * (max -num[i]) = n
interval = num.length / (max - min)
class Bucket{
int low;
int high;
public Bucket(){
low = -1;
high = -1;
}
}
415 | 531
171 Maximum Gap
if(buckets[index].low == -1){
buckets[index].low = num[i];
buckets[index].high = num[i];
}else{
buckets[index].low = Math.min(buckets[index].low, num[i]);
buckets[index].high = Math.max(buckets[index].high, num[i]);
}
}
return result;
}
Given an unsorted integer array, find the first missing positive integer. For example,
given [1,2,0] return 3 and [3,4,-1,1] return 2.
Your algorithm should run in O(n) time and uses constant space.
172.1 Analysis
This problem can solve by using a bucket-sort like algorithm. Let’s consider finding
first missing positive and 0 first. The key fact is that the ith element should be i, so we
have: i==A[i] A[i]==A[A[i]]
For example, given an array 1,2,0,4, the algorithm does the following:
417 | 531
172 First Missing Positive
A[i] = A[temp];
A[temp] = temp;
}
}
return n;
}
This problem only considers positive numbers, so we need to shift 1 offset. The ith
element is i+1.
public int firstMissingPositive(int[] A) {
int n = A.length;
if(A[i]==A[A[i]-1])
break;
return n + 1;
}
Given an array with n objects colored red, white or blue, sort them 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.
In solution 1, two arrays are created. One is for counting, and the other is for storing
the sorted array (space is O(n)). We can improve the solution so that it only uses
constant space. Since we already get the count of each element, we can directly project
them to the original array, instead of creating a new one.
419 | 531
173 Sort Colors
int j = 0;
int k = 0;
while(j<=2){
if(countArray[j]!=0){
nums[k++]=j;
countArray[j] = countArray[j]-1;
}else{
j++;
}
}
}
From Wiki:
In computer science, edit distance is a way of quantifying how dissimilar two strings
(e.g., words) are to one another by counting the minimum number of operations required
to transform one string into the other.
There are three operations permitted on a word: replace, delete, insert. For example,
the edit distance between "a" and "b" is 1, the edit distance between "abc" and "def" is
3. This post analyzes how to calculate edit distance by using dynamic programming.
Let dp[i][j] stands for the edit distance between two strings with length i and j, i.e.,
word1[0,...,i-1] and word2[0,...,j-1]. There is a relation between dp[i][j] and dp[i-1][j-1].
Let’s say we transform from one string to another. The first string has length i and
it’s last character is "x"; the second string has length j and its last character is "y". The
following diagram shows the relation.
421 | 531
174 Edit Distance in Java
return dp[len1][len2];
}
175.1 Analysis
The problem itself is very difficult to understand. It can be stated like this: Give a
sequence S and T, how many distinct sub sequences from S equals to T? How do you
define "distinct" subsequence? Clearly, the ’distinct’ here mean different operation
combination, not the final string of subsequence. Otherwise, the result is always 0 or
1. – from Jason’s comment
When you see string problem that is about subsequence or matching, dynamic pro-
gramming method should come to mind naturally. The key is to find the initial and
changing condition.
Let W(i, j) stand for the number of subsequences of S(0, i) equals to T(0, j). If S.charAt(i)
== T.charAt(j), W(i, j) = W(i-1, j-1) + W(i-1,j); Otherwise, W(i, j) = W(i-1,j).
public int numDistincts(String S, String T) {
int[][] table = new int[S.length() + 1][T.length() + 1];
425 | 531
175 Distinct Subsequences Total
return table[S.length()][T.length()];
}
Do NOT write something like this, even it can also pass the online judge.
public int numDistinct(String S, String T) {
HashMap<Character, ArrayList<Integer>> map = new HashMap<Character,
ArrayList<Integer>>();
if (map.containsKey(c)) {
ArrayList<Integer> temp = map.get(c);
int[] old = new int[temp.size()];
// the relation
for (int j = 0; j < temp.size(); j++)
result[temp.get(j) + 1] = result[temp.get(j) + 1] + old[j];
}
}
return result[T.length()];
}
Naively, we can simply examine every substring and check if it is palindromic. The
time complexity is O(n3̂). If this is submitted to LeetCode onlinejudge, an error mes-
sage will be returned - "Time Limit Exceeded". Therefore, this approach is just a start,
we need a better algorithm.
public static String longestPalindrome1(String s) {
int maxPalinLength = 0;
String longestPalindrome = null;
int length = s.length();
return longestPalindrome;
}
427 | 531
176 Longest Palindromic Substring
return true;
}
Let s be the input string, i and j are two indices of the string. Define a 2-dimension
array "table" and let table[i][j] denote whether a substring from i to j is palindrome.
Start condition:
table[i][i] == 1;
table[i][i+1] == 1 => s.charAt(i) == s.charAt(i+1)
Changing condition:
table[i+1][j-1] == 1 && s.charAt(i) == s.charAt(j)
=>
table[i][j] == 1
if(s.length() <=1)
return s;
int maxLen = 0;
String longestStr = null;
//e.g. bcba
//two consecutive same letters are palindrome
for (int i = 0; i <= length - 2; i++) {
if (s.charAt(i) == s.charAt(i + 1)){
table[i][i + 1] = 1;
longestStr = s.substring(i, i + 2);
}
}
printTable(table);
//condition for calculate whole table
for (int l = 3; l <= length; l++) {
for (int i = 0; i <= length-l; i++) {
int j = i + l - 1;
if (s.charAt(i) == s.charAt(j)) {
table[i][j] = table[i + 1][j - 1];
if (table[i][j] == 1 && l > maxLen)
longestStr = s.substring(i, j + 1);
} else {
table[i][j] = 0;
}
printTable(table);
}
}
return longestStr;
}
public static void printTable(int[][] x){
for(int [] y : x){
for(int z: y){
System.out.print(z + " ");
}
System.out.println();
}
System.out.println("------");
}
Given a string, we can use the printTable() method to examine the table after ex-
ecution. For example, if the input string is "dabcba", the final matrix would be the
following:
1 0 0 0 0 0
0 1 0 0 0 1
0 0 1 0 1 0
0 0 0 1 0 0
0 0 0 0 1 0
0 0 0 0 0 1
From the table, we can clearly see that the longest string is in cell table[1][5].
if (s.length() == 1) {
return s;
}
return longest;
}
Manacher’s algorithm is much more complicated to figure out, even though it will
bring benefit of time complexity of O(n). Since it is not typical, there is no need to
waste time on that.
Given a string s and a dictionary of words dict, determine if s can be segmented into
a space-separated sequence of one or more dictionary words. For example, given s =
"leetcode", dict = ["leet", "code"]. Return true because "leetcode" can be segmented as
"leet code".
This problem can be solve by using a naive approach, which is trivial. A discussion
can always start from that though.
public class Solution {
public boolean wordBreak(String s, Set<String> dict) {
return wordBreakHelper(s, dict, 0);
}
for(String a: dict){
int len = a.length();
int end = start+len;
if(s.substring(start, start+len).equals(a))
if(wordBreakHelper(s, dict, start+len))
return true;
}
return false;
}
}
431 | 531
177 Word Break
• Define an array t[] such that t[i]==true =>0-(i-1) can be segmented using dictio-
nary
• Initial state t[0] == true
for(String a: dict){
int len = a.length();
int end = i + len;
if(end > s.length())
continue;
if(t[end]) continue;
if(s.substring(i, end).equals(a)){
t[end] = true;
}
}
}
return t[s.length()];
}
}
(Thanks to hdante.) Leetcode online judge does not allow using the Pattern class
though.
public static void main(String[] args) {
HashSet<String> dict = new HashSet<String>();
dict.add("go");
dict.add("goal");
dict.add("goals");
dict.add("special");
for(String s: dict){
sb.append(s + "|");
}
if(m.matches()){
System.out.println("match");
}
}
The dynamic solution can tell us whether the string can be broken to words, but can
not tell us what words the string is broken to. So how to get those words?
Check out Word Break II.
Given a string s and a dictionary of words dict, add spaces in s to construct a sentence
where each word is a valid dictionary word. Return all such possible sentences. For
example, given s = "catsanddog", dict = ["cat", "cats", "and", "sand", "dog"], the solution
is ["cats and dog", "cat sand dog"].
This problem is very similar to Word Break. Instead of using a boolean array to track
the matched positions, we need to track the actual matched words. Then we can use
depth first search to get all the possible paths, i.e., the list of strings.
The following diagram shows the structure of the tracking array.
435 | 531
178 Word Break II
for(String word:dict){
int len = word.length();
int end = i+len;
if(end > s.length())
continue;
if(s.substring(i,end).equals(word)){
if(dp[end] == null){
dp[end] = new ArrayList<String>();
}
dp[end].add(word);
}
}
}
return result;
}
result.add(path);
return;
}
This problem is also useful for solving real problems. Assuming you want to analyze
the domain names of the top 10k websites. We can use this solution to break the main
part of the domain into words and then get a sense of what kinds of websites are
popular. I did this a long time ago and found some interesting results. For example,
the most frequent words include "news", "tube", "porn", "etc".
Find the contiguous subarray within an array (containing at least one number) which
has the largest sum.
For example, given the array [−2,1,−3,4,−1,2,1,−5,4], the contiguous subarray [4,−1,2,1]
has the largest sum = 6.
This is a wrong solution, check out the discussion below to see why it is wrong. I put
it here just for fun.
public class Solution {
public int maxSubArray(int[] A) {
int sum = 0;
int maxSum = Integer.MIN_VALUE;
if (sum < 0)
sum = 0;
}
return maxSum;
}
}
The changing condition for dynamic programming is "We should ignore the sum of
the previous n-1 elements if nth element is greater than the sum."
public class Solution {
public int maxSubArray(int[] A) {
int max = A[0];
int[] sum = new int[A.length];
sum[0] = A[0];
439 | 531
179 Maximum Subarray
return max;
}
}
Find the contiguous subarray within an array (containing at least one number) which
has the largest product.
For example, given the array [2,3,-2,4], the contiguous subarray [2,3] has the largest
product = 6.
}
return max;
}
This is similar to maximum subarray. Instead of sum, the sign of number affect the
product value.
When iterating the array, each element has two possibilities: positive number or
negative number. We need to track a minimum value, so that when a negative number
441 | 531
180 Maximum Product Subarray
is given, it can also find the maximum value. We define two local variables, one tracks
the maximum and the other tracks the minimum.
public int maxProduct(int[] A) {
if(A==null || A.length==0)
return 0;
Time is O(n).
181.1 Problem
Given a string s, partition s such that every substring of the partition is a palindrome.
Return all possible palindrome partitioning of s.
For example, given s = "aab", Return
[
["aa","b"],
["a","a","b"]
]
if (s == null || s.length() == 0) {
return result;
}
return result;
}
443 | 531
181 Palindrome Partitioning
partition.add(str);
addPalindrome(s, i, partition, result);
partition.remove(partition.size() - 1);
}
}
}
left++;
right--;
}
return true;
}
The dynamic programming approach is very similar to the problem of longest palin-
drome substring.
public static List<String> palindromePartitioning(String s) {
if (s == null)
return result;
if (s.length() <= 1) {
result.add(s);
return result;
}
if (s.charAt(i) == s.charAt(j)) {
if (l == 1 || l == 2) {
table[i][j] = 1;
} else {
table[i][j] = table[i + 1][j - 1];
}
if (table[i][j] == 1) {
result.add(s.substring(i, j + 1));
}
} else {
table[i][j] = 0;
}
}
}
return result;
}
Given a string s, partition s such that every substring of the partition is a palindrome.
Return the minimum cuts needed for a palindrome partitioning of s. For example,
given s = "aab", return 1 since the palindrome partitioning ["aa","b"] could be produced
using 1 cut.
182.1 Analysis
return cut[n-1];
}
447 | 531
183 House Robber
You are a professional robber planning to rob houses along a street. Each house has
a certain amount of money stashed, the only constraint stopping you from robbing
each of them is that adjacent houses have security system connected and it will au-
tomatically contact the police if two adjacent houses were broken into on the same
night.
Given a list of non-negative integers representing the amount of money of each
house, determine the maximum amount of money you can rob tonight without alert-
ing the police.
int n = num.length;
return dp[n];
}
We can use two variables, even and odd, to track the maximum value so far as iterating
the array. You can use the following example to walk through the code.
50 1 1 50
449 | 531
183 House Robber
int even = 0;
int odd = 0;
After robbing those houses on that street, the thief has found himself a new place for
his thievery so that he will not get too much attention. This time, all houses at this
place are arranged in a circle. That means the first house is the neighbor of the last
one. Meanwhile, the security system for these houses remain the same as for those in
the previous street.
Given a list of non-negative integers representing the amount of money of each
house, determine the maximum amount of money you can rob tonight without alert-
ing the police.
184.1 Analysis
This is an extension of House Robber. There are two cases here 1) 1st element is
included and last is not included 2) 1st is not included and last is included. Therefore,
we can use the similar dynamic programming approach to scan the array twice and
get the larger value.
int n = nums.length;
if(n==1){
return nums[0];
}
if(n==2){
return Math.max(nums[1], nums[0]);
}
451 | 531
184 House Robber II
The houses form a binary tree. If the root is robbed, its left and right can not be
robbed.
185.1 Analysis
Traverse down the tree recursively. We can use an array to keep 2 values: the maximum
money when a root is selected and the maximum value when a root if NOT selected.
return result;
}
453 | 531
186 Jump Game
Given an array of non-negative integers, you are initially positioned at the first index
of the array. Each element in the array represents your maximum jump length at that
position. Determine if you are able to reach the last index. For example: A = [2,3,1,1,4],
return true. A = [3,2,1,0,4], return false.
186.1 Analysis
We can track the maximum index that can be reached. The key to solve this problem
is to find: 1) when the current position can not reach next position (return false) , and
2) when the maximum index can reach the end (return true).
The largest index that can be reached is: i + A[i].
int max = A[0]; //max stands for the largest index that can be reached.
//update max
455 | 531
186 Jump Game
return false;
}
Given an array of non-negative integers, you are initially positioned at the first index
of the array. Each element in the array represents your maximum jump length at that
position.
Your goal is to reach the last index in the minimum number of jumps.
For example, given array A = [2,3,1,1,4], the minimum number of jumps to reach the
last index is 2. (Jump 1 step from index 0 to 1, then 3 steps to the last index.)
187.1 Analysis
int lastReach = 0;
int reach = 0;
int step = 0;
return step;
}
457 | 531
188 Best Time to Buy and Sell Stock
Say you have an array for which the ith element is the price of a given stock on day i.
If you were only permitted to complete at most one transaction (ie, buy one and sell
one share of the stock), design an algorithm to find the maximum profit.
Instead of keeping track of largest element in the array, we track the maximum profit
so far.
public int maxProfit(int[] prices) {
int profit = 0;
int minElement = Integer.MAX_VALUE;
for(int i=0; i<prices.length; i++){
profit = Math.max(profit, prices[i]-minElement);
minElement = Math.min(minElement, prices[i]);
}
return profit;
}
459 | 531
189 Best Time to Buy and Sell Stock II
Say you have an array for which the ith element is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete as many trans-
actions as you like (ie, buy one and sell one share of the stock multiple times). How-
ever, you may not engage in multiple transactions at the same time (ie, you must sell
the stock before you buy again).
189.1 Analysis
This problem can be viewed as finding all ascending sequences. For example, given 5,
1, 2, 3, 4, buy at 1 & sell at 4 is the same as buy at 1 &sell at 2 & buy at 2& sell at 3 &
buy at 3 & sell at 4.
We can scan the array once, and find all pairs of elements that are in ascending
order.
461 | 531
190 Best Time to Buy and Sell Stock III
Say you have an array for which the ith element is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete at most two
transactions.
Note: A transaction is a buy & a sell. You may not engage in multiple transactions
at the same time (ie, you must sell the stock before you buy again).
190.1 Analysis
Comparing to I and II, III limits the number of transactions to 2. This can be solve
by "devide and conquer". We use left[i] to track the maximum profit for transactions
before i, and use right[i] to track the maximum profit for transactions after i. You can
use the following example to understand the Java solution:
Prices: 1 4 5 7 6 3 2 9
left = [0, 3, 4, 6, 6, 6, 6, 8]
right= [8, 7, 7, 7, 7, 7, 7, 0]
463 | 531
190 Best Time to Buy and Sell Stock III
right[prices.length - 1] = 0;
int max = prices[prices.length - 1];
for (int i = prices.length - 2; i >= 0; i--) {
max = Math.max(max, prices[i]);
right[i] = Math.max(right[i + 1], max - prices[i]);
}
int profit = 0;
for (int i = 0; i < prices.length; i++) {
profit = Math.max(profit, left[i] + right[i]);
}
return profit;
}
191.1 Problem
Say you have an array for which the ith element is the price of a given stock on
day i.Design an algorithm to find the maximum profit. You may complete at most k
transactions.
Note: You may not engage in multiple transactions at the same time (ie, you must
sell the stock before you buy again).
191.2 Analysis
This is a generalized version of Best Time to Buy and Sell Stock III. If we can solve this
problem, we can also use k=2 to solve III.
The problem can be solve by using dynamic programming. The relation is:
local[i][j] = max(global[i-1][j-1] + max(diff,0), local[i-1][j]+diff)
global[i][j] = max(local[i][j], global[i-1][j])
We track two arrays - local and global. The local array tracks maximum profit of j
transactions & the last transaction is on ith day. The global array tracks the maximum
profit of j transactions until ith day.
465 | 531
191 Best Time to Buy and Sell Stock IV
return global[k];
}
Example:
-2 (K) -3 3
-5 -10 1
10 30 -5 (P)
This problem can be solved by using dynamic programming. We maintain a 2-D table.
h[i][j] is the minimum health value before he enters (i,j). h[0][0] is the value of the
answer. The left part is filling in numbers to the table.
public int calculateMinimumHP(int[][] dungeon) {
int m = dungeon.length;
int n = dungeon[0].length;
//init dp table
int[][] h = new int[m][n];
//calculate dp table
for (int i = m - 2; i >= 0; i--) {
for (int j = n - 2; j >= 0; j--) {
int down = Math.max(h[i + 1][j] - dungeon[i][j], 1);
int right = Math.max(h[i][j + 1] - dungeon[i][j], 1);
h[i][j] = Math.min(right, down);
}
}
return h[0][0];
467 | 531
192 Dungeon Game
A message containing letters from A-Z is being encoded to numbers using the follow-
ing mapping:
’A’ ->1 ’B’ ->2 ... ’Z’ ->26
Given an encoded message containing digits, determine the total number of ways
to decode it.
193.1 Analysis
//if(s.charAt(0)!=’0’)
if(isValid(s.substring(0,1)))
t[1]=1;
else
t[1]=0;
if(isValid(s.substring(i-2,i))){
t[i]+=t[i-2];
}
}
return t[s.length()];
}
469 | 531
193 Decode Ways
The longest common subsequence (LCS) problem is the problem of finding the longest
subsequence common to all sequences in a set of sequences (often just two sequences).
194.1 Analysis
471 | 531
194 Longest Common Subsequence
return dp[m][n];
}
In computer science, the longest common substring problem is to find the longest
string that is a substring of two or more strings.
195.1 Analysis
Given two strings a and b, let dp[i][j] be the length of the common substring ending
at a[i] and b[j].
The dp table looks like the following given a="abc" and b="abcd".
473 | 531
195 Longest Common Substring
int max = 0;
}
}
return max;
}
This is a similar problem like longest common subsequence. The difference of the
solution is that for this problem when a[i]!=b[j], dp[i][j] are all zeros by default. How-
ever, in the longest common subsequence problem, dp[i][j] values are carried from the
previous values, i.e., dp[i-1][j] and dp[i][j-1].
Given an unsorted array of integers, find the length of longest increasing subsequence.
For example, given [10, 9, 2, 5, 3, 7, 101, 18], the longest increasing subsequence is
[2, 3, 7, 101]. Therefore the length is 4.
Let max[i] represent the length of the longest increasing subsequence so far. If any
element before i is smaller than nums[i], then max[i] = max(max[i], max[j]+1).
Here is an example:
475 | 531
196 Longest Increasing Subsequence
int result = 0;
for(int i=0; i<max.length; i++){
if(max[i]>result)
result = max[i];
}
return result;
}
return 0;
while(i<j){
int mid = (i+j)/2;
if(list.get(mid) < num){
i=mid+1;
}else{
j=mid;
}
}
list.set(j, num);
}
}
return list.size();
}
You are given coins of different denominations and a total amount of money amount.
Write a function to compute the fewest number of coins that you need to make up that
amount. If that amount of money cannot be made up by any combination of the coins,
return -1.
Let dp[v] to be the minimum number of coins required to get the amount v.
dp[i+a_coin] = min(dp[i+a_coin], dp[i]+1) if dp[i] is reachable.
dp[i+a_coin] = dp[i+a_coin] is dp[i] is not reachable.
We initially set dp[i] to be MAX_VALUE.
return dp[amount];
}
479 | 531
197 Coin Change
if (temp == amount)
return step;
return -1;
}
The problem:
Given an array of integers, every element appears twice except for one. Find that single
one.
The key to solve this problem is bit manipulation. XOR will return 1 only on two
different bits. So if two numbers are the same, XOR will return 0. Finally only one
number left.
public int singleNumber(int[] A) {
int x = 0;
for (int a : A) {
x = x ^ a;
}
return x;
}
481 | 531
199 Single Number II
199.1 Problem
Given an array of integers, every element appears three times except for one. Find that
single one.
483 | 531
200 Twitter Codility Problem Max Binary
Gap
while (N > 0) {
// get right most bit & shift right
r = N & 1;
N = N >> 1;
if (1 == r) {
max = count > max ? count : max;
count = 0;
}
}
return max;
}
Time is O(n).
485 | 531
200 Twitter Codility Problem Max Binary Gap
while (N > 0) {
int k = N & -N;
N = N & (N - 1);
return len;
}
Time is O(log(n)).
201.1 Problem
Write a function that takes an unsigned integer and returns the number of ’1’ bits it
has (also known as the Hamming weight).
For example, the 32-bit integer ’11’ has binary representation 00000000000000000000000000001011,
so the function should return 3.
487 | 531
202 Reverse Bits
202.1 Problem
return n;
}
if ((a ^ b) != 0) {
return n ^= (1 << i) | (1 << j);
}
return n;
}
489 | 531
203 Repeated DNA Sequences
203.1 Problem
The key to solve this problem is that each of the 4 nucleotides can be stored in 2 bits.
So the 10-letter-long sequence can be converted to 20-bits-long integer. The following
is a Java solution. You may use an example to manually execute the program and see
how it works.
public List<String> findRepeatedDnaSequences(String s) {
List<String> result = new ArrayList<String>();
int hash = 0;
for (int i = 0; i < len; i++) {
if (i < 9) {
//each ACGT fit 2 bits, so left shift 2
hash = (hash << 2) + map.get(s.charAt(i));
} else {
491 | 531
203 Repeated DNA Sequences
return result;
}
The key to solve this problem is bitwise AND consecutive numbers. You can use the
following example to walk through the code.
8 4 2 1
---------------
5 | 0 1 0 1
6 | 0 1 1 0
7 | 0 1 1 1
493 | 531
205 Power of Two
205.1 Analysis
If a number is power of 2, it’s binary form should be 10...0. So if we right shift a bit of
the number and then left shift a bit, the value should be the same when the number
>= 10(i.e.,2).
while(n>2){
int t = n>>1;
int c = t<<1;
if(n-c != 0)
return false;
n = n>>1;
}
return true;
}
495 | 531
206 Counting Bits
Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤
num calculate the number of 1’s in their binary representation and return them as an
array.
Example:
For num = 5 you should return [0,1,1,2,1,2].
We can simply count bits for each number like the following:
public int[] countBits(int num) {
int[] result = new int[num+1];
return result;
}
while(num!=0){
if(num%2==1){
result++;
}
num = num/2;
}
return result;
}
For number 2(10), 4(100), 8(1000), 16(10000), ..., the number of 1’s is 1. Any other
number can be converted to be 2m̂ + x. For example, 9=8+1, 10=8+2. The number of
1’s for any other number is 1 + # of 1’s in x.
497 | 531
206 Counting Bits
return result;
}
Given a string array words, find the maximum value of length(word[i]) * length(word[j])
where the two words do not share common letters. You may assume that each word
will contain only lower case letters. If no such two words exist, return 0.
int result = 0;
return result;
}
499 | 531
208 Permutations
Loop through the array, in each iteration, a new number is added to different loca-
tions of results of previous iteration. Start from an empty List.
public ArrayList<ArrayList<Integer>> permute(int[] num) {
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
501 | 531
208 Permutations
current.add(temp);
//System.out.println(temp);
return result;
}
We can also recursively solve this problem. Swap each element with each element
after it.
public ArrayList<ArrayList<Integer>> permute(int[] num) {
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
permute(num, 0, result);
return result;
}
Given a collection of numbers that might contain duplicates, return all possible unique
permutations.
For example, [1,1,2] have the following unique permutations:
[1,1,2], [1,2,1], and [2,1,1].
For each number in the array, swap it with every element after it. To avoid duplicate,
we need to check the existing sequence first.
505 | 531
209 Permutations II
item.add(num[h]);
}
return item;
}
return returnList;
}
Given n and k, return the kth permutation sequence. (Note: Given n will be between
1 and 9 inclusive.)
// change k to be index
k--;
// set factorial of n
int mod = 1;
for (int i = 1; i <= n; i++) {
mod = mod * i;
}
// find sequence
for (int i = 0; i < n; i++) {
mod = mod / (n - i);
// find the right number(curIndex) of
int curIndex = k / mod;
507 | 531
210 Permutation Sequence
// update k
k = k % mod;
return result.toString();
}
}
output[s - 1] = true;
buf.append(Integer.toString(s));
}
return buf.toString();
}
}
if(left==0&&right==0){
result.add(s);
return;
}
if(left>0){
dfs(result, s+"(", left-1, right);
}
if(right>0){
dfs(result, s+")", left, right-1);
}
}
509 | 531
211 Generate Parentheses
This solution looks more complicated. ,You can use n=2 to walk though the code.
public List<String> generateParenthesis(int n) {
ArrayList<String> result = new ArrayList<String>();
ArrayList<Integer> diff = new ArrayList<Integer>();
result.add("");
diff.add(0);
if (i < 2 * n - 1) {
temp1.add(s + "(");
temp2.add(k + 1);
}
return result;
}
Given a set of candidate numbers (C) and a target number (T), find all unique combi-
nations in C where the candidate numbers sums to T. The same repeated number may
be chosen from C unlimited number of times.
Note: All numbers (including target) will be positive integers. Elements in a combi-
nation (a1, a2, ... , ak) must be in non-descending order. (ie, a1 <= a2 <= ... <= ak). The
solution set must not contain duplicate combinations. For example, given candidate
set 2,3,6,7 and target 7, A solution set is:
[7]
[2, 2, 3]
212.1 Thoughts
The first impression of this problem should be depth-first search(DFS). To solve DFS
problem, recursion is a normal implementation.
Note that the candidates array is not sorted, we need to sort it first.
return result;
}
511 | 531
212 Combination Sum
return;
}
curr.add(candidates[i]);
combinationSum(candidates, target - candidates[i], i, curr, result);
curr.remove(curr.size()-1);
}
}
Given a collection of candidate numbers (C) and a target number (T), find all unique
combinations in C where the candidate numbers sums to T. Each number in C may
only be used ONCE in the combination.
Note: 1) All numbers (including target) will be positive integers. 2) Elements in a
combination (a1, a2, . . . , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ . . . ≤
ak). 3) The solution set must not contain duplicate combinations.
Arrays.sort(num);
return result;
}
513 | 531
213 Combination Sum II
continue;
temp.add(num[i]);
getCombination(num, i+1, target-num[i], temp, result);
temp.remove(temp.size()-1);
}
}
Find all possible combinations of k numbers that add up to a number n, given that
only numbers from 1 to 9 can be used and each combination should be a unique set
of numbers.
Ensure that numbers within the set are sorted in ascending order.
Example 1: Input: k = 3, n = 7 Output: [[1,2,4]] Example 2: Input: k = 3, n = 9
Output: [[1,2,6], [1,3,5], [2,3,4]]
214.1 Analysis
list.add(i);
dfs(result, i+1, sum-i, list, k);
list.remove(list.size()-1);
}
}
515 | 531
214 Combination Sum III
215.1 Problem
Given two integers n and k, return all possible combinations of k numbers out of 1 ...
n.
For example, if n = 4 and k = 2, a solution is:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
This is my naive solution. It passed the online judge. I first initialize a list with only
one element, and then recursively add available elements to it.
public ArrayList<ArrayList<Integer>> combine(int n, int k) {
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
//illegal case
if (k > n) {
return null;
//if k==n
} else if (k == n) {
ArrayList<Integer> temp = new ArrayList<Integer>();
for (int i = 1; i <= n; i++) {
temp.add(i);
}
result.add(temp);
return result;
//if k==1
} else if (k == 1) {
517 | 531
215 Combinations
result.add(temp);
}
return result;
}
return result;
}
if(result.get(0).size() == k) return;
result.clear();
for (ArrayList<Integer> one : prevResult) {
combine(n, k, result);
}
if (n <= 0 || n < k)
return result;
return result;
}
Given a digit string, return all possible letter combinations that the number could
represent. (Check out your cellphone to see the mappings) Input:Digit string "23",
Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
216.1 Analysis
This problem can be solves by a typical DFS algorithm. DFS problems are very similar
and can be solved by using a simple recursion. Check out the index page to see other
DFS problems.
return result;
}
521 | 531
216 Letter Combinations of a Phone Number
if(digits.length() == 0){
char[] arr = new char[temp.size()];
for(int i=0; i<temp.size(); i++){
arr[i] = temp.get(i);
}
result.add(String.valueOf(arr));
return;
}
Given a string containing only digits, restore it by returning all possible valid IP ad-
dress combinations.
For example: given "25525511135",return ["255.255.11.135", "255.255.111.35"].
for(ArrayList<String> l: result){
StringBuilder sb = new StringBuilder();
for(String str: l){
sb.append(str+".");
}
sb.setLength(sb.length() - 1);
finalResult.add(sb.toString());
}
return finalResult;
}
523 | 531
217 Restore IP Addresses
return;
}
t.add(sub);
dfs(result, s, start+i, t);
t.remove(t.size()-1);
}
}
We can convert the integer to a string/char array, reverse the order, and convert the
string/char array back to an integer. However, this will require extra space for the
string. It doesn’t seem to be the right way, if you come with such a solution.
int res = 0;
int p = x;
while (p > 0) {
int mod = p % 10;
p = p / 10;
res = res * 10 + mod;
}
if (flag) {
res = 0 - res;
}
return res;
}
525 | 531
218 Reverse Integer
return rev;
}
As we form a new integer, it is possible that the number is out of range. We can use
the following code to assign the newly formed integer. When it is out of range, throw
an exception.
try{
result = ...;
}catch(InputMismatchException exception){
System.out.println("This is not an integer");
}
219.1 Thoughts
while (x != 0) {
int left = x / div;
int right = x % 10;
if (left != right)
return false;
x = (x % div) / 10;
div /= 100;
}
return true;
}
}
527 | 531
220 Pow(x, n)
Problem:
Implement pow(x, n).
This is a great example to illustrate how to solve a problem during a technical
interview. The first and second solution exceeds time limit; the third and fourth are
accepted.
First of all, assuming n is not negative, to calculate x to the power of n, we can simply
multiply x n times, i.e., x * x * ... * x. The time complexity is O(n). The implementation
is as simple as:
public class Solution {
public double pow(double x, int n) {
if(x == 0) return 0;
if(n == 0) return 1;
double result=1;
for(int i=1; i<=n; i++){
result = result * x;
}
return result;
}
}
Naturally, we next may think how to do it in O(logn). We have a relation that xn̂ =
ˆ
x(n/2) * xˆ(n/2) * xˆ(n
public static double pow(double x, int n) {
if(n == 0)
return 1;
if(n == 1)
return x;
529 | 531
220 Pow(x, n)
The accepted solution is also recursive, but does division first. Time complexity is
O(nlog(n)). The key part of solving this problem is the while loop.
public double pow(double x, int n) {
if (n == 0)
return 1;
if (n == 1)
return x;
int k = 1;
//the key part of solving this problem
while (pn / 2 > 0) {
result = result * result;
pn = pn / 2;
k = k * 2;
}
result = 1 / result;
return result;
}
if (n % 2 == 0) {
return v * v;
} else {
return v * v * x;
}
}