JAVA Coding Interview Questions and Answers
JAVA Coding Interview Questions and Answers
Program Creek
May 1st, 2015
Contents
11
Isomorphic Strings
14
Word Ladder
15
18
20
Merge Intervals
22
Insert Interval
24
Two Sum
26
27
28
12 3Sum
29
13 4Sum
31
14 3Sum Closest
33
34
35
17 Valid Parentheses
36
18 Implement strStr()
37
39
41
2 | 247
Contents
42
22 Valid Palindrome
44
23 ZigZag Conversion
47
24 Add Binary
48
49
26 Triangle
50
27 Contains Duplicate
52
28 Contains Duplicate II
52
53
55
58
60
63
64
65
66
68
38 Min Stack
68
39 Majority Element
70
40 Remove Element
71
71
73
43 Largest Number
74
44 Simplify Path
75
76
Program Creek
3 | 247
Contents
46 Gas Station
77
47 Pascals Triangle
79
48 Pascals Triangle II
80
81
82
83
84
53 Anagrams
86
87
55 Shortest Palindrome
88
89
57 Spiral Matrix
91
58 Spiral Matrix II
94
59 Search a 2D Matrix
95
60 Rotate Image
96
61 Valid Sudoku
98
99
63 Unique Paths
101
64 Unique Paths II
102
65 Number of Islands
104
66 Surrounded Regions
105
67 Maximal Rectangle
109
110
69 Reorder List
114
118
4 | 247
Program Creek
Contents
119
121
123
124
75 Partition List
126
76 LRU Cache
128
131
132
133
134
135
137
139
140
141
143
144
145
147
90 Path Sum
148
91 Path Sum II
150
151
153
154
156
Program Creek
5 | 247
Contents
157
158
98 Symmetric Tree
159
160
162
163
165
168
169
171
173
174
176
178
181
182
186
187
190
191
194
198
200
203
204
6 | 247
Program Creek
Contents
206
208
123 Candy
209
210
211
212
213
214
216
217
218
220
222
222
223
224
224
225
227
140 Permutations
227
141 Permutations II
229
231
233
235
236
Program Creek
7 | 247
Contents
237
147 Combinations
238
240
242
243
151 Pow(x, n)
244
8 | 247
Program Creek
Space is O(n) and time is O(n). You can check out the difference between System.arraycopy() and Arrays.copyOf().
9 | 247
2 3 4 5 6
2 3 4 6 5
1 2 3 4 5
1 2 3 5 4
0 1 2 3 4
0 1 2 4 3
6 0 1 2 3
Divide
Rotate
Rotate
Rotate
10 | 247
Program Creek
reverse(arr, 0, a-1);
reverse(arr, a, arr.length-1);
reverse(arr, 0, arr.length-1);
}
public static void reverse(int[] arr, int left, int right){
if(arr == null || arr.length == 1)
return;
while(left < right){
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
left++;
right--;
}
}
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
The following is the code. However, this code contains compilation errors in leetcode. Why?
public class Test {
public static void main(String[] args) throws IOException {
String[] tokens = new String[] { "2", "1", "+", "3", "*" };
System.out.println(evalRPN(tokens));
}
public static int evalRPN(String[] tokens) {
int returnValue = 0;
String operators = "+-*/";
Stack<String> stack = new Stack<String>();
for (String t : tokens) {
if (!operators.contains(t)) { //push to stack if it is a number
stack.push(t);
} else {//pop numbers from stack if it is an operator
int a = Integer.valueOf(stack.pop());
int b = Integer.valueOf(stack.pop());
switch (t) {
case "+":
stack.push(String.valueOf(a + b));
break;
case "-":
stack.push(String.valueOf(b - a));
break;
case "*":
stack.push(String.valueOf(a * b));
break;
12 | 247
Program Creek
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.
Program Creek
13 | 247
break;
}
}
}
returnValue = Integer.valueOf(stack.pop());
return returnValue;
}
}
3 Isomorphic Strings
Given two strings s and t, determine if they are isomorphic. Two strings are isomorphic 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.
14 | 247
}else if(map.containsKey(c1)){
if(c2 != map.get(c1))
return false;
}else{
map.put(c1,c2);
}
}
return true;
}
// a method for getting key of a target value
public Character getKey(HashMap<Character,Character> map, Character target){
for (Map.Entry<Character,Character> entry : map.entrySet()) {
if (entry.getValue().equals(target)) {
return entry.getKey();
}
}
return null;
}
4 Word Ladder
Given two words (start and end), and a dictionary, find the length of shortest transformation 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.
15 | 247
4 Word Ladder
int len=0;
HashSet<String> visited = new HashSet<String>();
for(int i=0; i<start.length(); i++){
char[] startArr = start.toCharArray();
for(char c=a; c<=z; c++){
if(c==start.toCharArray()[i]){
continue;
}
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.
16 | 247
Program Creek
4 Word Ladder
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);
LinkedList<String> wordQueue = new LinkedList<String>();
LinkedList<Integer> distanceQueue = new LinkedList<Integer>();
wordQueue.add(start);
distanceQueue.add(1);
//track the shortest path
int result = Integer.MAX_VALUE;
while (!wordQueue.isEmpty()) {
String currWord = wordQueue.pop();
Integer currDistance = distanceQueue.pop();
if (currWord.equals(end)) {
result = Math.min(result, currDistance);
}
for (int i = 0; i < currWord.length(); i++) {
char[] currCharArr = currWord.toCharArray();
for (char c = a; c <= z; c++) {
currCharArr[i] = c;
String newWord = new String(currCharArr);
if (dict.contains(newWord)) {
Program Creek
17 | 247
wordQueue.add(newWord);
distanceQueue.add(currDistance + 1);
dict.remove(newWord);
}
}
}
}
if (result < Integer.MAX_VALUE)
return result;
else
return 0;
}
5.1 Analysis
If we see log(n), we should think about using binary something.
This problem can be converted to the problem of finding kth element, k is (As length
+ B Length)/2.
If any of the two arrays is empty, then the kth element is the non-empty arrays kth
element. If k == 0, the kth element is the first element of A or B.
18 | 247
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;
}
}
public static int findKth(int A[], int B[], int k,
int aStart, int aEnd, int bStart, int bEnd) {
int aLen = aEnd - aStart + 1;
int bLen = bEnd - bStart + 1;
// Handle special cases
if (aLen == 0)
return B[bStart + k];
if (bLen == 0)
return A[aStart + k];
if (k == 0)
return A[aStart] < B[bStart] ? A[aStart] : B[bStart];
int aMid = aLen * k / (aLen + bLen); // as middle count
int bMid = k - aMid - 1; // bs middle count
// make aMid and bMid to be array index
aMid = aMid + aStart;
bMid = bMid + bStart;
if (A[aMid] > B[bMid]) {
k = k - (bMid - bStart + 1);
aEnd = aMid;
bStart = bMid + 1;
} else {
k = k - (aMid - aStart + 1);
bEnd = bMid;
aStart = aMid + 1;
}
return findKth(A, B, k, aStart, aEnd, bStart, bEnd);
}
Program Creek
19 | 247
1) Calculate the medians m1 and m2 of the input arrays ar1[] and ar2[]
respectively.
2) If m1 and m2 both are equal then we are done, and return m1 (or m2)
3) If m1 is greater than m2, then median is present in one of the below two
subarrays.
a) From first element of ar1 to m1 (ar1[0...|_n/2_|])
b) From m2 to last element of ar2 (ar2[|_n/2_|...n-1])
4) If m2 is greater than m1, then median is present in one of the below two
subarrays.
a) From m1 to last element of ar1 (ar1[|_n/2_|...n-1])
b) From first element of ar2 to m2 (ar2[0...|_n/2_|])
5) Repeat the above process until size of both the subarrays becomes 2.
6) If size of the two arrays is 2 then use below formula to get the median.
Median = (max(ar1[0], ar2[0]) + min(ar1[1], ar2[1]))/2
6.1 Analysis
First of all, this is one of the most difficulty problems. It is hard to think through all
different cases. The problem should be simplified to handle 2 basic cases:
the second char of pattern is "*"
the second char of pattern is not "*"
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
Program Creek
21 | 247
}
// otherwise, compare the rest of the string of s and p.
else {
return isMatch(s.substring(1), p.substring(1));
}
}
// case 1: when the second char of p is not *
if (p.charAt(1) != *) {
if (s.length() < 1) {
return false;
}
if ((p.charAt(0) != s.charAt(0)) && (p.charAt(0) != .)) {
return false;
} else {
return isMatch(s.substring(1), p.substring(1));
}
}
// case 2: when the second char of p is *, complex case.
else {
//case 2.1: a char & * can stand for 0 element
if (isMatch(s, p.substring(2))) {
return true;
}
//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].
Program Creek
23 | 247
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].
This is because the new interval [4,9] overlaps with [3,5],[6,7],[8,10].
24 | 247
8 Insert Interval
Program Creek
25 | 247
result.add(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
Can we do better?
26 | 247
Time complexity depends on the put and get operations of HashMap which is normally O(1).
Time complexity of this solution is O(n).
10 Two Sum II
27 | 247
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},
A solution set is:
(-1, 0, 1)
(-1, -1, 2)
29 | 247
12 3Sum
* The solution also does not handle duplicates. Therefore, it is not only time inefficient, but also incorrect.
Result:
Submission Result: Output Limit Exceeded
30 | 247
Program Creek
13 4Sum
Given an array S of n integers, are there elements a, b, c, and d in S such that a + b +
c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note: Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a
b c d) The solution set must not contain duplicate quadruplets.
For example, given array S = {1 0 -1 0 -2 2}, and target = 0.
A solution set is:
31 | 247
13 4Sum
(-1, 0, 0, 1)
(-2, -1, 1, 2)
(-2, 0, 0, 2)
13.1 Thoughts
A typical k-sum problem. Time is N to the power of (k-1).
32 | 247
Program Creek
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.
33 | 247
15 String to Integer
(atoi)
Implement atoi to convert a string to an integer.
Hint: Carefully consider all possible input cases. If you want a challenge, please do
not see below and ask yourself what are the possible input cases.
15.1 Analysis
The following cases should be considered for this problem:
1.
2.
3.
4.
5.
34 | 247
str = str.trim();
char flag = +;
// check negative or positive
int i = 0;
if (str.charAt(0) == -) {
flag = -;
i++;
} else if (str.charAt(0) == +) {
i++;
}
// use double to store result
double result = 0;
// 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;
// handle max and min
if (result > Integer.MAX_VALUE)
return Integer.MAX_VALUE;
if (result < Integer.MIN_VALUE)
return Integer.MIN_VALUE;
return (int) result;
}
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.
n > 0){
B[n-1]){
= A[m-1];
= B[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
Given a string containing just the characters (, ), , , [ and ], determine if the
input string is valid. The brackets must close in the correct order, "()" and "()[]" are all
valid but "(]" and "([)]" are not.
17.1 Analysis
17.2 Java Solution
public static boolean isValid(String s) {
HashMap<Character, Character> map = new HashMap<Character, Character>();
map.put((, ));
map.put([, ]);
map.put({, });
Stack<Character> stack = new Stack<Character>();
for (int i = 0; i < s.length(); i++) {
char curr = s.charAt(i);
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.
38 | 247
Program Creek
if (n > h)
return -1;
if (n == 0)
return 0;
int[] next = getNext(needle);
int i = 0;
while (i <= h - n) {
int success = 1;
for (int j = 0; j < n; j++) {
if (needle.charAt(0) != haystack.charAt(i)) {
success = 0;
i++;
break;
} else if (needle.charAt(j) != haystack.charAt(i + j)) {
success = 0;
i = i + j - next[j - 1];
break;
}
}
if (success == 1)
return i;
}
return -1;
}
//calculate KMP array
public int[] getNext(String needle) {
int[] next = new int[needle.length()];
next[0] = 0;
for (int i = 1; i < needle.length(); i++) {
int index = next[i - 1];
while (index > 0 && needle.charAt(index) != needle.charAt(i)) {
index = next[index - 1];
}
if (needle.charAt(index) == needle.charAt(i)) {
next[i] = next[i - 1] + 1;
} else {
next[i] = 0;
}
}
return next;
}
39 | 247
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.
40 | 247
Program Creek
5
2
7
0
->
->
->
->
2
1
4
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
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);
}
public int searchInsert(int[] A, int target, int start, int end){
int mid=(start+end)/2;
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);
}
}
42 | 247
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.
Program Creek
43 | 247
After an element is checked, it should be removed from the set. Otherwise, time
complexity would be O(mn) in which m is the average length of all consecutive sequences.
To clearly see the time complexity, I suggest you use some simple examples and
manually execute the program. For example, given an array 1,2,4,5,3, the program
time is m. m is the length of longest consecutive sequence.
We do have an extreme case here: If n is number of elements, m is average length
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
can use this array to get the point: 1,3,5,7,9.
22 Valid
Palindrome
Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases.
For example, "Red rum, sir, is murder" is a palindrome, while "Programcreek is
awesome" is not.
Note: Have you consider that the string might be empty? This is a good question to
ask during an interview.
For the purpose of this problem, we define empty string as valid palindrome.
22.1 Thoughts
From start and end loop though the string, i.e., char array. If it is not alpha or number, 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;
while(i<len-1 && !isAlpha(left) && !isNum(left)){
i++;
left = charArray[i];
}
while(j>0 && !isAlpha(right) && !isNum(right)){
j--;
right = charArray[j];
}
if(i >= j)
break;
left = charArray[i];
right = charArray[j];
if(!isSame(left, right)){
return false;
}
i++;
j--;
}
return true;
}
public boolean isAlpha(char a){
if((a >= a && a <= z) || (a >= A && a <= Z)){
return true;
}else{
return false;
}
}
public boolean isNum(char a){
if(a >= 0 && a <= 9){
return true;
}else{
return false;
}
}
public boolean isSame(char a, char b){
Program Creek
45 | 247
22 Valid Palindrome
46 | 247
Program Creek
23 ZigZag Conversion
The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of
rows like this: (you may want to display this pattern in a fixed font for better legibility)
P A H N
A P L S I I G
Y I R
And then read line by line: "PAHNAPLSIIGYIR" Write the a method convert("PAYPALISHIRING",
3) which returns "PAHNAPLSIIGYIR".
47 | 247
return s;
StringBuilder sb = new StringBuilder();
// step
int step = 2 * numRows - 2;
for (int i = 0; i < numRows; i++) {
//first & last rows
if (i == 0 || i == numRows - 1) {
for (int j = i; j < s.length(); j = j + step) {
sb.append(s.charAt(j));
}
//middle rows
} else {
int j = i;
boolean flag = true;
int step1 = 2 * (numRows - 1 - i);
int step2 = step - step1;
while (j < s.length()) {
sb.append(s.charAt(j));
if (flag)
j = j + step1;
else
j = j + step2;
flag = !flag;
}
}
}
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".
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(pa >= 0){
va = a.charAt(pa)==0? 0 : 1;
pa--;
}
if(pb >= 0){
vb = b.charAt(pb)==0? 0: 1;
pb--;
}
int sum = va + vb + flag;
if(sum >= 2){
sb.append(String.valueOf(sum-2));
flag = 1;
}else{
flag = 0;
sb.append(String.valueOf(sum));
}
}
if(flag == 1){
sb.append("1");
}
String reversed = sb.reverse().toString();
return reversed;
}
49 | 247
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
Program Creek
51 | 247
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.
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.
53 | 247
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
// Manipulate original array
public static int removeDuplicatesNaive(int[] A) {
if (A.length < 2)
return A.length;
int j = 0;
int i = 1;
while (i < A.length) {
if (A[i] == A[j]) {
i++;
} else {
j++;
A[j] = A[i];
i++;
}
}
return j + 1;
}
This method returns the number of unique elements, but does not change the original 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
// Create an array with all unique elements
public static int[] removeDuplicates(int[] A) {
if (A.length < 2)
return A;
int j = 0;
int i = 1;
while (i < A.length) {
54 | 247
Program Creek
if (A[i] == A[j]) {
i++;
} else {
j++;
A[j] = A[i];
i++;
}
}
int[] B = Arrays.copyOf(A, j + 1);
return B;
}
public static void main(String[] args) {
int[] arr = { 1, 2, 2, 3, 3 };
arr = removeDuplicates(arr);
System.out.println(arr.length);
}
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);
}
public static void main(String[] args) {
int[] arr = { 1, 2, 2, 3, 3 };
int size = countUnique(arr);
System.out.println(size);
}
55 | 247
56 | 247
Program Creek
Program Creek
57 | 247
return A.length;
int prev = 1; // point to previous
int curr = 2; // point to current
while (curr < A.length) {
if (A[curr] == A[prev] && A[curr] == A[prev - 1]) {
curr++;
} else {
prev++;
A[prev] = A[curr];
curr++;
}
}
return prev + 1;
}
}
58 | 247
Program Creek
59 | 247
When loop hits the second "a", the HashMap contains the following:
a
b
c
d
0
1
2
3
The index i is set to 0 and incremented by 1, so the loop start from second element
again.
60 | 247
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.
Program Creek
61 | 247
62 | 247
Program Creek
}
//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++;
}
}
}
if (map.size() == k && maxLen == 0) {
return s;
}
return maxSubstring;
}
Time is O(n).
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
}
}
// character counter for s
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
int left = 0;
int minLen = s.length()+1;
int count = 0; // the total of mapped characters
for(int i=0; i<s.length(); i++){
char c = s.charAt(i);
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);
}
if (i - left + 1 < minLen) {
result = s.substring(left, i + 1);
minLen = i - left + 1;
}
}
}
return result;
}
64 | 247
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.
66 | 247
67 | 247
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.
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.
Program Creek
69 | 247
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.
70 | 247
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.)
71 | 247
41.1 Analysis
The key to solve this problem is to maintain a stack to store bars indexes. The stack
only keeps the increasing bars.
72 | 247
Program Creek
(!stack.isEmpty()) {
p = stack.pop();
h = height[p];
w = stack.isEmpty() ? i : i - stack.peek() - 1;
= Math.max(h * w, max);
return max;
}
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
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
44 Simplify Path
Given an absolute path for a file (Unix-style), simplify it.
For example,
path
path
path
path
=
=
=
=
75 | 247
76 | 247
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.
78 | 247
Program Creek
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);
for (int i = 2; i <= numRows; i++) {
ArrayList<Integer> cur = new ArrayList<Integer>();
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
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
82 | 247
return null;
String result = "1";
int i = 1;
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;
}
83 | 247
Time is O(nlog(n))
84 | 247
}
return getKth(nums.length - k +1, nums, 0, nums.length - 1);
}
public int getKth(int k, int[] nums, int start, int end) {
int pivot = nums[end];
int left = start;
int right = end;
while (true) {
while (nums[left] < pivot && left < right) {
left++;
}
while (nums[right] >= pivot && right > left) {
right--;
}
if (left == right) {
break;
}
swap(nums, left, right);
}
swap(nums, left, end);
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);
}
}
public void swap(int[] nums, int n1, int n2) {
int tmp = nums[n1];
nums[n1] = nums[n2];
nums[n2] = tmp;
}
85 | 247
53 Anagrams
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. Therefore, this problem can be seen as a problem of finding duplicate elements.
86 | 247
Program Creek
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;
}
}
for (int i = 0; i < n; i++) {
if (A[i] != i)
return i;
}
return n;
}
87 | 247
= 0; i < n; i++)
!= i + 1)
i + 1;
1;
55 Shortest Palindrome
Given a string S, you are allowed to convert it to a palindrome by adding characters
in front of it. Find and return the shortest palindrome you can find by performing this
transformation.
For example, given "aacecaaa", return "aaacecaaa"; given "abcd", return "dcbabcd".
55.1 Analysis
We can solve this problem by using one of the methods which is used to solve the
longest palindrome substring problem.
Specifically, we can start from the center and scan two sides. If read the left boundary, then the shortest palindrome is identified.
88 | 247
89 | 247
90 | 247
Program Creek
if(firstRowZero){
for(int i=0; i<matrix[0].length; i++)
matrix[0][i] = 0;
}
}
}
57 Spiral Matrix
Given a matrix of m x n elements (m rows, n columns), return all elements of the
matrix in spiral order.
For example, given the following matrix:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
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;
}
//below, process a circle
//top - move right
for(int i=0;i<n-1;i++){
result.add(matrix[x][y++]);
}
//right - move down
for(int i=0;i<m-1;i++){
result.add(matrix[x++][y]);
}
//bottom - move left
for(int i=0;i<n-1;i++){
result.add(matrix[x][y--]);
}
//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;
}
}
92 | 247
Program Creek
57 Spiral Matrix
Program Creek
93 | 247
return result;
}
}
58 Spiral Matrix II
Given an integer n, generate a square matrix filled with elements from 1 to n2 in
spiral order. For example, given n = 4,
[
[1, 2, 3, 4],
[12, 13, 14, 5],
[11, 16, 15, 6],
[10, 9, 8, 7]
]
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
60 Rotate Image
You are given an n x n 2D matrix representing an image.
Rotate the image by 90 degrees (clockwise).
Follow up: Could you do this in-place?
96 | 247
60 Rotate Image
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;
int[][] result = new int[m][m];
for(int i=0; i<m; i++){
for(int j=0; j<m; j++){
result[j][m-1-i] = matrix[i][j];
}
}
for(int i=0; i<m; i++){
for(int j=0; j<m; j++){
matrix[i][j] = result[i][j];
}
}
}
}
Program Creek
97 | 247
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
99 | 247
100 | 247
Program Creek
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?
101 | 247
}
if(i<m-1 && j<n-1){
return dfs(i+1,j,m,n) + dfs(i,j+1,m,n);
}
if(i<m-1){
return dfs(i+1,j,m,n);
}
if(j<n-1){
return dfs(i,j+1,m,n);
}
return 0;
}
102 | 247
64 Unique Paths II
64 Unique Paths II
Follow up for "Unique Paths":
Now consider if some obstacles are added to the grids. How many unique paths
would there be?
An obstacle and empty space is marked as 1 and 0 respectively in the grid. For
example, there is one obstacle in the middle of a 3x3 grid as illustrated below,
[
[0,0,0],
[0,1,0],
[0,0,0]
]
Program Creek
103 | 247
dp[0][i] = 0;
}else{
dp[0][i] = dp[0][i-1];
}
}
//fill up cells inside
for(int i=1; i<m; i++){
for(int j=1; j<n; j++){
if(obstacleGrid[i][j]==1){
dp[i][j]=0;
}else{
dp[i][j]=dp[i-1][j]+dp[i][j-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
adjacent land
i-1, j);
i+1, j);
i, j-1);
i, j+1);
66 Surrounded Regions
Given a 2D board containing X and O, capture all regions surrounded by X. A
region is captured by flipping all Os into Xs in that surrounded region.
For example,
105 | 247
66 Surrounded Regions
X
X
X
X
X
O
X
O
X
O
O
X
X
X
X
X
X
X
X
O
X
X
X
X
X
X
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).
106 | 247
Program Creek
66 Surrounded Regions
}
//process the board
for(int i=0;i<m;i++){
for(int j=0; j<n; j++){
if(board[i][j] == O){
board[i][j] = X;
}else if(board[i][j] == #){
board[i][j] = O;
}
}
}
}
public void merge(char[][] board, int i, int j){
if(i<0 || i>=board.length || j<0 || j>=board[0].length)
return;
if(board[i][j] != O)
return;
board[i][j] = #;
merge(board,
merge(board,
merge(board,
merge(board,
i-1, j);
i+1, j);
i, j-1);
i, j+1);
Program Creek
107 | 247
66 Surrounded Regions
if (board[i][0] == O) {
bfs(board, i, 0);
}
if (board[i][n - 1] == O) {
bfs(board, i, n - 1);
}
}
// merge Os on top & bottom boarder
for (int j = 0; j < n; j++) {
if (board[0][j] == O) {
bfs(board, 0, j);
}
if (board[m - 1][j] == O) {
bfs(board, m - 1, j);
}
}
// process the board
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (board[i][j] == O) {
board[i][j] = X;
} else if (board[i][j] == #) {
board[i][j] = O;
}
}
}
}
private void bfs(char[][] board, int i, int j) {
int n = board[0].length;
// fill current first and then its neighbors
fillCell(board, i, j);
while
int
int
int
(!queue.isEmpty()) {
cur = queue.poll();
x = cur / n;
y = cur % n;
fillCell(board,
fillCell(board,
fillCell(board,
fillCell(board,
x - 1,
x + 1,
x, y x, y +
y);
y);
1);
1);
}
}
108 | 247
Program Creek
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
This problem can be converted to the "Largest Rectangle in Histogram" problem.
109 | 247
}
}
return maxArea;
}
private int maxAreaInHist(int[] height) {
Stack<Integer> stack = new Stack<Integer>();
int i = 0;
int max = 0;
while (i < height.length) {
if (stack.isEmpty() || height[stack.peek()] <= height[i]) {
stack.push(i++);
} else {
int t = stack.pop();
max = Math.max(max, height[t]
* (stack.isEmpty() ? i : i - stack.peek() - 1));
}
}
return max;
}
68.1 Thoughts
This is a simple problem. It can be solved by doing the following:
Use a flag to mark if previous sum is >= 10
Handle the situation that one list is longer than the other
Correctly move the 3 pointers p1, p2 and p3 which pointer to two input lists and
one output list
This leads to solution 1.
110 | 247
68.2 Solution 1
Program Creek
111 | 247
if(flag){
val = p2.val + 1;
if(val >= 10){
flag = true;
}else{
flag = false;
}
}else{
val = p2.val;
flag = false;
}
p3.next = new ListNode(val%10);
p2 = p2.next;
////p2 is null, because p1 is longer
}else if(p1 != null){
if(flag){
val = p1.val + 1;
if(val >= 10){
flag = true;
}else{
flag = false;
}
}else{
val = p1.val;
flag = false;
}
p3.next = new ListNode(val%10);
p1 = p1.next;
}
p3 = p3.next;
}
//handle situation that same length final sum >=10
if(p1 == null && p2 == null && flag){
p3.next = new ListNode(1);
}
return newHead.next;
}
}
The hard part is how to make the code more readable. Adding some internal comments and refactoring some code are helpful.
112 | 247
Program Creek
68.3 Solution 2
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;
ListNode newHead = new ListNode(0);
ListNode p1 = l1, p2 = l2, p3=newHead;
while(p1 != null || p2 != null){
if(p1 != null){
carry += p1.val;
p1 = p1.next;
}
if(p2 != null){
carry += p2.val;
p2 = p2.next;
}
p3.next = new ListNode(carry%10);
p3 = p3.next;
carry /= 10;
}
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: L0LnL1Ln1L2Ln-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
This problem is not straightforward, because it requires "in-place" operations. That
means we can only change their pointers, not creating a new list.
114 | 247
Program Creek
69 Reorder List
n3.next = n4;
printList(n1);
reorderList(n1);
printList(n1);
}
public static void reorderList(ListNode head) {
if (head != null && head.next != null) {
ListNode slow = head;
ListNode fast = head;
//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 second = slow.next;
slow.next = null;// need to close first part
// now should have two lists: head and fast
// reverse order for second part
second = reverseOrder(second);
ListNode p1 = head;
ListNode p2 = second;
//merge two lists here
while (p2 != null) {
ListNode temp1 = p1.next;
ListNode temp2 = p2.next;
p1.next = p2;
p2.next = temp1;
p1 = temp1;
p2 = temp2;
}
}
}
Program Creek
115 | 247
69 Reorder List
The three steps can be used to solve other problems of linked list. A little diagram
may help better understand them.
Reverse List:
116 | 247
Program Creek
Merge List:
117 | 247
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.
118 | 247
Program Creek
119 | 247
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){
120 | 247
Program Creek
121 | 247
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.
122 | 247
Program Creek
if(p2 != null)
p.next = p2;
return fakeHead.next;
}
}
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).
123 | 247
124 | 247
74.1 Thoughts
The key of this problem is using the right loop condition. And change what is necessary 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;
ListNode prev = head;
ListNode p = head.next;
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;
}
}
Program Creek
125 | 247
74.3 Solution 2
public class Solution {
public ListNode deleteDuplicates(ListNode head) {
if(head == null || head.next == null)
return head;
ListNode p = head;
while( p!= null && p.next != null){
if(p.val == p.next.val){
p.next = p.next.next;
}else{
p = p.next;
}
}
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.
126 | 247
75 Partition List
*/
public class Solution {
public ListNode partition(ListNode head, int x) {
if(head == null) return null;
ListNode fakeHead1 = new ListNode(0);
ListNode fakeHead2 = new ListNode(0);
fakeHead1.next = head;
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;
}
}
Program Creek
127 | 247
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.
128 | 247
76 LRU Cache
import java.util.HashMap;
public class LRUCache {
private HashMap<Integer, DoubleLinkedListNode> map
= new HashMap<Integer, DoubleLinkedListNode>();
private DoubleLinkedListNode head;
private DoubleLinkedListNode end;
private int capacity;
private int len;
public LRUCache(int capacity) {
this.capacity = capacity;
len = 0;
}
public int get(int key) {
if (map.containsKey(key)) {
DoubleLinkedListNode latest = map.get(key);
removeNode(latest);
setHead(latest);
return latest.val;
} else {
return -1;
}
}
public void removeNode(DoubleLinkedListNode node) {
DoubleLinkedListNode cur = node;
DoubleLinkedListNode pre = cur.pre;
DoubleLinkedListNode post = cur.next;
if (pre != null) {
pre.next = post;
} else {
head = post;
}
Program Creek
129 | 247
76 LRU Cache
if (post != null) {
post.pre = pre;
} else {
end = pre;
}
}
public void setHead(DoubleLinkedListNode node) {
node.next = head;
node.pre = null;
if (head != null) {
head.pre = node;
}
head = node;
if (end == null) {
end = node;
}
}
public void set(int key, int value) {
if (map.containsKey(key)) {
DoubleLinkedListNode oldNode = map.get(key);
oldNode.val = value;
removeNode(oldNode);
setHead(oldNode);
} else {
DoubleLinkedListNode newNode =
new DoubleLinkedListNode(key, value);
if (len < capacity) {
setHead(newNode);
map.put(key, newNode);
len++;
} else {
map.remove(end.key);
end = end.pre;
if (end != null) {
end.next = null;
}
setHead(newNode);
map.put(key, newNode);
}
}
}
}
class DoubleLinkedListNode {
public int val;
130 | 247
Program Creek
B:
a1 -> a2
->
c1 -> c2 -> c3
->
b1 -> b2 -> b3
131 | 247
132 | 247
133 | 247
134 | 247
}else{
break;
}
}
return p2;
}
135 | 247
len++;
p = p.next;
}
//if remove first node
int fromStart = len-n+1;
if(fromStart==1)
return head.next;
//remove non-first node
p = head;
int i=0;
while(p!=null){
i++;
if(i==fromStart-1){
p.next = p.next.next;
}
p=p.next;
}
return head;
}
136 | 247
Program Creek
slow = slow.next;
}
slow.next = slow.next.next;
return head;
}
137 | 247
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
Program Creek
139 | 247
}
return returnList;
}
}
140 | 247
// the same Solution instance will be reused for each test case.
ArrayList<Integer> lst = new ArrayList<Integer>();
if(root == null)
return lst;
Stack<TreeNode> stack = new Stack<TreeNode>();
//define a pointer to track nodes
TreeNode p = root;
while(!stack.empty() || p != null){
// if it is not null, push to stack
//and go down the tree to left
if(p != null){
stack.push(p);
p = p.left;
// 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;
}
}
141 | 247
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; }
}
142 | 247
Program Creek
lst.add(curr.val);
}
//go up the tree from right node
//after coming back from right node, process parent node and pop
stack.
}else if(curr.right == prev){
stack.pop();
lst.add(curr.val);
}
prev = curr;
}
return lst;
}
}
86.1 Analysis
It is obvious that this problem can be solve by using a queue. However, if we use one
queue we can not track when each level starts. So we use two queues to track the
current level and the next level.
143 | 247
if(root == null)
return al;
LinkedList<TreeNode> current = new LinkedList<TreeNode>();
LinkedList<TreeNode> next = new LinkedList<TreeNode>();
current.add(root);
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;
}
144 | 247
if(root == null){
return result;
}
LinkedList<TreeNode> current = new LinkedList<TreeNode>();
LinkedList<TreeNode> next = new LinkedList<TreeNode>();
current.offer(root);
ArrayList<Integer> numberList = new ArrayList<Integer>();
// need to track when each level starts
while(!current.isEmpty()){
TreeNode head = current.poll();
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
146 | 247
Program Creek
// left subtree must be < root.val && right subtree must be > root.val
return validate(root.left, min, root.val) && validate(root.right,
root.val, max);
}
}
89.1 Thoughts
Go down through the left, when right is not null, push right to stack.
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;
while(p != null || !stack.empty()){
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
Program Creek
149 | 247
91 Path Sum
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
This problem can be converted to be a typical depth-first search problem. A recursive
depth-first search algorithm usually requires a recursive method call, a reference to
the final result, a temporary result, etc.
150 | 247
151 | 247
92.1 Throughts
This problem can be illustrated by using a simple example.
in-order: 4 2 5 (1) 6 7 3 8
post-order: 4 5 2 6 7 8 3 (1)
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.
152 | 247
Program Creek
}
root.left = buildTree(inorder, inStart, k-1, postorder, postStart,
postStart+k-(inStart+1));
// Becuase k is not the length, it it need to -(inStart+1) to get the
length
root.right = buildTree(inorder, k+1, inEnd, postorder,
postStart+k-inStart, postEnd-1);
// postStart+k-inStart = postStart+k-(inStart+1) +1
return root;
}
}
93.1 Thoughts
Straightforward! Recursively do the job.
153 | 247
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.
154 | 247
}
// Definition for binary tree
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}
public class Solution {
static ListNode h;
public TreeNode sortedListToBST(ListNode head) {
if (head == null)
return null;
h = head;
int len = getLength(head);
return sortedListToBST(0, len - 1);
}
// get list length
public int getLength(ListNode head) {
int len = 0;
ListNode p = head;
while (p != null) {
len++;
p = p.next;
}
return len;
}
// build tree bottom-up
public TreeNode sortedListToBST(int start, int end) {
if (start > end)
return null;
// mid
int mid = (start + end) / 2;
TreeNode left = sortedListToBST(start, mid - 1);
TreeNode root = new TreeNode(h.val);
h = h.next;
TreeNode right = sortedListToBST(mid + 1, end);
Program Creek
155 | 247
root.left = left;
root.right = right;
return root;
}
}
95.1 Thoughts
Need to know LinkedList is a queue. add() and remove() are the two methods to
manipulate the queue.
156 | 247
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];
}
public int calculateSum(TreeNode root, int[] max) {
if (root == null)
return 0;
int left = calculateSum(root.left, max);
int right = calculateSum(root.right, max);
int current = Math.max(root.val, Math.max(root.val + left, root.val +
right));
max[0] = Math.max(max[0], Math.max(current, left + root.val + right));
return current;
}
97.1 Thoughts
A typical recursive problem for solving tree problems.
158 | 247
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
160 | 247
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.
/**
* Definition for binary tree
* public class TreeNode {
int val;
*
TreeNode left;
*
TreeNode right;
*
TreeNode(int x) { val = x; }
*
* }
*/
public class BSTIterator {
Stack<TreeNode> stack;
public BSTIterator(TreeNode root) {
stack = new Stack<TreeNode>();
while (root != null) {
stack.push(root);
root = root.left;
}
}
public boolean hasNext() {
Program Creek
161 | 247
return !stack.isEmpty();
}
public int next() {
TreeNode node = stack.pop();
int result = node.val;
if (node.right != null) {
node = node.right;
while (node != null) {
stack.push(node);
node = node.left;
}
}
return result;
}
}
<--<--<---
100.1 Analysis
This problem can be solve by using a queue. On each level of the tree, we add the
right-most element to the results.
162 | 247
101.1 Analysis
A trie node should contains the character, its children and the flag that marks if it is a
leaf node.
163 | 247
class TrieNode {
char c;
HashMap<Character, TrieNode> children = new HashMap<Character, TrieNode>();
boolean isLeaf;
public TrieNode() {}
public TrieNode(char c){
this.c = c;
}
}
164 | 247
Program Creek
children = t.children;
//set leaf node
if(i==word.length()-1)
t.isLeaf = true;
}
}
// Returns if the word is in the trie.
public boolean search(String word) {
TrieNode t = searchNode(word);
if(t != null && t.isLeaf)
return true;
else
return false;
}
// Returns if there is any word in the trie
// that starts with the given prefix.
public boolean startsWith(String prefix) {
if(searchNode(prefix) == null)
return false;
else
return true;
}
public TrieNode searchNode(String str){
Map<Character, TrieNode> children = root.children;
TrieNode t = null;
for(int i=0; i<str.length(); i++){
char c = str.charAt(i);
if(children.containsKey(c)){
t = children.get(c);
children = t.children;
}else{
return null;
}
}
return t;
}
}
165 | 247
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.
WordDictionary
public class WordDictionary {
private TrieNode root;
public WordDictionary(){
root = new TrieNode();
}
// Adds a word into the data structure.
public void addWord(String word) {
HashMap<Character, TrieNode> children = root.children;
for(int i=0; i<word.length(); i++){
166 | 247
Program Creek
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;
}
}
}
// Returns if the word is in the data structure. A word could
// contain the dot character . to represent any one letter.
public boolean search(String word) {
return dfsSearch(root.children, word, 0);
}
public boolean dfsSearch(HashMap<Character, TrieNode> children, String
word, int start) {
if(start == word.length()){
if(children.size()==0)
return true;
else
return false;
}
char c = word.charAt(start);
if(children.containsKey(c)){
if(start == word.length()-1 && children.get(c).isLeaf){
return true;
}
return dfsSearch(children.get(c).children, word, start+1);
}else if(c == .){
boolean result = false;
for(Map.Entry<Character, TrieNode> child: children.entrySet()){
if(start == word.length()-1 && child.getValue().isLeaf){
return true;
}
//if any path is true, set result to be true;
Program Creek
167 | 247
168 | 247
heap
i < arr.length; i++) {
ArrayContainer(arr[i], 0));
+ arr[i].length;
int m=0;
int result[] = new int[total];
//while heap is not empty
while(!queue.isEmpty()){
ArrayContainer ac = queue.poll();
result[m++]=ac.arr[ac.index];
if(ac.index < ac.arr.length-1){
queue.add(new ArrayContainer(ac.arr, ac.index+1));
}
}
return result;
}
public static void main(String[] args) {
int[] arr1 = { 1, 3, 5, 7 };
int[] arr2 = { 2, 4, 6, 8 };
int[] arr3 = { 0, 9, 10, 11 };
int[] result = mergeKSortedArray(new int[][] { arr1, arr2, arr3 });
System.out.println(Arrays.toString(result));
}
}
169 | 247
/
2
/ \
4 5
\
3
/ \
6 7
170 | 247
Program Creek
Given n, how many structurally unique BSTs (binary search trees) that store values
1...n?
For example, Given n = 3, there are a total of 5 unique BSTs.
1
3
\
3
/
2
/
2
/
1
3
/
1
\
2
2
/ \
1 3
1
\
2
\
3
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
i=1, count[1]=1 //one tree
i=2, count[2]=count[0]*count[1] // 0 is root
+ count[1]*count[0] // 1 is root
i=3, count[3]=count[0]*count[2] // 1 is root
+ count[1]*count[1] // 2 is root
+ count[2]*count[0] // 3 is root
i=4, count[4]=count[0]*count[3]
+ count[1]*count[2] //
+ count[2]*count[1] //
+ count[3]*count[0] //
..
..
..
// 1
2 is
3 is
4 is
is root
root
root
root
172 | 247
106 Unique
3
\
3
/
2
/
2
/
1
3
/
1
\
2
2
/ \
1 3
1
\
2
\
3
106.1 Analysis
Check out Unique Binary Search Trees I.
This problem can be solved by recursively forming left and right subtrees. The
different combinations of left and right subtrees form the set of all unique binary
search trees.
Program Creek
173 | 247
node.left = left;
node.right = right;
list.add(node);
}
}
}
return list;
}
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.
174 | 247
return result;
}
public void dfs(TreeNode n, ArrayList<TreeNode> l,
ArrayList<ArrayList<TreeNode>> all){
if(n.left==null && n.right==null){
ArrayList<TreeNode> t = new ArrayList<TreeNode>();
t.addAll(l);
all.add(t);
}
if(n.left!=null){
l.add(n.left);
dfs(n.left, l, all);
l.remove(l.size()-1);
}
if(n.right!=null){
l.add(n.right);
dfs(n.right, l, all);
l.remove(l.size()-1);
}
}
175 | 247
176 | 247
Program Creek
/**
* 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;
LinkedList<UndirectedGraphNode> queue = new
LinkedList<UndirectedGraphNode>();
HashMap<UndirectedGraphNode, UndirectedGraphNode> map =
new
HashMap<UndirectedGraphNode,UndirectedGraphNode>();
UndirectedGraphNode newHead = new UndirectedGraphNode(node.label);
queue.add(node);
map.put(node, newHead);
Program Creek
177 | 247
while(!queue.isEmpty()){
UndirectedGraphNode curr = queue.pop();
ArrayList<UndirectedGraphNode> currNeighbors = curr.neighbors;
for(UndirectedGraphNode aNeighbor: currNeighbors){
if(!map.containsKey(aNeighbor)){
UndirectedGraphNode copy = new
UndirectedGraphNode(aNeighbor.label);
map.put(aNeighbor,copy);
map.get(curr).neighbors.add(copy);
queue.add(aNeighbor);
}else{
map.get(curr).neighbors.add(map.get(aNeighbor));
}
}
}
return newHead;
}
}
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
Program Creek
179 | 247
180 | 247
Program Creek
visit[i]=1;
return true;
}
110 How
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).
182 | 247
Program Creek
183 | 247
184 | 247
Program Creek
=
=
=
=
=
n2;
n3;
n4;
n5;
n6;
n1 = mergeSortList(n1);
printList(n1);
}
public static void printList(ListNode x) {
if(x != null){
System.out.print(x.val + " ");
while (x.next != null) {
System.out.print(x.next.val + " ");
x = x.next;
}
System.out.println();
}
}
Program Creek
185 | 247
Output:
233445
Quicksort is a divide and conquer algorithm. It first divides a large list into two
smaller sub-lists and then recursively sort the two sub-lists. If we want to sort an array
without any extra space, quicksort is a good option. On average, time complexity is
O(n log(n)).
The basic step of sorting an array are as follows:
Select a pivot, normally the middle one
From both ends, swap elements and make all elements on the left less than the
pivot and all elements on the right greater than the pivot
Recursively sort left part and right part
Here is a very good animation of quicksort.
public class QuickSort {
public static void main(String[] args) {
int[] x = { 9, 2, 4, 7, 3, 7, 10 };
System.out.println(Arrays.toString(x));
int low = 0;
int high = x.length - 1;
quickSort(x, low, high);
System.out.println(Arrays.toString(x));
}
public static void quickSort(int[] arr, int low, int high) {
if (arr == null || arr.length == 0)
return;
if (low >= high)
return;
// pick the pivot
int middle = low + (high - low) / 2;
int pivot = arr[middle];
// make left < pivot and right > pivot
int i = low, j = high;
while (i <= j) {
186 | 247
Output:
9 2 4 7 3 7 10 2 3 4 7 7 9 10
187 | 247
Code:
package algorithm.sort;
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
public class SortLinkedList {
public static ListNode insertionSortList(ListNode head) {
if (head == null || head.next == null)
return head;
ListNode newHead = new ListNode(head.val);
ListNode pointer = head.next;
// loop through each element in the list
while (pointer != null) {
// insert this element to the new list
ListNode innerPointer = newHead;
ListNode next = pointer.next;
if (pointer.val <= newHead.val) {
ListNode oldHead = newHead;
newHead = pointer;
newHead.next = oldHead;
188 | 247
Program Creek
} else {
while (innerPointer.next != null) {
if (pointer.val > innerPointer.val && pointer.val <=
innerPointer.next.val) {
ListNode oldNext = innerPointer.next;
innerPointer.next = pointer;
pointer.next = oldNext;
}
innerPointer = innerPointer.next;
}
if (innerPointer.next == null && pointer.val > innerPointer.val) {
innerPointer.next = pointer;
pointer.next = null;
}
}
// finally
pointer = next;
}
return newHead;
}
public static
ListNode n1
ListNode n2
ListNode n3
=
=
=
=
=
n2;
n3;
n4;
n5;
n6;
n1 = insertionSortList(n1);
printList(n1);
}
public static void printList(ListNode x) {
if(x != null){
System.out.print(x.val + " ");
Program Creek
189 | 247
Output:
233445
Given an unsorted array, find the maximum difference between the successive elements in its sorted form.
Try to solve it in linear time/space. Return 0 if the array contains less than 2 elements. 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)
190 | 247
191 | 247
192 | 247
Program Creek
193 | 247
194 | 247
Program Creek
return true;
}
Changing condition:
table[i+1][j-1] == 1 && s.charAt(i) == s.charAt(j)
=>
table[i][j] == 1
Program Creek
195 | 247
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 execution. 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
0
0
0
1
0
0
0
0
0
0
1
0
0
0
0
1
0
1
0
0
1
0
0
0
1
From the table, we can clearly see that the longest string is in cell table[1][5].
196 | 247
Program Creek
if (s.length() == 1) {
return s;
}
String longest = s.substring(0, 1);
for (int i = 0; i < s.length(); i++) {
// get longest palindrome with center of i
String tmp = helper(s, i, i);
if (tmp.length() > longest.length()) {
longest = tmp;
}
// get longest palindrome with center of i, i+1
tmp = helper(s, i, i + 1);
if (tmp.length() > longest.length()) {
longest = tmp;
}
}
return longest;
}
// Given a center, either one letter or two letter,
// Find longest palindrome
public String helper(String s, int begin, int end) {
while (begin >= 0 && end <= s.length() - 1 && s.charAt(begin) ==
s.charAt(end)) {
begin--;
end++;
}
return s.substring(begin + 1, end);
}
197 | 247
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".
198 | 247
Program Creek
Program Creek
199 | 247
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
Program Creek
201 | 247
}
}
}
List<String> result = new LinkedList<String>();
if(dp[s.length()] == null)
return result;
ArrayList<String> temp = new ArrayList<String>();
dfs(dp, s.length(), result, temp);
return result;
}
public static void dfs(List<String> dp[],int end,List<String> result,
ArrayList<String> tmp){
if(end <= 0){
String path = tmp.get(tmp.size()-1);
for(int i=tmp.size()-2; i>=0; i--){
path += " " + tmp.get(i) ;
}
result.add(path);
return;
}
for(String str : dp[end]){
tmp.add(str);
dfs(dp, end-str.length(), result, tmp);
tmp.remove(tmp.size()-1);
}
}
202 | 247
This problem is also useful for solving real problems. Assuming you want to
analyze the domain names of the top 10k websites. We can use this solution
to break the main part of the domain into words and then get a sense of
what kinds of websites are popular. I did this a long time ago and found
some interesting results. For example, the most frequent words include
"news", "tube", "porn", "etc".
119 Maximum
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.
Program Creek
203 | 247
120 Maximum
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
Program Creek
205 | 247
Time is O(n).
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"]
]
206 | 247
}
for (int i = start + 1; i <= s.length(); i++) {
String str = s.substring(start, i);
if (isPalindrome(str)) {
partition.add(str);
addPalindrome(s, i, partition, result);
partition.remove(partition.size() - 1);
}
}
}
private boolean isPalindrome(String str) {
int left = 0;
int right = str.length() - 1;
while (left < right) {
if (str.charAt(left) != str.charAt(right)) {
return false;
}
left++;
right--;
}
return true;
}
Program Creek
207 | 247
122.1 Analysis
This problem is similar to Palindrome Partitioning. It can be efficiently solved by using
dynamic programming. Unlike "Palindrome Partitioning", we need to maintain two
cache arrays, one tracks the partition position and one tracks the number of minimum
cut.
208 | 247
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
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
211 | 247
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.
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
214 | 247
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.
Program Creek
215 | 247
216 | 247
217 | 247
dp[0]=0;
dp[1]=num[0];
for (int i=2; i<n+1; i++){
dp[i] = Math.max(dp[i-1], dp[i-2]+num[i-1]);
}
return dp[n];
}
218 | 247
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.
Program Creek
219 | 247
132.1 Thoughts
When you see string problem that is about subsequence or matching, dynamic programming method should come to your mind naturally. The key is to find the changing condition.
220 | 247
} else {
table[i][j] += table[i - 1][j];
}
}
}
return table[S.length()][T.length()];
}
221 | 247
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.
134.1 Problem
Given an array of integers, every element appears three times except for one. Find that
single one.
222 | 247
135.1 Thoughts
The key to solve this problem is the fact that an integer x & 1 will get the last digit of
the integer.
223 | 247
}
if (1 == r) {
max = count > max ? count : max;
count = 0;
}
}
return max;
}
public static void main(String[] args) {
System.out.println(solution(9));
}
}
224 | 247
225 | 247
138.1 Problem
All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, for
example: "ACGAATTCCG". When studying DNA, it is sometimes useful to identify
repeated sequences within the DNA.
Write a function to find all the 10-letter-long sequences (substrings) that occur more
than once in a DNA molecule.
For example, given s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT", return: ["AAAAACCCCC", "CCCCCAAAAA"].
226 | 247
Program Creek
temp.add(hash);
}
}
}
return result;
}
140 Permutations
Given a collection of numbers, return all possible permutations.
For example,
227 | 247
140 Permutations
1]
2]
2,
3,
1,
1,
3,
2,
1]
1]
3]
2]
2]
3]
Loop through the array, in each iteration, a new number is added to different locations 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>>();
//start from an empty list
result.add(new ArrayList<Integer>());
for (int i = 0; i < num.length; i++) {
//list of list in current iteration of the array num
ArrayList<ArrayList<Integer>> current = new
ArrayList<ArrayList<Integer>>();
for (ArrayList<Integer> l : result) {
// # of locations to insert is largest index + 1
for (int j = 0; j < l.size()+1; j++) {
// + add num[i] to different locations
l.add(j, num[i]);
ArrayList<Integer> temp = new ArrayList<Integer>(l);
current.add(temp);
//System.out.println(temp);
// - remove num[i] add
l.remove(j);
}
}
result = new ArrayList<ArrayList<Integer>>(current);
}
228 | 247
Program Creek
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].
230 | 247
Program Creek
142 Permutation
Sequence
The set [1,2,3,. . . ,n] contains a total of n! unique permutations.
231 | 247
By listing and labeling all of the permutations in order, We get the following sequence (ie, for n = 3):
"123"
"132"
"213"
"231"
"312"
"321"
142.1 Thoughts
Naively loop through all cases will not work.
232 | 247
Program Creek
233 | 247
234 | 247
Program Creek
Solution is provided first now. I will come back and draw a diagram to explain the
solution.
Given a set of candidate numbers (C) and a target number (T), find all unique combinations 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 combination (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.
235 | 247
if(target == 0){
ArrayList<Integer> temp = new ArrayList<Integer>(curr);
result.add(temp);
return;
}
for(int i=j; i<candidates.length; i++){
if(target < candidates[i])
return;
curr.add(candidates[i]);
combinationSum(candidates, target - candidates[i], i, curr, result);
curr.remove(curr.size()-1);
}
}
236 | 247
result.addAll(set);
return result;
}
public void getCombination(int[] num, int start, int target,
ArrayList<Integer> temp, ArrayList<ArrayList<Integer>> result){
if(target == 0){
ArrayList<Integer> t = new ArrayList<Integer>(temp);
result.add(t);
return;
}
for(int i=start; i<num.length; i++){
if(target < num[i])
continue;
temp.add(num[i]);
getCombination(num, i+1, target-num[i], temp, result);
temp.remove(temp.size()-1);
}
}
146.1 Analysis
Related problems: Combination Sum, Combination Sum II.
237 | 247
return result;
}
public void dfs(ArrayList<ArrayList<Integer>> result, int start, int sum,
ArrayList<Integer> list, int k){
if(sum==0 && list.size()==k){
ArrayList<Integer> temp = new ArrayList<Integer>();
temp.addAll(list);
result.add(temp);
}
for(int i=start; i<=9; i++){
if(sum-i<0) break;
if(list.size()>k) break;
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],
]
238 | 247
147 Combinations
Program Creek
239 | 247
240 | 247
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.
Program Creek
241 | 247
return;
}
Integer curr = Integer.valueOf(digits.substring(0,1));
String letters = map.get(curr);
for(int i=0; i<letters.length(); i++){
temp.add(letters.charAt(i));
getString(digits.substring(1), temp, result, map);
temp.remove(temp.size()-1);
}
}
242 | 247
243 | 247
150.1 Thoughts
Problems related with numbers are frequently solved by / and
Note: no extra space here means do not convert the integer to string, since string
will be a copy of the integer and take extra space. The space take by div, left, and right
can be ignored.
151 Pow(x, n)
Problem:
Implement pow(x, n).
This is a great example to illustrate how to solve a problem during a technical interview. The first and second solution exceeds time limit; the third and fourth are
244 | 247
151 Pow(x, n)
accepted.
Program Creek
245 | 247
151 Pow(x, n)
In this solution, we can handle cases that x <0 and n <0. This solution actually takes
more time than the first solution. Why?
246 | 247
Program Creek
151 Pow(x, n)
return 1;
double v = power(x, n / 2);
if (n % 2 == 0) {
return v * v;
} else {
return v * v * x;
}
}
public double pow(double x, int n) {
if (n < 0) {
return 1 / power(x, -n);
} else {
return power(x, n);
}
}
Program Creek
247 | 247