JAVA Coding Interview Questions and Answers PDF
JAVA Coding Interview Questions and Answers PDF
Program Creek
3 Isomorphic Strings 14
4 Word Ladder 15
7 Merge Intervals 22
8 Insert Interval 24
9 Two Sum 26
12 3Sum 29
13 4Sum 31
14 3Sum Closest 33
17 Valid Parentheses 36
18 Implement strStr() 37
2 | 247
Contents
22 Valid Palindrome 44
23 ZigZag Conversion 47
24 Add Binary 48
26 Triangle 50
27 Contains Duplicate 52
28 Contains Duplicate II 52
38 Min Stack 68
39 Majority Element 70
40 Remove Element 71
43 Largest Number 74
44 Simplify Path 75
46 Gas Station 77
47 Pascals Triangle 79
48 Pascals Triangle II 80
53 Anagrams 86
55 Shortest Palindrome 88
57 Spiral Matrix 91
58 Spiral Matrix II 94
59 Search a 2D Matrix 95
60 Rotate Image 96
61 Valid Sudoku 98
113 Solution Sort a linked list using insertion sort in Java 187
You may have been using Java for a while. Do you think a simple Java array question
can be a challenge? Lets 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().
9 | 247
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. Rotate first part: 4,3,2,1,5,6
3. Rotate second part: 4,3,2,1,6,5
4. Rotate the whole array: 5,6,1,2,3,4
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.
11 | 247
2 Evaluate Reverse Polish Notation
The following is the code. However, this code contains compilation errors in leet-
code. Why?
public class Test {
case "/":
stack.push(String.valueOf(b / a));
break;
}
}
}
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));
returnValue = Integer.valueOf(stack.pop());
return returnValue;
}
}
3 Isomorphic Strings
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 values
key in the map.
if(s.length() != t.length())
return false;
14 | 247
}else if(map.containsKey(c1)){
if(c2 != map.get(c1))
return false;
}else{
map.put(c1,c2);
}
}
return true;
}
return null;
}
4 Word Ladder
Given two words (start and end), and a dictionary, find the length of shortest trans-
formation 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.
Note: Return 0 if there is no such transformation sequence. All words have the same
length. All words contain only lowercase alphabetic characters.
4.1 Naive Approach
In a simplest way, we can start from start word, change one character each time, if it
is in the dictionary, we continue with the replaced word, until start == end.
public class Solution {
public int ladderLength(String start, String end, HashSet<String> dict) {
15 | 247
4 Word Ladder
int len=0;
HashSet<String> visited = new HashSet<String>();
startArr[i] = c;
String temp = new String(startArr);
if(dict.contains(temp)){
len++;
start = temp;
if(temp.equals(end)){
return len;
}
}
}
}
return len;
}
}
This solution is wrong. The following example shows the problem. It can not find
the shortest path. The output is 3, but it actually only takes 2.
Input: "a", "c", ["a","b","c"]
Output: 3
Expected: 2
So we quickly realize that this looks like a tree searching problem for which breath
first guarantees the optimal solution.
Assuming we have some words in the dictionary, and the start is "hit" as shown in
the diagram below.
We can use two queues to traverse the tree, one stores the nodes, the other stores the
step numbers.
public int ladderLength(String start, String end, HashSet<String> dict) {
if (dict.size() == 0)
return 0;
dict.add(end);
wordQueue.add(start);
distanceQueue.add(1);
if (currWord.equals(end)) {
result = Math.min(result, currDistance);
}
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)).
5.1 Analysis
18 | 247
5 Median of Two Sorted Arrays Java
int n = B.length;
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;
}
}
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.
20 | 247
6 Regular Expression Matching in Java
if(p.length() == 0)
return s.length() == 0;
}else{
int len = s.length();
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) {
//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;
}
}
7 Merge Intervals
Problem:
Given a collection of intervals, merge all overlapping intervals.
22 | 247
7 Merge 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;
}
}
result.add(prev);
return result;
}
}
8 Insert Interval
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].
24 | 247
8 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) {
return result;
}
}
9 Two Sum
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?
26 | 247
9.2 Better Solution
return result;
}
}
Time complexity depends on the put and get operations of HashMap which is nor-
mally O(1).
int i = 0;
int j = numbers.length - 1;
while (i < j) {
int x = numbers[i] + numbers[j];
if (x < target) {
++i;
27 | 247
} else if (x > target) {
j--;
} else {
return new int[] { i + 1, j + 1 };
}
}
return null;
}
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>();
28 | 247
if (elements.containsKey(target)) {
if (i == target && elements.get(target) < 2) {
continue;
}
return true;
}
}
return false;
}
}
12 3Sum
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);
29 | 247
12 3Sum
each.add(num[i]);
each.add(num[j]);
each.add(num[k]);
result.add(each);
each.clear();
}
}
}
}
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;
result.add(temp);
start++;
end--;
//avoid duplicate solutions
while (start < end && num[end] == num[end + 1])
end--;
}
}
return result;
}
13 4Sum
31 | 247
13 4Sum
(-1, 0, 0, 1)
(-2, -1, 1, 2)
(-2, 0, 0, 2)
13.1 Thoughts
while (k < l) {
int sum = num[i] + num[j] + num[k] + 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());
}
14 3Sum Closest
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).
14.1 Thoughts
This problem is similar with 2 Sum. This kind of problem can be solve by using similar
approach, i.e., two pointers from both left and right.
Arrays.sort(num);
if(diff == 0) return 0;
33 | 247
if (diff < min) {
min = diff;
result = sum;
}
if (sum <= target) {
j++;
} else {
k--;
}
}
}
return result;
}
}
(atoi)
15.1 Analysis
34 | 247
str = str.trim();
char flag = +;
// calculate value
while (str.length() > i && str.charAt(i) >= 0 && str.charAt(i) <= 9) {
result = result * 10 + (str.charAt(i) - 0);
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.
35 | 247
16.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.
public void merge(int A[], int m, int B[], int n) {
int i = m - 1;
int j = n - 1;
int k = m + n - 1;
while (k >= 0) {
if (j < 0 || (i >= 0 && A[i] > B[j]))
A[k--] = A[i--];
else
A[k--] = B[j--];
}
}
36 | 247
17 Valid Parentheses
17.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();
}
37 | 247
18 Implement strStr()
18 Implement strStr()
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;
}
int h = haystack.length();
int n = needle.length();
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;
}
39 | 247
19 Minimum Size Subarray Sum
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 isnt 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.
19.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 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);
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
20.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;
41 | 247
if(target <= A[0]) return 0;
return A.length;
}
}
20.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) {
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 ele-
ments sequence.
42 | 247
21 Longest Consecutive 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.
21.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--;
}
while (set.contains(right)) {
count++;
set.remove(right);
right++;
}
return max;
}
of consecutive sequence, and m==n, then the time complexity is O(n2). The
reason is that in this case, no element is removed from the set each time. You
Palindrome
22.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.
44 | 247
22 Valid Palindrome
int i=0;
int j=len-1;
while(i<j){
char left, right;
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));
}
}
23 ZigZag Conversion
And then read line by line: "PAHNAPLSIIGYIR" Write the a method convert("PAYPALISHIRING",
3) which returns "PAHNAPLSIIGYIR".
23.1 Java Solution
47 | 247
return s;
return sb.toString();
}
24 Add Binary
Given two binary strings, return their sum (also a binary string).
For example, a = "11", b = "1", the return is "100".
24.1 Java Solution
48 | 247
if(b==null || b.length()==0)
return a;
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){
sb.append("1");
}
49 | 247
25.1 Java Solution
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;
}
26 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]
]
50 | 247
26 Triangle
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;
}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];
}
27 Contains Duplicate
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.
27.1 Java Solution
return false;
}
52 | 247
28 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.
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].
53 | 247
29 Remove Duplicates from Sorted Array
29.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.
29.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 arrays size can
not be changed once created, there is no way we can return the original array with
correct results.
29.3 Solution 2
int j = 0;
int i = 1;
return B;
}
29.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);
}
55 | 247
30 Remove Duplicates from Sorted Array II
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].
30.1 Naive Approach
Given the method signature "public int removeDuplicates(int[] A)", it seems that we
should write a method that returns a integer and thats 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;
}
}
We can not change the given arrays 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.
31.1 Java Solution 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) {
boolean[] flag = new boolean[256];
int result = 0;
int start = 0;
char[] arr = s.toCharArray();
58 | 247
31 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 position.
When a repeated character occurs, check from the previously repeated character. How-
ever, the time complexity is higher - O(n3).
public static int lengthOfLongestSubstring(String s) {
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
In this solution, a hashmap is used to track the right most index of 2 unique elements
in the map. When a third character is being added to the map, the left pointer needs
to move to the leftmost position in the map.
You can use "abac" to walk through this solution.
public static String maxSubString2UniqueChars(String s) {
int maxLen = 0;
String maxSubstring = null;
int m = 0;
// declare a map to track the right most position of the two characters
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
60 | 247
32 Longest Substring Which Contains 2 Unique Characters
m = leftMost + 1;
map.remove(s.charAt(leftMost));
}
map.put(c, i);
}
return maxSubstring;
}
Now if this question is extended to be "the longest substring that contains k unique
characters", what should we do? Apparently, the solution above is not scalable.
The above solution can be extended to be a more general solution which would allow
k distinct characters.
public static String maxSubStringKUniqueChars(String s, int k) {
int maxLen = 0;
String maxSubstring = null;
int m = 0;
// declare a map to track the right most position of the two characters
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
m = leftMost + 1;
map.remove(s.charAt(leftMost));
}
map.put(c, i);
}
return maxSubstring;
}
if(map.size() == k+1){
//get maximum
int range = i-start;
if(range > maxLen){
maxLen = range;
maxSubstring = s.substring(start, i);
//move left cursor toward right, so that substring contains only k chars
char first = s.charAt(start);
while(map.size()>k){
int count = map.get(first);
if(count>1){
map.put(first,count-1);
}else{
map.remove(first);
}
start++;
}
}
}
return maxSubstring;
}
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".
63 | 247
}
}
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++;
}
}
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;
}
64 | 247
34 Reverse Words in a String
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 "";
}
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.
35.1 Thoughts
When we search something from a sorted array, binary search is almost a top choice.
Binary search is efficient for sorted arrays.
65 | 247
This problems seems like a binary search, and the key is how to break the array to
two parts, so that we only need to work on half of the array each time, i.e., when to
select the left half and when to select the right half.
If we pick the middle element, we can compare the middle element with the left-end
element. If middle is less than leftmost, the left half should be selected; if the middle
is greater than the leftmost, the right half should be selected. Using simple recursion,
this problem can be solve 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];
// go right side
} else if (num[middle] > num[left]) {
return findMin(num, middle, right);
// go left side
} else {
return findMin(num, left, middle);
}
}
66 | 247
36 Find Minimum in Rotated Sorted
Array II
36.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);
}
67 | 247
37 Find Peak Element
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.
37.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;
}
}
68 | 247
38 Min Stack
38 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.
38.1 Thoughts
An array is a perfect fit for this problem. We can use a integer to track the top of the
stack. You can use the Stack class from Java SDK, but I think a simple array is more
efficient and more beautiful.
class MinStack {
private int[] arr = new int[100];
private int index = -1;
39 Majority Element
Problem:
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. You may assume that the array is
non-empty and the majority element always exist in the array.
39.1 Java Solution 1
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;
}
}
70 | 247
39.2 Java Solution 2 - Much Simpler
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!
public int majorityElement(int[] num) {
if (num.length == 1) {
return num[0];
}
Arrays.sort(num);
return num[num.length / 2];
}
40 Remove Element
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 doesnt matter what
you leave beyond the new length.)
40.1 Java Solution
j++;
}
return i;
}
71 | 247
41 Largest Rectangle in Histogram
Given n non-negative integers representing the histograms bar height where the
width of each bar is 1, find the area of largest rectangle in the histogram.
The key to solve this problem is to maintain a stack to store bars indexes. The stack
only keeps the increasing bars.
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;
}
42.1 Problem
Write a function to find the longest common prefix string amongst an array of strings.
42.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.
73 | 247
42.3 Java Solution
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);
}
43 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.)
43.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.
74 | 247
43.2 Java Solution
44 Simplify Path
//stack.push(path.substring(0,1));
75 | 247
while(path.length()> 0 && path.charAt(path.length()-1) ==/){
path = path.substring(0, path.length()-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){
back--;
}else{
result.push(top);
}
}
}
return sb.toString();
}
76 | 247
45 Compare Version Numbers
45.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;
}
77 | 247
46 Gas Station
46 Gas Station
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 stations index if you can travel around the circuit once,
otherwise return -1.
46.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.
In the following solution, sumRemaining tracks the sum of remaining to the current
index. If sumRemaining <0, then every index between old start and current index is
bad, and we need to update start to be the current index.
47 Pascals Triangle
Given numRows, generate the first numRows of Pascals 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]
]
79 | 247
pre.add(1);
result.add(pre);
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;
}
48 Pascals Triangle II
Given an index k, return the kth row of the Pascals triangle. For example, when k
= 3, the row is [1,3,3,1].
48.1 Analysis
This problem is related to Pascals Triangle which gets all rows of Pascals triangle. In
this problem, only one row is required to return.
80 | 247
public List<Integer> getRow(int rowIndex) {
ArrayList<Integer> result = new ArrayList<Integer>();
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;
}
49.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.
49.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.
81 | 247
49.3 Java Solution
int max = 0;
int left = 0;
int right = height.length - 1;
return max;
}
50.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)
82 | 247
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++;
}
return result;
}
Given a sorted array of integers, find the starting and ending position of a given
target value. Your algorithms 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].
51.1 Java Solution
83 | 247
for(int i=0; i< nums.length; i++){
if(nums[i]==target){
result.add(i);
}
}
if(result.size() == 0){
arr[0]=-1;
arr[1]=-1;
}else{
arr[0] = result.get(0);
arr[1] = result.get(result.size()-1);
}
return arr;
}
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 arrays length.
52.1 Java Solution 1
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;
84 | 247
}
while (true) {
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);
}
}
85 | 247
53 Anagrams
Given an array of strings, return all groups of strings that are anagrams.
53.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. There-
fore, this problem can be seen as a problem of finding duplicate elements.
for(ArrayList<Integer> l: map.values()){
if(l.size() > 1){
for(Integer i: l){
result.add(strs[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.
54.1 Analysis
This problem can solve by using a bucket-sort like algorithm. Lets 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]]
int firstMissingPositiveAnd0(int A[], int n) {
for (int i = 0; i < n; i++) {
// when the ith element is not i
while (A[i] != i) {
// no need to swap when ith element is out of range [0,n]
if (A[i] < 0 || A[i] >= n)
break;
// swap elements
int temp = A[i];
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.
int firstMissingPositive(int A[], int n) {
87 | 247
for (int i = 0; i < n; i++) {
while (A[i] != i + 1) {
if (A[i] <= 0 || A[i] > n)
break;
55 Shortest Palindrome
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.
88 | 247
if (s.charAt(i) == s.charAt(i - 1)) {
if ((result = scanFromCenter(s, i - 1, i)) != null)
return result;
} else {
if ((result = scanFromCenter(s, i - 1, i - 1)) != null)
return result;
}
}
return result;
}
return sb.append(s).toString();
}
89 | 247
56 Set Matrix Zeroes
}
}
57 Spiral Matrix
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;
91 | 247
57 Spiral Matrix
result.add(matrix[x][y++]);
}
break;
}else if(n==1){
for(int i=0; i<m; i++){
result.add(matrix[x++][y]);
}
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 solutions performance is not better
than Solution or as clear as Solution 1. Therefore, Solution 1 should be preferred.
public class Solution {
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));
58 Spiral Matrix II
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--;
94 | 247
while(y>=0+step){
i++;
result[x][y]=i;
y--;
}
y++;
x--;
step++;
while(x>=0+step){
i++;
result[x][y]=i;
x--;
}
x++;
y++;
}
return result;
}
59 Search a 2D Matrix
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]
]
95 | 247
using binary search.
public class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
if(matrix==null || matrix.length==0 || matrix[0].length==0)
return false;
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;
if(matrix[midX][midY]<target){
start=mid+1;
}else{
end=mid-1;
}
}
return false;
}
}
60 Rotate Image
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) {
96 | 247
60 Rotate Image
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;
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;
}
}
}
61 Valid Sudoku
Determine if a Sudoku is valid. The Sudoku board could be partially filled, where
empty cells are filled with the character ..
98 | 247
// check each column
for (int i = 0; i < 9; i++) {
boolean[] m = new boolean[9];
for (int j = 0; j < 9; j++) {
if (board[i][j] != .) {
if (m[(int) (board[i][j] - 1)]) {
return false;
}
m[(int) (board[i][j] - 1)] = true;
}
}
}
return true;
}
99 | 247
62 Minimum Path Sum
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.
62.1 Java Solution 1: Depth-First Search
A native solution would be depth-first search. Its 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;
}
int m = grid.length;
int n = grid[0].length;
return dp[m-1][n-1];
}
63 Unique Paths
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?
63.1 Java Solution 1 - DFS
101 | 247
}
if(i<m-1){
return dfs(i+1,j,m,n);
}
if(j<n-1){
return dfs(i,j+1,m,n);
}
return 0;
}
//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];
}
102 | 247
64 Unique Paths II
64 Unique Paths II
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
for(int i=1; i<n; i++){
if(obstacleGrid[0][i]==1){
}
}
return dp[m-1][n-1];
}
65 Number of Islands
Given a 2-d grid map of 1s (land) and 0s (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
104 | 247
65.1 Java Solution
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 count = 0;
66 Surrounded Regions
105 | 247
66 Surrounded Regions
X X X X
X O O X
X X O X
X O X X
66.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 Os on the boarders like
in Number of Islands and replace Os with #, and then scan the board and replace all
Os left (if any).
int m = board.length;
int n = board[0].length;
if(board[i][n-1] == O){
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][0] == O) {
bfs(board, i, 0);
}
if (board[i][n - 1] == O) {
bfs(board, i, n - 1);
}
}
if (board[m - 1][j] == O) {
bfs(board, m - 1, j);
}
}
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] = #;
}
}
67 Maximal Rectangle
Given a 2D binary matrix filled with 0s and 1s, find the largest rectangle containing
all ones and return its area.
67.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;
}
}
}
109 | 247
}
}
return maxArea;
}
int i = 0;
int max = 0;
return max;
}
The problem:
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
68.1 Thoughts
110 | 247
68 Add Two Numbers
68.2 Solution 1
ListNode p1 = l1;
ListNode p2 = l2;
if(flag){
val = p1.val + p2.val + 1;
}else{
val = p1.val + p2.val;
}
if(flag){
val = p2.val + 1;
if(val >= 10){
flag = true;
}else{
flag = false;
}
}else{
val = p2.val;
flag = false;
}
if(flag){
val = p1.val + 1;
if(val >= 10){
flag = true;
}else{
flag = false;
}
}else{
val = p1.val;
flag = false;
}
p3 = p3.next;
}
return newHead.next;
}
}
The hard part is how to make the code more readable. Adding some internal com-
ments and refactoring some code are helpful.
There is nothing wrong with solution 1, but the code is not readable. We can refactor
the code and make it much shorter and cleaner.
public class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
int carry =0;
if(p2 != null){
carry += p2.val;
p2 = p2.next;
}
if(carry==1)
p3.next=new ListNode(1);
return newHead.next;
}
}
68.4 Quesion
What is the digits are stored in regular order instead of reversed order?
113 | 247
69 Reorder List
Answer: We can simple reverse the list, calculate the result, and reverse the result.
69 Reorder List
Given a singly linked list L: L0L1 ... Ln-1Ln, reorder it to: L0LnL1Ln-
1L2Ln-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.
69.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;
}
}
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:
117 | 247
70 Linked List Cycle
70.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(head == null)
return false;
if(head.next == null)
return false;
if(slow == fast)
return true;
}
return false;
}
}
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.
119 | 247
71 Copy List with Random Pointer
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;
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){
From Xiaomengs 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;
}
121 | 247
72 Merge Two Sorted Lists
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.
72.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;
p = p.next;
}
if(p1 != null)
p.next = p1;
return fakeHead.next;
}
}
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its
complexity.
73.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;
}
}
123 | 247
public int compare(ListNode a, ListNode b) {
if (a.val > b.val)
return 1;
else if(a.val == b.val)
return 0;
else
return -1;
}
});
p = p.next;
}
return head.next;
}
}
List
Given a sorted linked list, delete all duplicates such that each element appear only
once.
For example,
124 | 247
74 Remove Duplicates from Sorted List
74.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.
74.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
}else{
prev = p;
p = p.next;
}
}
return head;
}
}
ListNode p = head;
return head;
}
}
75 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.
75.1 Naive Solution (Wrong)
The following is a solution I write at the beginning. It contains a trivial problem, but
it took me a long time to fix it.
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
126 | 247
75 Partition List
*/
public class Solution {
public ListNode partition(ListNode head, int x) {
if(head == null) return null;
ListNode p = head;
ListNode prev = fakeHead1;
ListNode p2 = fakeHead2;
while(p != null){
if(p.val < 3){
p = p.next;
prev = prev.next;
}else{
prev.next = p.next;
p2.next = p;
p = prev.next;
p2 = p2.next;
}
}
p.next = fakeHead2.next;
return fakeHead1.next;
}
}
The problem of the first solution is that the last nodes next element should be set to
null.
public class Solution {
public ListNode partition(ListNode head, int x) {
if(head == null) return null;
ListNode p = head;
ListNode prev = fakeHead1;
ListNode p2 = fakeHead2;
while(p != null){
p2.next = p;
prev.next = p.next;
p = prev.next;
p2 = p2.next;
}
}
prev.next = fakeHead2.next;
return fakeHead1.next;
}
}
76 LRU Cache
76.1 Problem
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.
The key to solve this problem is using a double linked list which enables us to quickly
move nodes.
128 | 247
76 LRU Cache
import java.util.HashMap;
if (pre != null) {
pre.next = post;
} else {
head = post;
}
if (post != null) {
post.pre = pre;
} else {
end = pre;
}
}
head = node;
if (end == null) {
end = node;
}
}
setHead(newNode);
map.put(key, newNode);
}
}
}
}
class DoubleLinkedListNode {
public int val;
77.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 {
131 | 247
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;
}
while(p2 !=null){
len2++;
p2 = p2.next;
}
int diff = 0;
p1=headA;
p2=headB;
}
p1 = p1.next;
p2 = p2.next;
}
return null;
}
}
132 | 247
78 Remove Linked List Elements
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;
}
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.
79.1 Java Solution
Use two template variable to track the previous and next node of each pair.
133 | 247
public ListNode swapPairs(ListNode head) {
if(head == null || head.next == null)
return head;
return h.next;
}
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;
134 | 247
}else{
break;
}
}
return p2;
}
return rest;
}
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.
81.1 Java Solution 1 - Naive Two Passes
Calculate the length first, and then remove the nth from the beginning.
public ListNode removeNthFromEnd(ListNode head, int n) {
if(head == null)
return null;
135 | 247
81 Remove Nth Node From End of List
len++;
p = p.next;
}
return head;
}
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.next = slow.next.next;
return head;
}
The following examples shows the basic operations of PriorityQueue such as offer(),
peek(), poll(), and size().
import java.util.Comparator;
import java.util.PriorityQueue;
137 | 247
// instead of self-defined comparator
for (int x : ia) {
pq2.offer(x);
}
// 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]
138 | 247
83 Solution for Binary Tree Preorder Traversal in Java
Traversal in Java
Preorder binary tree traversal is a classic interview problem about trees. The key to
solve this problem is to understand the following:
It is not obvious what preorder for some strange cases. However, if you draw a
stack and manually execute the program, how each element is pushed and popped is
obvious.
The key to solve this problem is using a stack to store left and right children, and
push right child first so that it is processed after the left child.
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
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);
}
The key to solve inorder traversal of binary tree includes the following:
The order of "inorder" is: left child ->parent ->right child
Use a stack to track nodes
Understand when to push node into the stack and when to pop node out of the
stack
140 | 247
// the same Solution instance will be reused for each test case.
ArrayList<Integer> lst = new ArrayList<Integer>();
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;
}
}
As we go down the tree, check the previously visited node. If it is the parent of
the current node, we should add current node to stack. When there is no children
141 | 247
85 Solution of Iterative Binary Tree Postorder Traversal in Java
for current node, pop it from stack. Then the previous node become to be under the
current node for next loop.
//Definition for binary tree
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
if(root == null)
return lst;
prev = curr;
}
return lst;
}
}
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
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.
143 | 247
if(root == null)
return al;
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);
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
144 | 247
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;
next = new LinkedList<TreeNode>();
result.add(numberList);
numberList = new ArrayList<Integer>();
}
}
//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;
}
145 | 247
88 Validate Binary Search Tree
Problem:
Given a binary tree, determine if it is a valid binary search tree (BST).
Assume a BST is defined as follows:
The left subtree of a node contains only nodes with keys less than the nodes key.
The right subtree of a node contains only nodes with keys greater than the nodes
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.
TreeNode(int x) {
val = x;
}
}
// not in range
if (root.val <= min || root.val >= max) {
return false;
}
89.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;
147 | 247
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public void flatten(TreeNode root) {
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode p = root;
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;
}
}
}
90 Path Sum
Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that
adding up all the values along the path equals the given sum.
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.
148 | 247
90 Path Sum
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()){
TreeNode curr = nodes.poll();
int sumValue = values.poll();
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;
}
}
II
Given a binary tree and a sum, find all root-to-leaf paths where each paths 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
91.1 Analysis
150 | 247
91.2 Java Solution
Given inorder and postorder traversal of a tree, construct the binary tree.
151 | 247
92 Construct Binary Tree from Inorder and Postorder Traversal
92.1 Throughts
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.
int k=0;
for(int i=0; i< inorder.length; i++){
if(inorder[i]==rootValue){
k = i;
break;
}
return root;
}
}
Given an array where elements are sorted in ascending order, convert it to a height
balanced BST.
93.1 Thoughts
TreeNode(int x) {
val = x;
}
}
153 | 247
return sortedArrayToBST(num, 0, num.length - 1);
}
return root;
}
}
Given a singly linked list where elements are sorted in ascending order, convert it to
a height balanced BST.
94.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;
}
154 | 247
94 Convert Sorted List to Binary Search Tree
TreeNode(int x) {
val = x;
}
}
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;
return root;
}
}
Need to know LinkedList is a queue. add() and remove() are the two methods 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();
156 | 247
int count = counts.remove();
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.
96.1 Analysis
1) Recursively solve this problem 2) Get largest left sum and right sum 2) Compare to
the stored maximum
157 | 247
calculateSum(root, max);
return max[0];
}
return current;
}
TreeNode(int x) {
val = x;
}
}
158 | 247
public boolean isBalanced(TreeNode root) {
if (root == null)
return true;
if (getHeight(root) == -1)
return false;
return true;
}
}
}
98 Symmetric Tree
98.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
159 | 247
1
/ \
2 2
\ \
3 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)
return false;
if (!isSymmetric(l.left, r.right))
return false;
if (!isSymmetric(l.right, r.left))
return false;
return true;
}
160 | 247
99 Binary Search Tree Iterator
99.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; }
* }
*/
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 <---
This problem can be solve by using a queue. On each level of the tree, we add the
right-most element to the results.
162 | 247
LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root);
return result;
}
101.1 Analysis
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.
163 | 247
101 Implement Trie (Prefix Tree)
class TrieNode {
char c;
HashMap<Character, TrieNode> children = new HashMap<Character, TrieNode>();
boolean isLeaf;
public TrieNode() {}
public Trie() {
root = new TrieNode();
}
TrieNode t;
if(children.containsKey(c)){
t = children.get(c);
}else{
t = new TrieNode(c);
children.put(c, t);
}
return t;
}
}
165 | 247
102 Add and Search Word Data structure design
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.
102.1 Analysis
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();
}
char c = word.charAt(i);
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;
}
}
}
@Override
public int compareTo(ArrayContainer o) {
if (this.arr[this.index] > o.arr[o.index]) {
return 1;
} else if (this.arr[this.index] < o.arr[o.index]) {
return -1;
} else {
return 0;
}
}
}
168 | 247
public static int[] mergeKSortedArray(int[][] arr) {
//PriorityQueue is heap in Java
PriorityQueue<ArrayContainer> queue = new PriorityQueue<ArrayContainer>();
int total=0;
int m=0;
int result[] = new int[total];
return result;
}
169 | 247
104 Populating Next Right Pointers in Each Node
/ \
2 3
/ \ / \
4 5 6 7
This solution is easier to understand. you can use the example tree above to walk
through the algorithm. The basic idea is have two pointers(top and p) to move towards
right on two levels.
public void connect(TreeLinkNode root) {
TreeLinkNode top = root;//the previous level, just use a better name for
root
while(top != null){
TreeLinkNode levelFirst = null;//first of each level
TreeLinkNode p = null;//cursor for node on each level
while(top != null){
//record the firston each level
if(levelFirst == null){
levelFirst = top.left;
}
if(top.left!=null){
if(p!=null)
p.next = top.left;
p=top.left;
}
if(top.right!=null){
if(p!=null)
p.next = top.right;
p = top.right;
}
top = top.next;
}
top = levelFirst;
}
}
//top node
TreeLinkNode top = root;
//first node of each level
TreeLinkNode first = root.left;
top = first;
first = top == null ? null : top.left;
}
}
Given n, how many structurally unique BSTs (binary search trees) that store values
1...n?
171 | 247
105.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
count[0] = 1;
count[1] = 1;
return count[n];
}
172 | 247
106 Unique Binary Search Trees II
Check out how to get all unique binary search trees. 106 Unique
Given n, generate all structurally unique BSTs (binary search trees) that store values
1...n.
For example, Given n = 3, your program should return all 5 unique BSTs shown
below.
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
106.1 Analysis
return list;
}
Given a binary tree containing digits from 0-9 only, each root-to-leaf path could
represent 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.
107.1 Java Solution - Recursive
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;
}
174 | 247
return result;
}
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;
}
175 | 247
108 Clone Graph Java
LeetCode Problem:
Clone an undirected graph. Each node in the graph contains a label and a list of its
neighbors.
/**
* 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);
}
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.
109.1 Analysis
This problem can be converted to finding if a graph contains a cycle. The following
solution use a breath-first search algorithm. You can read the comment to understand
the solution.
178 | 247
109 Course Schedule
while(!queue.isEmpty()){
int top = queue.remove();
for(int i=0; i<len; i++){
// if a courses 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]);
}
}
}
}
return true;
}
visit[i]=-1;
if(map.containsKey(i)){
for(int j: map.get(i)){
if(!canFinishDFS(map, visit, j))
return false;
}
}
return true;
}
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.
181 | 247
// TreeSet
Set<ObjectName> sortedSet = new TreeSet<ObjectName>(new
Comparator<ObjectName>() {
public int compare(ObjectName o1, ObjectName o2) {
return o1.toString().compareTo(o2.toString());
}
});
sortedSet.addAll(unsortedSet);
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;
}
182 | 247
111 Solution Merge Sort LinkedList in Java
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
// merge sort
public static ListNode mergeSortList(ListNode head) {
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:
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:
int low = 0;
int high = x.length - 1;
186 | 247
while (arr[i] < pivot) {
i++;
}
if (i <= j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
}
}
if (high > i)
quickSort(arr, i, high);
}
}
Output:
This is my accepted answer for LeetCode problem - Sort a linked list using insertion
sort in Java. It is a complete program.
Before coding for that, here is an example of insertion sort from wiki. You can get
an idea of what is insertion sort.
187 | 247
113 Solution Sort a linked list using insertion sort in Java
Code:
package algorithm.sort;
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
} else {
while (innerPointer.next != null) {
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:
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.
114.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;
}
}
190 | 247
public int maximumGap(int[] num) {
if(num == null || num.length < 2){
return 0;
}
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;
}
191 | 247
115 Edit Distance in Java
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].
Lets say we transform from one string to another. The first string has length i and
its last character is "x"; the second string has length j and its last character is "y". The
following diagram shows the relation.
return dp[len1][len2];
}
193 | 247
116 Longest Palindromic Substring
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;
}
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].
return longest;
}
197 | 247
117 Word Break
Manachers algorithm is much more complicated to figure out, even though it will
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;
}
}
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()];
}
}
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?
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"].
200 | 247
118 Word Break II
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.
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;
}
202 | 247
119 Maximum Subarray
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
Subarray
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];
return max;
}
}
Product Subarray
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.
204 | 247
120 Maximum Product Subarray
}
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
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;
121.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;
}
206 | 247
121 Palindrome Partitioning
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;
}
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.
122.1 Analysis
208 | 247
boolean dp[][] = new boolean[n][n];
int cut[] = new int[n];
return cut[n-1];
}
123 Candy
123.1 Problem
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?
209 | 247
public int candy(int[] ratings) {
if (ratings == null || ratings.length == 0) {
return 0;
}
return result;
}
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.
210 | 247
124.1 Java Solution
We can track the maximum length a position can reach. The key to solve this problem
is to find: 1) when the position can not reach next step (return false) , and 2) when the
maximum can reach the end (return true).
public boolean canJump(int[] A) {
if(A.length <= 1)
return true;
//update max
if(i + A[i] > max){
max = i + A[i];
}
return false;
}
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.
125.1 Naive Approach
211 | 247
int profit = Integer.MIN_VALUE;
for(int i=0; i<prices.length-1; i++){
for(int j=0; j< prices.length; j++){
if(profit < prices[j] - prices[i]){
profit = prices[j] - prices[i];
}
}
}
return 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;
}
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).
126.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.
212 | 247
We can scan the array once, and find all pairs of elements that are in ascending
order.
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).
127.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]
213 | 247
public int maxProfit(int[] prices) {
if (prices == null || prices.length < 2) {
return 0;
}
int profit = 0;
for (int i = 0; i < prices.length; i++) {
profit = Math.max(profit, left[i] + right[i]);
}
return profit;
}
128.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).
214 | 247
128 Best Time to Buy and Sell Stock IV
128.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.
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];
216 | 247
//init last row
for (int i = m - 2; i >= 0; i--) {
h[i][n - 1] = Math.max(h[i + 1][n - 1] - dungeon[i][n - 1], 1);
}
//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];
}
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 rob-
bing each of them is that adjacent houses have security system connected and it will
automatically contact the police if two adjacent houses were broken into on the same
night.
Given a list of non-negative integers representing the amount of money of each
house, determine the maximum amount of money you can rob tonight without alert-
ing the police.
130.1 Java Solution 1 - Dynamic Programming
int n = num.length;
217 | 247
dp[0]=0;
dp[1]=num[0];
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
int even = 0;
int odd = 0;
218 | 247
131 House Robber II
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.
131.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]);
}
When you see string problem that is about subsequence or matching, dynamic pro-
gramming method should come to your mind naturally. The key is to find the chang-
ing condition.
Let W(i, j) stand for the number of subsequences of S(0, i) in 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];
220 | 247
} else {
table[i][j] += table[i - 1][j];
}
}
}
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()];
}
221 | 247
133 Single Number
The problem:
Given an array of integers, every element appears twice except for one. Find that single
one.
133.1 Thoughts
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.
for(int a: A){
x = x ^ a;
}
return x;
}
}
134.1 Problem
Given an array of integers, every element appears three times except for one. Find that
single one.
222 | 247
134.2 Java Solution
The key to solve this problem is the fact that an integer x & 1 will get the last digit of
the integer.
while (N > 0) {
// get right most bit & shift right
r = N & 1;
N = N >> 1;
223 | 247
}
if (1 == r) {
max = count > max ? count : max;
count = 0;
}
}
return max;
}
136.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.
224 | 247
137 Reverse Bits
137.1 Problem
return n;
}
if ((a ^ b) != 0) {
return n ^= (1 << i) | (1 << j);
}
return n;
}
225 | 247
138 Repeated DNA Sequences
138.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 {
hash = (hash << 2) + map.get(s.charAt(i));
//make length of hash to be 20
hash = hash & (1 << 20) - 1;
return result;
}
Given a range [m, n] where 0 <= m <= n <= 2147483647, return the bitwise AND of
all numbers in this range, inclusive. For example, given the range [5, 7], you should
return 4.
139.1 Java Solution
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
140 Permutations
227 | 247
140 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>>();
//System.out.println(temp);
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;
}
229 | 247
141 Permutations II
141 Permutations II
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.
return returnList;
}
Sequence
231 | 247
142 Permutation Sequence
By listing and labeling all of the permutations in order, We get the following se-
quence (ie, for n = 3):
"123"
"132"
"213"
"231"
"312"
"321"
142.1 Thoughts
// 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;
// update k
k = k % mod;
return result.toString();
}
}
output[s - 1] = true;
buf.append(Integer.toString(s));
}
return buf.toString();
}
}
233 | 247
143 Generate Parentheses
Read the following solution, give n=2, walk though the code. Hopefully you will
quickly get an idea.
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;
Solution is provided first now. I will come back and draw a diagram to explain the
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]
144.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;
}
235 | 247
if(target == 0){
ArrayList<Integer> temp = new ArrayList<Integer>(curr);
result.add(temp);
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.
145.1 Java Solution
Arrays.sort(num);
236 | 247
result.addAll(set);
return result;
}
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]]
146.1 Analysis
237 | 247
return result;
}
list.add(i);
dfs(result, i+1, sum-i, list, k);
list.remove(list.size()-1);
}
}
147 Combinations
147.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.
238 | 247
147 Combinations
//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) {
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;
}
240 | 247
148 Letter Combinations of a Phone Number
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"].
148.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;
}
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 doesnt 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;
242 | 247
res = res * 10 + mod;
}
if (flag) {
res = 0 - res;
}
return res;
}
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");
}
243 | 247
150.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;
}
}
151 Pow(x, n)
Problem:
Implement pow(x, n).
This is a great example to illustrate how to solve a problem during a technical in-
terview. The first and second solution exceeds time limit; the third and fourth are
244 | 247
151 Pow(x, n)
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;
}
}
if(n == 1)
return x;
In this solution, we can handle cases that x <0 and n <0. This solution actually takes
more time than the first solution. Why?
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;
}
return result;
}
return 1;
if (n % 2 == 0) {
return v * v;
} else {
return v * v * x;
}
}