Coding Interview in Java
Coding Interview in Java
Coding Interview in Java
Program Creek
Contents
3 Remove Element 18
4 Move Zeroes 19
5 Candy 20
9 Summary Ranges 28
10 Missing Ranges 29
11 Merge Intervals 30
12 Insert Interval 31
13 Partition Labels 34
17 Is Subsequence 40
22 Valid Palindrome 46
2 | 568
Contents
30 3Sum 58
31 4Sum 60
32 3Sum Closest 62
33 Wiggle Sort 63
34 Wiggle Subsequence 64
36 Next Permutation 66
49 HIndex 93
50 HIndex II 95
51 Valid Anagram 96
169 Construct Binary Tree from Inorder and Postorder Traversal 327
170 Construct Binary Tree from Preorder and Inorder Traversal 329
218 Evaluate math expression with plus, minus and parentheses 423
232 Get Target Number Using Number List and Arithmetic Operations 450
279 Design a Data Structure with Insert, Delete and GetMostFrequent of O(1) 533
Every title in the PDF is linked back to the original blog. When it is clicked, it opens the original post in your
browser. If you want to discuss any problem, please go to the post and leave your comment there.
I’m not an expert and some solutions may not be optimal. So please leave your comment if you see any problem
or have a better solution. I will reply your comment as soon as I can.
This collection is updated from time to time. Please check out this link for the latest version: http://www.programcreek.com/
10-algorithms-for-coding-interview/
1.1 Analysis
The problem is pretty straightforward. It returns the length of the array with unique elements, but the original
array need to be changed also. This problem is similar to Remove Duplicates from Sorted Array II.
int j = 0;
int i = 1;
i++;
}
return j + 1;
}
14 | 568
1 Remove Duplicates from Sorted Array
Note that we only care about the first unique part of the original array. So it is ok if input array is 1, 2, 2, 3, 3,
the array is changed to 1, 2, 3, 3, 3.
int i=0;
int j=1;
/*
i, j 1 1 1 2 2 3
step1 0 1 i j
step2 1 2 i j
step3 1 3 i j
step4 2 4 i j
*/
while(j<nums.length){
if(nums[j]==nums[i]){
if(i==0){
i++;
j++;
}else if(nums[i]==nums[i-1]){
j++;
}else{
i++;
nums[i]=nums[j];
j++;
}
}else{
i++;
nums[i]=nums[j];
j++;
}
}
return i+1;
}
16 | 568
2 Remove Duplicates from Sorted Array II
The problem with this solution is that there are 4 cases to handle. If we shift our two points to right by 1
element, the solution can be simplified as the Solution 2.
return i + 1;
}
j++;
}
return i;
}
18 | 568
4 Move Zeroes
Given an array nums, write a function to move all 0’s to the end of it while maintaining the relative order of the
non-zero elements.
For example, given nums = [0, 1, 0, 3, 12], after calling your function, nums should be [1, 3, 12, 0, 0].
while(j<nums.length){
if(nums[j]==0){
j++;
}else{
nums[i]=nums[j];
i++;
j++;
}
}
while(i<nums.length){
nums[i]=0;
i++;
}
}
19 | 568
5 Candy
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?
5.1 Analysis
This problem can be solved in O(n) time.
We can always assign a neighbor with 1 more if the neighbor has higher a rating value. However, to get the
minimum total number, we should always start adding 1s in the ascending order. We can solve this problem by
scanning the array from both sides. First, scan the array from left to right, and assign values for all the ascending
pairs. Then scan from right to left and assign values to descending pairs.
This problem is similar to Trapping Rain Water.
20 | 568
5 Candy
return result;
}
6.1 Analysis
This problem is similar to Candy. It can be solve by scanning from both sides and then get the total.
if(height==null || height.length<=2)
return result;
22 | 568
6 Trapping Rain Water
}else{
left[i]=height[i];
max = height[i];
}
}
//calculate totoal
for(int i=0; i<height.length; i++){
result+= Math.min(left[i],right[i])-height[i];
}
return result;
}
t1[0]=1;
t2[nums.length-1]=1;
//multiply
for(int i=0; i<nums.length; i++){
result[i] = t1[i] * t2[i];
}
return result;
}
result[nums.length-1]=1;
for(int i=nums.length-2; i>=0; i--){
result[i]=result[i+1]*nums[i+1];
}
24 | 568
7 Product of Array Except Self
int left=1;
for(int i=0; i<nums.length; i++){
result[i]=result[i]*left;
left = left*nums[i];
}
return result;
}
8.1 Analysis
We can use 2 points to mark the left and right boundaries of the sliding window. When the sum is greater than
the target, shift the left pointer; when the sum is less than the target, shift the right pointer.
int start=0;
int sum=0;
int i=0;
boolean exists = false;
while(i<=nums.length){
if(sum>=s){
exists=true; //mark if there exists such a subarray
if(start==i-1){
return 1;
}
}else{
if(i==nums.length)
break;
sum = sum+nums[i];
i++;
}
}
if(exists)
return result;
else
return 0;
26 | 568
8 Minimum Size Subarray Sum
int i=0;
int j=0;
int sum=0;
while(j<nums.length){
if(sum<s){
sum += nums[j];
j++;
}else{
minLen = Math.min(minLen, j-i);
if(i==j-1)
return 1;
sum -=nums[i];
i++;
}
}
while(sum>=s){
minLen = Math.min(minLen, j-i);
sum -=nums[i++];
}
9.1 Analysis
When iterating over the array, two values need to be tracked: 1) the first value of a new range and 2) the previous
value in the range.
if(nums.length==1){
result.add(nums[0]+"");
}
if(i==nums.length-1){
result.add(nums[i]+"");
}
first = nums[i];
}
pre = nums[i];
}
return result;
}
28 | 568
10 Missing Ranges
Given a sorted integer array nums, where the range of elements are in the inclusive range [lower, upper], return
its missing ranges.
Example:
Input: nums = [0, 1, 3, 50, 75], lower = 0 and upper = 99, Output: ["2", "4->49", "51->74", "76->99"]
if(lower==Integer.MAX_VALUE){
return result;
}
if(nums[i] == start){
start++;
}else{
result.add(getRange(start, nums[i]-1));
if(nums[i]==Integer.MAX_VALUE){
return result;
}
start = nums[i]+1;
}
}
if(start<=upper){
result.add(getRange(start, upper));
}
return result;
}
29 | 568
11 Merge Intervals
Given a collection of intervals, merge all overlapping intervals.
For example, Given [1,3],[2,6],[8,10],[15,18], return [1,6],[8,10],[15,18].
11.1 Analysis
The key to solve this problem is defining a Comparator first to sort the arraylist of Intevals.
result.add(t);
return result;
}
30 | 568
12 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].
/**
* 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; }
31 | 568
12 Insert Interval
* }
*/
public class Solution {
public ArrayList<Interval> insert(ArrayList<Interval> intervals, Interval newInterval) {
result.add(newInterval);
return result;
}
}
if (intervals.size() == 0) {
result.add(newInterval);
return result;
}
result.add(newInterval);
return result;
}
if(arr == null){
arr = new int[]{i, i};
map.put(c, arr);
}else{
arr[1]=i;
}
}
34 | 568
13 Partition Labels
int[] t = list.get(0);
for(int i=1; i<list.size(); i++){
int[] range = list.get(i);
if(range[1]<=t[1]){
continue;
}else if(range[0]>t[1]){ //impossible be equal
result.add(t[1]-t[0]+1);
t = range;
}else{
t[1] = range[1];
}
}
result.add(t[1]-t[0]+1);
return result;
}
int prev = 0;
if (prev != startIndex) {
sb.append(S.substring(prev, startIndex));
}
return sb.toString();
}
36 | 568
15 One Edit Distance
Given two strings S and T, determine if they are both one edit distance apart.
int m = s.length();
int n = t.length();
if(Math.abs(m-n)>1){
return false;
}
int i=0;
int j=0;
int count=0;
while(i<m&&j<n){
if(s.charAt(i)==t.charAt(j)){
i++;
j++;
}else{
count++;
if(count>1)
return false;
if(m>n){
i++;
}else if(m<n){
j++;
}else{
i++;
j++;
}
}
}
if(i<m||j<n){
count++;
}
if(count==1)
return true;
return false;
}
37 | 568
16 Merge Sorted Array
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.
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.
while (k >= 0) {
if (j < 0 || (i >= 0 && A[i] > B[j]))
A[k--] = A[i--];
38 | 568
16 Merge Sorted Array
else
A[k--] = B[j--];
}
}
int i=0;
int j=0;
while(i<s.length() && j<t.length()){
if(s.charAt(i)==t.charAt(j)){
i++;
}
j++;
if(i==s.length())
return true;
}
return false;
}
40 | 568
18 Backspace String Compare
Given two strings S and T, return if they are equal when both are typed into empty text editors. # means a
backspace character.
Example 1:
Example 2:
while(i>=0 || j>=0){
int c1=0;
while(i>=0 && (c1>0 || S.charAt(i)==’#’)){
if(S.charAt(i)==’#’){
c1++;
}else{
c1--;
}
i--;
}
int c2=0;
while(j>=0 && (c2>0 || T.charAt(j)==’#’)){
if(T.charAt(j)==’#’){
c2++;
}else{
c2--;
}
j--;
}
41 | 568
18 Backspace String Compare
}else{
i--;
j--;
}
}else{
if(i>=0 || j>=0){
return false;
}
}
}
int result = 0;
int k = 0;
if (i == A.length()) {
i = 0;
result++;
}
} else {
k++;
if (k == A.length()) {
return -1;
}
i = k;
j = 0;
result = 0;
}
}
if (i > 0) {
result++;
}
return result;
}
43 | 568
20 Container With Most Water
20.1 Problem
Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (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.
20.2 Analysis
Initially we can assume the result is 0. Then we scan from both sides. If leftHeight <rightHeight, move right and
find a value that is greater than leftHeight. Similarily, if leftHeight >rightHeight, move left and find a value that
is greater than rightHeight. Additionally, keep tracking the max value.
int max = 0;
int left = 0;
int right = height.length - 1;
return max;
}
44 | 568
21 Reverse Vowels of a String
Write a function that takes a string as input and reverse only the vowels of a string.
int i=0;
int j=s.length()-1;
while(i<j){
if(!vowList.contains(arr[i])){
i++;
continue;
}
if(!vowList.contains(arr[j])){
j--;
continue;
}
char t = arr[i];
arr[i]=arr[j];
arr[j]=t;
i++;
j--;
}
45 | 568
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.
s = s.toLowerCase();
int i=0;
int j=s.length()-1;
while(i<j){
while(i<j && !((s.charAt(i)>=’a’ && s.charAt(i)<=’z’)
|| (s.charAt(i)>=’0’&&s.charAt(i)<=’9’))){
i++;
}
if(s.charAt(i) != s.charAt(j)){
return false;
}
i++;
j--;
}
return true;
}
46 | 568
23 Shortest Word Distance
Given a list of words and two words word1 and word2, return the shortest distance between these two words in
the list.
For example, Assume that words = ["practice", "makes", "perfect", "coding", "makes"].
Given word1 = “coding”, word2 = “practice”, return 3. Given word1 = "makes", word2 = "coding", return 1.
return min;
}
47 | 568
24 Shortest Word Distance II
This is a follow up of Shortest Word Distance. The only difference is now you are given the list of words and
your method will be called repeatedly many times with different parameters. How would you optimize it?
Design a class which receives a list of words in the constructor, and implements a method that takes two words
word1 and word2 and return the shortest distance between these two words in the list.
For example, Assume that words = ["practice", "makes", "perfect", "coding", "makes"].
Given word1 = “coding”, word2 = “practice”, return 3. Given word1 = "makes", word2 = "coding", return 1.
ArrayList<Integer> l1 = map.get(word1);
ArrayList<Integer> l2 = map.get(word2);
The time complexity for shortest method is O(M*N), where M is freqency of word1 and N is the frequency of
word2. This can be improved by the following:
ArrayList<Integer> l1 = map.get(word1);
ArrayList<Integer> l2 = map.get(word2);
48 | 568
24 Shortest Word Distance II
int i=0;
int j=0;
while(i<l1.size() && j<l2.size()){
result = Math.min(result, Math.abs(l1.get(i)-l2.get(j)));
if(l1.get(i)<l2.get(j)){
i++;
}else{
j++;
}
}
return result;
}
The time complexity of the shortest method is now O(M+N). Since M+N <size of word list, the time is O(K)
where k is the list size.
int m=-1;
int n=-1;
return min;
}
50 | 568
25 Shortest Word Distance III
if(word1==null || word2==null)
return -1;
if(word1.equals(word2))
isSame = true;
int prev=-1;
int i1=-1;
int i2=-1;
return shortest;
}
return result;
}
52 | 568
26 Intersection of Two Arrays
for(int i: list){
result[k++] = i;
}
return result;
}
return result;
}
54 | 568
27 Intersection of Two Arrays II
}
}
int i = 0;
int j = numbers.length - 1;
while (i < j) {
int x = numbers[i] + numbers[j];
if (x < target) {
++i;
} else if (x > target) {
j--;
} else {
return new int[] { i + 1, j + 1 };
}
}
return null;
}
56 | 568
29 Two Sum III Data structure design
Design and implement a TwoSum class. It should support the following operations: add and find.
add - Add the number to an internal data structure. find - Find if there exists any pair of numbers which sum
is equal to the value.
For example,
add(1);
add(3);
add(5);
find(4) -> true
find(7) -> false
57 | 568
30 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.
while (j < k) {
if (k < nums.length - 1 && nums[k] == nums[k + 1]) {
k--;
continue;
}
58 | 568
30 3Sum
k--;
}
}
}
return result;
}
if(nums==null|| nums.length<4)
return result;
Arrays.sort(nums);
k++;
l--;
60 | 568
31 4Sum
while(k<l &&nums[l]==nums[l+1] ){
l--;
}
while(k<l &&nums[k]==nums[k-1]){
k++;
}
}
}
}
}
return result;
}
32.1 Analysis
This problem is similar to 2 Sum. This kind of problem can be solved by using a similar approach, i.e., two
pointers from both left and right.
Arrays.sort(nums);
return result;
}
62 | 568
33 Wiggle Sort
Given an unsorted array nums, reorder it in-place such that nums[0] <nums[1] >nums[2] <nums[3].... Example:
63 | 568
34 Wiggle Subsequence
Given a sequence of integers, return the length of the longest subsequence that is a wiggle sequence. A sub-
sequence is obtained by deleting some number of elements (eventually, also zero) from the original sequence,
leaving the remaining elements in their original order.
int count=1;
return count;
}
64 | 568
35 Longest Common Prefix
35.1 Problem
Write a function to find the longest common prefix string amongst an array of strings.
35.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.
if(strs.length == 1){
return strs[0];
}
int i=0;
while(true){
boolean flag = true;
for(int j=1; j<strs.length; j++){
if(strs[j].length()<=i || strs[j-1].length() <=i
|| strs[j].charAt(i) != strs[j-1].charAt(i)){
flag = false;
break;
}
}
if(flag){
i++;
}else{
break;
}
}
65 | 568
36 Next Permutation
Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of
numbers.
If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending
order). The replacement must be in-place, do not allocate extra memory.
Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand
column.
36.1 Analysis
The steps to solve this problem: 1) scan from right to left, find the first element that is less than its previous one.
4 5 6 3 2 1
|
p
2) scan from right to left, find the first element that is greater than p.
4 5 6 3 2 1
|
q
3) swap p and q
4 5 6 3 2 1
swap
4 6 5 3 2 1
4 6 1 2 3 5
66 | 568
36 Next Permutation
if (mark == -1) {
reverse(nums, 0, nums.length - 1);
return;
}
[1,3,5,6], 5 -> 2
[1,3,5,6], 2 -> 1
[1,3,5,6], 7 -> 4
[1,3,5,6], 0 -> 0
int l=0;
int r=nums.length-1;
while(l<r){
int m = l+(r-l)/2;
if(target>nums[m]){
l=m+1;
}else{
r=m;
}
}
return l;
}
while(i<=j){
int mid = (i+j)/2;
68 | 568
37 Search Insert Position
}
}
return i;
}
if(k==0){
return Math.min(nums1[i1], nums2[i2]);
}
int len1 = j1 - i1 + 1;
int len2 = j2 - i2 + 1;
int m1 = k*len1/(len1+len2);
int m2 = k - m1 - 1;
m1 += i1;
m2 += i2;
if(nums1[m1]<nums2[m2]){
k = k-(m1-i1+1);
j2 = m2;
i1 = m1+1;
}else{
k = k-(m2-i2+1);
70 | 568
38 Median of Two Sorted Arrays
j1 = m1;
i2 = m2+1;
}
The main challenge is to calculate the middle elements, we can not do the following like a regular binary search:
int m1 = i1+(j1-i1)/2;
int m2 = i2+(j2-i2)/2;
It will result in either dead loop or missing the element at the beginning. The key is we always drop <= half
size of the elements.
39.1 Analysis
This problem is a binary search and the key is breaking the array to two parts, so that we can work on half of the
array each time.
If we pick the middle element, we can compare the middle element with the leftmost (or rightmost) element. If
the middle element is less than leftmost, the left half should be selected; if the middle element is greater than the
leftmost (or rightmost), the right half should be selected. Using recursion or iteration, this problem can be solved
in time log(n).
In addition, in any rotated sorted array, the rightmost element should be less than the left-most element,
otherwise, the sorted array is not rotated and we can simply pick the leftmost element as the minimum.
72 | 568
39 Find Minimum in Rotated Sorted Array
// 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);
}
}
/*
To understand the boundaries, use the following 3 examples:
[2,1], [2,3,1], [3,1,2]
*/
public int findMin(int[] nums) {
if(nums==null || nums.length==0)
return -1;
int i=0;
int j=nums.length-1;
while(i<=j){
if(nums[i]<=nums[j])
return nums[i];
int m=(i+j)/2;
if(nums[m]>=nums[i]){
i=m+1;
}else{
j=m;
}
}
return -1;
}
while(i<=j){
74 | 568
40 Find Minimum in Rotated Sorted Array II
if(nums[i]<=nums[j]){
return nums[i];
}
int m=(i+j)/2;
if(nums[m]>=nums[i]){
i=m+1;
}else{
j=m;
}
}
return -1;
}
41.1 Analysis
Based on the requirement of O(log n), this is a binary search problem apparently.
while(l<r){
int m=l+(r-l)/2;
if(nums[m]<target){
l=m+1;
}else{
r=m;
}
}
int first=l;
if(l<nums.length&&nums[l]==target){//l is in boundary and is the target
l=0;
r=nums.length-1;
while(l<r){
int m=l+(r-l+1)/2;
if(nums[m]>target){
r=m-1;
}else{
l=m;
}
}
76 | 568
41 Find First and Last Position of Element in Sorted Array
return arr;
}
public void binarySearch(int[] nums, int left, int right, int target, int[] arr){
if(right<left)
return;
if(nums[mid]<target){
binarySearch(nums, mid+1, right, target, arr);
}else if(nums[mid]>target){
binarySearch(nums, left, mid-1, target, arr);
}else{
arr[0]=mid;
arr[1]=mid;
In the worst case, the time of the second solution is actually O(n).
return -1;
}
low+((high-low)>>1)
(low+high)>>>1
Under the assumption that high and low are both non-negative, we know for sure that the upper-most bit (the
sign-bit) is zero.
So both high and low are in fact 31-bit integers.
high = 0100 0000 0000 0000 0000 0000 0000 0000 = 1073741824
low = 0100 0000 0000 0000 0000 0000 0000 0000 = 1073741824
When you add them together they may "spill" over into the top-bit.
78 | 568
42 Guess Number Higher or Lower
high + low = 1000 0000 0000 0000 0000 0000 0000 0000
= 2147483648 as unsigned 32-bit integer
= -2147483648 as signed 32-bit integer
(high + low) / 2 = 1100 0000 0000 0000 0000 0000 0000 0000 = -1073741824
(high + low) >>> 1 = 0100 0000 0000 0000 0000 0000 0000 0000 = 1073741824
if(i>=j)
return i;
if(isBadVersion(m)){
return helper(i, m);
}else{
return helper(m+1, j); //not bad, left --> m+1
}
}
if (isBadVersion(i)) {
return i;
}
return j;
80 | 568
43 First Bad Version
44.1 Analysis
In order to use binary search on the rotated sorted array, we need to determine how to update the left and right
pointers. There are two major cases as shown below:
Once the two cases are identified, the problem is straightforward to solve. We only need to check if the target
element is in the sorted side, and based on that move left or right pointers.
public int binarySearch(int[] nums, int left, int right, int target){
if(left>right)
82 | 568
44 Search in Rotated Sorted Array
return -1;
if(target == nums[mid])
return mid;
while(left<=right){
int mid = left + (right-left)/2;
if(target==nums[mid])
return mid;
if(nums[left]<=nums[mid]){
if(nums[left]<=target&& target<nums[mid]){
right=mid-1;
}else{
left=mid+1;
}
}else{
if(nums[mid]<target&& target<=nums[right]){
left=mid+1;
}else{
right=mid-1;
}
}
}
return -1;
}
while(left<=right){
int mid = (left+right)/2;
if(nums[mid]==target)
return true;
if(nums[left]<nums[mid]){
if(nums[left]<=target&& target<nums[mid]){
right=mid-1;
}else{
left=mid+1;
}
}else if(nums[left]>nums[mid]){
if(nums[mid]<target&&target<=nums[right]){
left=mid+1;
}else{
right=mid-1;
}
}else{
left++;
}
}
return false;
}
84 | 568
46 Longest Increasing Subsequence
Given an unsorted array of integers, find the length of longest increasing subsequence.
For example, given [10, 9, 2, 5, 3, 7, 101, 18], the longest increasing subsequence is [2, 3, 7, 101]. Therefore the
length is 4.
85 | 568
46 Longest Increasing Subsequence
max[i]=Math.max(max[i], max[j]+1);
}
}
}
int result = 0;
for(int i=0; i<max.length; i++){
if(max[i]>result)
result = max[i];
}
return result;
}
int result = 1;
for(int i=0; i<nums.length; i++){
for(int j=0; j<i; j++){
if(nums[i]>nums[j]){
max[i]= Math.max(max[i], max[j]+1);
}
}
result = Math.max(max[i], result);
}
return result;
}
while(i<j){
int mid = (i+j)/2;
if(list.get(mid) < num){
i=mid+1;
}else{
j=mid;
}
}
list.set(j, num);
}
}
return list.size();
}
Note that the problem asks the length of the sequence, not the sequence itself.
while(l<r){
int m = l + (r-l)/2;
if(nums[i]>sorted.get(m)){
l=m+1;
}else{
r=m;
}
}
sorted.add(r, nums[i]);
result.add(r);
}
}
Collections.reverse(result);
return result;
}
This solution is simple. However, note that time complexity of adding an element to a list is O(n), because
elements after the insertion position need to be shifted. So the time complexity is O(n2̂(logn)).
88 | 568
47 Count of Smaller Numbers After Self
class Solution {
public List<Integer> countSmaller(int[] nums) {
Collections.reverse(result);
return result;
}
while(p!=null){
if(value>p.value){
result+=p.count+p.numLeft;
if(p.right==null){
Node t = new Node(value);
t.count=1;
p.right=t;
return result;
}else{
p=p.right;
}
}else if(value==p.value){
p.count++;
return result+p.numLeft;
}else{
p.numLeft++;
if(p.left==null){
Node t = new Node(value);
t.count=1;
p.left=t;
return result;
}else{
p=p.left;
}
}
}
return 0;
}
}
class Node{
Node left;
Node right;
int value;
int count;
int numLeft;
public Node(int value){
this.value=value;
}
}
return max;
}
91 | 568
48 Russian Doll Envelopes
if(list.isEmpty()||target>list.get(list.size()-1)){
list.add(target);
}else{
int i=0;
int j=list.size()-1;
while(i<j){
int m = i + (j-i)/2;
if(list.get(m)>=target){
j = m;
}else{
i = m+1;
}
}
list.set(j, target);
}
}
return list.size();
}
Time complexity is O(n*log(n)) and we need O(n) of space for the list.
int result = 0;
for(int i=citations.length-1; i>=0; i--){
int cnt = citations.length-i;
if(citations[i]>=cnt){
result = cnt;
}else{
break;
}
}
return result;
}
93 | 568
49 HIndex
for(int c: citations){
counter[Math.min(len,c)]++;
}
int k=len;
for(int s=counter[len]; k > s; s += counter[k]){
k--;
}
return k;
}
if (len == 0) {
return 0;
}
if (len == 1) {
if (citations[0] == 0) {
return 0;
} else {
return 1;
}
}
int i = 0;
int j = len - 1;
while (i < j) {
int m = i + (j - i + 1) / 2;
if (citations[m] > len - m) {
j = m - 1;
} else {
i = m;
}
}
if (citations[j] == len - j) {
return len - j;
} else {
return len - j - 1;
}
}
95 | 568
51 Valid Anagram
Given two strings s and t, write a function to determine if t is an anagram of s.
if(s.length()!=t.length())
return false;
for(int i: arr){
if(i!=0)
return false;
}
return true;
}
96 | 568
51 Valid Anagram
char c2 = t.charAt(i);
if(map.containsKey(c2)){
if(map.get(c2)==1){
map.remove(c2);
}else{
map.put(c2, map.get(c2)-1);
}
}else{
return false;
}
}
if(map.size()>0)
return false;
return true;
}
[
["abc","bcd","xyz"],
["az","ba"],
["acef"],
["a","z"]
]
for(String s: strings){
char[] arr = s.toCharArray();
if(arr.length>0){
int diff = arr[0]-’a’;
for(int i=0; i<arr.length; i++){
if(arr[i]-diff<’a’){
arr[i] = (char) (arr[i]-diff+26);
}else{
arr[i] = (char) (arr[i]-diff);
}
}
}
98 | 568
52 Group Shifted Strings
result.addAll(map.values());
return result;
}
100 | 568
53 Palindrome Pairs
}
}
return result;
}
while(i<=j){
if(s.charAt(i)!=s.charAt(j)){
return false;
}
i++;
j--;
}
return true;
}
Time complexity is O(n*k2̂), where n is the number of words and k is the average length of each word.
int min=Integer.MAX_VALUE;
int max=Integer.MIN_VALUE;
set.add(arr[1]);
int y = min+max;
return true;
}
102 | 568
55 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.
55.1 Analysis
We can define a map which tracks the char-char mappings. If a value is already mapped, it can not be mapped
again.
if(map1.containsKey(c1)){
if(c2!=map1.get(c1)){
return false;
}
}else{
if(map2.containsKey(c2)){
return false;
}
map1.put(c1, c2);
map2.put(c2, c1);
}
}
return true;
}
Time complexity is O(n) and space complexity is O(n), where n is the length of the input string.
103 | 568
56 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:
104 | 568
57 Maximum Size Subarray Sum Equals k
Given an array nums and a target value k, find the maximum length of a subarray that sums to k. If there isn’t
one, return 0 instead.
Note: The sum of the entire nums array is guaranteed to fit within the 32-bit signed integer range.
Example 1: Given nums = [1, -1, 5, -2, 3], k = 3, return 4. (because the subarray [1, -1, 5, -2] sums to 3 and is the
longest)
int max = 0;
int sum=0;
for(int i=0; i<nums.length; i++){
sum += nums[i];
if(sum==k){
105 | 568
57 Maximum Size Subarray Sum Equals k
if(map.containsKey(diff)){
max = Math.max(max, i-map.get(diff));
}
if(!map.containsKey(sum)){
map.put(sum, i);
}
}
return max;
}
int count = 0;
int sum = 0;
//e.g., 1 1 2 1 1
for(int i=0; i<nums.length; i++){
sum += nums[i];
int n = map.getOrDefault(sum-k, 0);
count += n;
map.put(sum, map.getOrDefault(sum,0)+1);
}
return count;
}
107 | 568
59 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.
f(0) = 0
f(1) = nums[0]
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."
108 | 568
59 Maximum Subarray
return max;
}
}
The time complexity and space complexity are the same O(n). However, we can improve the space complexity
and make it to be O(1).
return result;
}
int sum = 0;
return result;
}
return result;
}
Time is O(n).
111 | 568
61 Longest Substring Without Repeating
Characters
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.
61.1 Analysis
The basic idea to solve this problem is using an extra data structure to track the unique characters in a sliding
window. Both an array and a hash set work for this purpose.
int result = 0;
int start = 0;
char[] arr = s.toCharArray();
return result;
112 | 568
61 Longest Substring Without Repeating Characters
/*
pwwkew
i |
j |
i |
j |
i |
j |
*/
public int lengthOfLongestSubstring(String s) {
if(s==null||s.length()==0){
return 0;
}
set.remove(s.charAt(i));
i++;
}
}
}
return result;
}
if(map.size()>2){
max = Math.max(max, i-start);
while(map.size()>2){
char t = s.charAt(start);
int count = map.get(t);
if(count>1){
map.put(t, count-1);
}else{
map.remove(t);
}
start++;
}
}
}
return max;
}
Now if this question is extended to be "the longest substring that contains k unique characters", what should
we do?
114 | 568
62 Longest Substring with At Most K Distinct Characters
if(map.size()<=k){
result = Math.max(result, j-i+1);
}else{
while(map.size()>k){
char l = s.charAt(i);
int count = map.get(l);
if(count==1){
map.remove(l);
}else{
map.put(l, map.get(l)-1);
}
i++;
}
}
return result;
}
Time is O(n).
63.1 Analysis
This problem is similar (almost the same) to Longest Substring Which Contains 2 Unique Characters.
Since each word in the dictionary has the same length, each of them can be treated as a single character.
//frequency of words
HashMap<String, Integer> map = new HashMap<String, Integer>();
for(String w: words){
if(map.containsKey(w)){
map.put(w, map.get(w)+1);
}else{
map.put(w, 1);
}
}
count++;
116 | 568
63 Substring with Concatenation of All Words
while(currentMap.get(sub)>map.get(sub)){
String left = s.substring(start, start+len);
currentMap.put(left, currentMap.get(left)-1);
count--;
start = start + len;
}
if(count==words.length){
result.add(start); //add to result
return result;
}
//target dictionary
for(int k=0; k<t.length(); k++){
goal.put(t.charAt(k), goal.getOrDefault(t.charAt(k), 0)+1);
}
int i=0;
int total=0;
HashMap<Character, Integer> map = new HashMap<>();
for(int j=0; j<s.length(); j++){
char c = s.charAt(j);
if(!goal.containsKey(c)){
continue;
}
//if c is a target character in the goal, and count is < goal, increase the total
int count = map.getOrDefault(c, 0);
if(count<goal.get(c)){
total++;
}
map.put(c, count+1);
//when total reaches the goal, trim from left until no more chars can be trimmed.
if(total==goalSize){
while(!goal.containsKey(s.charAt(i)) || map.get(s.charAt(i))>goal.get(s.charAt(i))){
char pc = s.charAt(i);
if(goal.containsKey(pc) && map.get(pc)>goal.get(pc)){
map.put(pc, map.get(pc)-1);
}
i++;
}
if(minLen>j-i+1){
minLen = j-i+1;
result = s.substring(i, j+1);
118 | 568
64 Minimum Window Substring
}
}
}
return result;
}
Input:
s = "aaabb", k = 3
Output:
3
The longest substring is "aaa", as ’a’ is repeated 3 times.
char c = s.charAt(i);
if(counter.containsKey(c)){
counter.put(c, counter.get(c)+1);
}else{
counter.put(c, 1);
}
if(splitSet.isEmpty()){
return s.length();
}
int max = 0;
int i=0, j=0;
while(j<s.length()){
char c = s.charAt(j);
if(splitSet.contains(c)){
120 | 568
65 Longest Substring with At Least K Repeating Characters
if(j!=i){
max = Math.max(max, longestSubstring(s.substring(i, j), k));
}
i=j+1;
}
j++;
}
if(i!=j)
max = Math.max(max, longestSubstring(s.substring(i, j), k));
return max;
}
if (j - i + 1 == s1.length()) {
return true;
}
} else {
while (i < j) {
if (s2.charAt(i) == s2.charAt(j)) {
i++;
break;
}
return false;
122 | 568
66 Permutation in String
while (set.contains(left)) {
count++;
set.remove(left);
left--;
}
while (set.contains(right)) {
count++;
set.remove(right);
right++;
}
return max;
}
124 | 568
67 Longest Consecutive Sequence
Arrays.sort(num);
return num[num.length / 2];
}
126 | 568
68 Majority Element
return result;
}
for(int i: nums){
if(n1!=null && i==n1.intValue()){
c1++;
}else if(n2!=null && i==n2.intValue()){
c2++;
}else if(c1==0){
c1=1;
n1=i;
}else if(c2==0){
c2=1;
n2=i;
}else{
c1--;
c2--;
}
}
c1=c2=0;
for(int i: nums){
if(i==n1.intValue()){
c1++;
}else if(i==n2.intValue()){
c2++;
}
}
if(c1>nums.length/3)
result.add(n1);
if(c2>nums.length/3)
result.add(n2);
return result;
}
128 | 568
70 Increasing Triplet Subsequence
Given an unsorted array return whether an increasing subsequence of length 3 exists or not in the array.
Examples: Given [1, 2, 3, 4, 5], return true.
Given [5, 4, 3, 2, 1], return false.
70.1 Analysis
This problem can be formalized as finding a sequence x, y and z, such that x <y <z .
if (x >= z) {
x = z;// update x to be a smaller value
} else if (y >= z) {
y = z; // update y to be a smaller value
} else {
return true;
}
}
return false;
129 | 568
70 Increasing Triplet Subsequence
71.1 Problem
Given an integer array, find the second largest number in the array.
71.2 Solution
The optimal time is linear to the length of the array N. We can iterate over the array, whenever the largest elements
get updated, its current value becomes the second largest.
return second;
}
131 | 568
72 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.
class WordNode{
String word;
int numSteps;
wordDict.add(endWord);
while(!queue.isEmpty()){
WordNode top = queue.remove();
String word = top.word;
if(word.equals(endWord)){
132 | 568
72 Word Ladder
return top.numSteps;
}
arr[i]=temp;
}
}
}
return 0;
}
}
[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]
class Solution {
if(t.equals(endWord)){
//add to result
134 | 568
73 Word Ladder II
Collections.reverse(aResult);
result.add(aResult);
if(unvisited.contains(t)){
Node n=new Node(t,top.depth+1,top);
queue.offer(n);
unvisited.remove(t);
}
}
}
}
return result;
}
}
class Node{
public String word;
public int depth;
public Node prev;
class Pair{
int num;
int count;
public Pair(int num, int count){
this.num=num;
this.count=count;
}
}
class Solution {
public List<Integer> topKFrequent(int[] nums, int k) {
//count the frequency for each element
HashMap<Integer, Integer> map = new HashMap<>();
for(int num: nums){
if(map.containsKey(num)){
map.put(num, map.get(num)+1);
}else{
map.put(num, 1);
}
}
136 | 568
74 Top K Frequent Elements
return result;
}
}
return result;
}
for(int i: nums){
if(counter.containsKey(i)){
counter.put(i, counter.get(i)+1);
}else{
counter.put(i, 1);
}
}
int i=0;
for(Map.Entry<Integer, Integer> entry: sortedMap.entrySet()){
result.add(entry.getKey());
i++;
if(i==k)
break;
}
return result;
}
}
if(diff==0){
return 1;
}else{
return diff;
}
}
}
return count;
}
There was a discussion in the comment about why a regular queue is not good enough. I draw an example
below to show why sorting based on start time and using a priority queue is necessary.
139 | 568
75 Meeting Rooms II
return true;
}
141 | 568
77 Range Addition
Assume you have an array of length n initialized with all 0’s and are given k update operations.
Each operation is represented as a triplet: [startIndex, endIndex, inc] which increments each element of subar-
ray A[startIndex ... endIndex] (startIndex and endIndex inclusive) with inc.
Return the modified array after all k operations were executed.
For example, Input: length = 5, updates = [[1,3,2],[2,4,3],[0,2,-2]] Output: [-2,0,3,5,3]
int sum=0;
int j=0;
for(int i=0; i<length; i++){
//substract value from sum when ending index is reached
while(!queue.isEmpty() && updates[queue.peek()][1] < i){
int top = queue.poll();
sum -= updates[top][2];
}
result[i]=sum;
}
142 | 568
77 Range Addition
return result;
}
int v=0;
for(int i=0; i<length; i++){
v += result[i];
result[i]=v;
}
return result;
}
@Override
public int compareTo(ArrayContainer o) {
return this.arr[this.index] - o.arr[o.index];
}
}
int m=0;
int result[] = new int[total];
return result;
}
144 | 568
78 Merge K Sorted Arrays in Java
int[] arr1 = { 1, 3, 5, 7 };
int[] arr2 = { 2, 4, 6, 8 };
int[] arr3 = { 0, 9, 10, 11 };
79.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).
while(!queue.isEmpty()){
ListNode n = queue.poll();
p.next = n;
p=p.next;
if(n.next!=null)
queue.offer(n.next);
}
return head.next;
146 | 568
80 Rearrange String k Distance Apart
Given a non-empty string str and an integer k, rearrange the string such that the same characters are at least
distance k from each other.
All input strings are given in lowercase letters. If it is not possible to rearrange the string, return an empty
string "".
Example:
str = "aabbcc", k = 3
Result: "abcabc"
for(char c: map.keySet())
queue.offer(c);
147 | 568
80 Rearrange String k Distance Apart
while(!queue.isEmpty()){
char c = queue.poll();
sb.append(String.valueOf(c));
map.put(c, map.get(c)-1);
if(map.get(c)>0){
temp.add(c);
}
len--;
}
for(char c: temp)
queue.offer(c);
}
return sb.toString();
}
class Solution {
public double mincostToHireWorkers(int[] quality, int[] wage, int K) {
ArrayList<Worker> list = new ArrayList<>();
for(int i=0; i<wage.length; i++){
list.add(new Worker(quality[i], wage[i]));
}
Comparator<Worker> comp = Comparator.comparing((Worker w) -> w.ratio);
Collections.sort(list, comp);
if(q.size()>K){
int extra = q.poll();
sum += extra;
}
if(q.size() == K){
result = Math.min(result, sum * w.ratio);
}
}
return result;
}
149 | 568
81 Minimum Cost to Hire K Workers
class Worker{
int quality;
int wage;
double ratio;
return false;
}
151 | 568
83 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.
map.put(nums[i], i);
}
return false;
}
int i=0;
if(set.size()>=k+1){
set.remove(nums[i++]);
}
}
return false;
}
152 | 568
84 Contains Duplicate III
Given an array of integers, find out whether there are two distinct indices i and j in the array such that the
difference between nums[i] and nums[j] is at most t and the difference between i and j is at most k.
set.add(curr);
if(i>=k){ // or if(set.size()>=k+1)
set.remove((long)nums[i-k]);
}
}
return false;
}
153 | 568
84 Contains Duplicate III
return false;
set.add(c);
if (i >= k)
set.remove(nums[i - k]);
}
return false;
}
Given matrix = [
[1, 0, 1],
[0, -2, 3]
]
k = 2
The answer is 2. Because the sum of rectangle [[0, 1], [-2, 3]] is 2 and 2 is the max number no larger than k (k =
2).
Note: The rectangle inside the matrix must have an area >0. What if the number of rows is much larger than
the number of columns?
85.1 Analysis
We can solve this problem by comparing each submatrix. This method is trivial and we need a better solution.
The key to the optimal solution is using a tree set to calculate the maximum sum of subarray close to k.
int m=matrix.length;
int n=matrix[0].length;
return result;
}
155 | 568
85 Max Sum of Rectangle No Larger Than K
int sum=0;
TreeSet<Integer> set = new TreeSet<Integer>();
int result=Integer.MIN_VALUE;
set.add(0);
set.add(sum);
}
return result;
}
The time complexity is O(n*n*m*log(m)). If m is greater than n, this solution is fine. However, if m is less than
n, then this solution is not optimal. In this case, we should reverse the row and column, like Solution 2.
int row=matrix.length;
int col=matrix[0].length;
return result;
}
int sum=0;
TreeSet<Integer> set = new TreeSet<Integer>();
int result=Integer.MIN_VALUE;
set.add(0);
set.add(sum);
}
return result;
}
158 | 568
86 Maximum Sum of Subarray Close to K
set.add(0);
set.add(sum);
}
return result;
}
160 | 568
87 Sliding Window Maximum
if(!deque.isEmpty()&&deque.peekFirst()==i-k)
deque.poll();
while(!deque.isEmpty()&&nums[deque.peekLast()]<nums[i]){
deque.removeLast();
}
deque.offer(i);
if(i+1>=k)
result[i+1-k]=nums[deque.peek()];
}
return result;
}
class MovingAverage {
double sum;
int size;
LinkedList<Integer> list;
if(list.size()<=size){
return sum/list.size();
}
sum -= list.poll();
return sum/size;
}
}
162 | 568
89 Find Median from Data Stream
Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So
the median is the mean of the two middle value.
89.1 Analysis
First of all, it seems that the best time complexity we can get for this problem is O(log(n)) of add() and O(1) of
getMedian(). This data structure seems highly likely to be a tree.
We can use heap to solve this problem. In Java, the PriorityQueue class is a priority heap. We can use two
heaps to store the lower half and the higher half of the data stream. The size of the two heaps differs at most 1.
163 | 568
89 Find Median from Data Stream
class MedianFinder {
PriorityQueue<Integer> minHeap = null;
PriorityQueue<Integer> maxHeap = null;
if(minHeap.size()<maxHeap.size()){
minHeap.offer(maxHeap.poll());
}
}
90.1 Analysis
We can store the interval in an array and each time iterator over the array and merge the new value to an existing
interval. This takes time O(n). If there are a lot of merges, we want to do it in log(n).
We can solve this problem using a tree set. The floor() method returns the greatest element in this set less than
or equal to the given element, or null if there is no such element. The higher() method returns the least element in
this set strictly greater than the given element, or null if there is no such element. Note: we use higher() instead
of ceiling() to exclude the given element.
TreeSet<Interval> set;
165 | 568
90 Data Stream as Disjoint Intervals
set.remove(ceil);
}
}
set.add(t);
}
/** @param head The linked list’s head. Note that the head is guanranteed to be not null, so it
contains at least one node. */
Random r=null;
ListNode h=null;
public Solution(ListNode head) {
r = new Random();
h = head;
}
167 | 568
92 Shuffle an Array
Shuffle a set of numbers without duplicates.
class Solution {
int[] original = null;
int[] shuffle = null;
Random rand = null;
168 | 568
92 Shuffle an Array
/** Resets the array to its original configuration and return it. */
public int[] reset() {
shuffle = Arrays.copyOf(original, original.length);
return shuffle;
}
return shuffle;
}
}
93.1 Analysis
If this problem does not have the constant space limitation, we can easily sort using a sorting method from Java
SDK. With the constant space limitation, we need to do some pointer manipulation.
• Break the list to two in the middle
• Recursively sort the two sub lists
• Merge the two sub lists
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode sortList(ListNode head) {
if(head==null || head.next==null){
return head;
}
170 | 568
93 Sort List
p1 = p1.next;
p2 = p2.next.next;
}
return head;
}
p = p.next;
}
if(p1!=null){
p.next = p1;
}
if(p2!=null){
p.next = p2;
}
return head.next;
}
}
• Select a pivot
• Move smaller elements to the left and move bigger elements to the right of the pivot
• Recursively sort left part and right part
This post shows two versions of the Java implementation. The first one picks the rightmost element as the pivot
and the second one picks the middle element as the pivot.
if(partition-1>start) {
quickSort(arr, start, partition - 1);
}
if(partition+1<end) {
quickSort(arr, partition + 1, end);
}
}
172 | 568
94 Quicksort Array in Java
arr[start] = pivot;
arr[end] = temp;
return start;
}
}
int low = 0;
int high = x.length - 1;
return;
if (i <= j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
}
}
if (high > i)
quickSort(arr, i, high);
}
}
Output:
9 2 4 7 3 7 10 2 3 4 7 7 9 10
Here is a very good animation of quicksort.
Time is O(nlog(n)). The problem of this solution is that sorting all elements is not necessary and is a overkill
for getting just one element.
if(q.size()>k){
q.poll();
}
}
return q.peek();
}
Time complexity of n*log(k) is an improvement to Solution 1. However, this solution requires O(k) space
complexity and it is also maintained k-element heap.
175 | 568
95 Kth Largest Element in an Array
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);
}
}
int j = 0;
int k = 0;
while(j<=2){
if(countArray[j]!=0){
nums[k++]=j;
countArray[j] = countArray[j]-1;
}else{
j++;
}
}
}
177 | 568
97 Maximum Gap
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.
97.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:
class Bucket{
178 | 568
97 Maximum Gap
int low;
int high;
public Bucket(){
low = -1;
high = -1;
}
}
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;
}
if(map.containsKey(ns)){
map.get(ns).add(str);
}else{
ArrayList<String> al = new ArrayList<String>();
al.add(str);
map.put(ns, al);
}
}
result.addAll(map.values());
return result;
}
180 | 568
99 Ugly Number
Write a program to check whether a given number is an ugly number. Ugly numbers are positive numbers whose
prime factors only include 2, 3, 5. For example, 6, 8 are ugly while 14 is not ugly since it includes another prime
factor 7. Note that 1 is typically treated as an ugly number.
if(num%2==0){
num=num/2;
return isUgly(num);
}
if(num%3==0){
num=num/3;
return isUgly(num);
}
if(num%5==0){
num=num/5;
return isUgly(num);
}
return false;
}
181 | 568
100 Ugly Number II
Write a program to find the n-th ugly number. Ugly numbers are positive numbers whose prime factors only
include 2, 3, 5. For example, 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 is the sequence of the first 10 ugly numbers. Note that 1 is
typically treated as an ugly number.
int i=0;
int j=0;
int k=0;
while(list.size()<n){
int m2 = list.get(i)*2;
int m3 = list.get(j)*3;
int m5 = list.get(k)*5;
if(min==m2)
i++;
if(min==m3)
j++;
if(min==m5)
k++;
}
return list.get(list.size()-1);
}
182 | 568
101 Super Ugly Number
Write a program to find the nth super ugly number.
Super ugly numbers are positive numbers whose all prime factors are in the given prime list primes of size k.
For example, [1, 2, 4, 7, 8, 13, 14, 16, 19, 26, 28, 32] is the sequence of the first 12 super ugly numbers given primes
= [2, 7, 13, 19] of size 4.
Note: (1) 1 is a super ugly number for any given primes. (2) The given numbers in primes are in ascending
order. (3) 0 <k <= 100, 0 <n <= 106, 0 <primes[i] <1000.
result[i] = min;
183 | 568
102 Find K Pairs with Smallest Sums
You are given two integer arrays nums1 and nums2 sorted in ascending order and an integer k.
Define a pair (u,v) which consists of one element from the first array and one element from the second array.
Find the k pairs (u1,v1),(u2,v2) ...(uk,vk) with the smallest sums.
Example:
Return: [1,2],[1,4],[1,6]
return result;
}
184 | 568
103 Rotate Array in Java
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?
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 System.arraycopy() and Arrays.copyOf().
185 | 568
103 Rotate Array in Java
i=0
0 1 2 3 4 5 6
0 1 2 3 4 6 5
...
6 0 1 2 3 4 5
i=1
6 0 1 2 3 5 4
...
5 6 0 1 2 3 4
i=2
5 6 0 1 2 4 3
...
4 5 6 0 1 2 3
reverse(arr, 0, a-1);
reverse(arr, a, arr.length-1);
reverse(arr, 0, arr.length-1);
}
}
reverse(s, i, s.length-1);
reverse(s, 0, s.length-1);
}
188 | 568
105 Missing Number
Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one that is missing from the array.
For example, given nums = [0, 1, 3] return 2.
int n=nums.length;
return n*(n+1)/2-sum;
}
int miss=0;
for(int i=0; i<nums.length; i++){
miss ^= (i+1) ^nums[i];
}
return miss;
}
return r;
}
189 | 568
106 Find the Duplicate Number
Given an array containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one
duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one.
Note: 1) You must not modify the array (assume the array is read only). 2) You must use only constant, O(1)
extra space. 3) Your runtime complexity should be less than O(n2̂). 4) There is only one duplicate number in the
array, but it could be repeated more than once.
do{
slow = nums[slow];
fast = nums[nums[fast]];
} while(slow != fast);
int find = 0;
while(find != slow){
slow = nums[slow];
find = nums[find];
}
return find;
}
If we can assume there is only one duplicate number, it can be easily solved by using the sum of the array.
190 | 568
106 Find the Duplicate Number
int n=nums.length;
return sum - ((n-1)*n)/2;
}
107.1 Analysis
This problem can solve by using a bucket-sort like algorithm. Let’s consider finding first missing positive and 0
first. The key fact is that the ith element should be i, so we have: i==A[i] A[i]==A[A[i]]
For example, given an array 1,2,0,4, the algorithm does the following:
192 | 568
107 First Missing Positive
return n;
}
if(A[i]==A[A[i]-1])
break;
return n + 1;
}
108.1 Analysis
The key to solve this problem is finding the start point of reconstruction. For this problem, we can start adding
the largest element first. The basic idea is to keep adding the largest element each time, until all elements are in
place.
return result;
}
194 | 568
109 Binary Watch
Given a non-negative integer n which represents the number of LEDs that are currently on, return all possible
times the watch could represent.
Example:
Input: n = 1 Return: ["1:00", "2:00", "4:00", "8:00", "0:01", "0:02", "0:04", "0:08", "0:16", "0:32"]
if(j<10){
s+="0"+j;
}else{
s+=j;
}
result.add(s);
}
}
}
return result;
}
while(num>0){
if((num&1)==1){
result++;
}
num>>=1;
}
return result;
}
195 | 568
109 Binary Watch
if(hSet.size()==0){
hoursList.add("0");
}else{
hoursList.addAll(getTime(hSet, true));
}
if(mSet.size()==0){
minsList.add("00");
}else{
minsList.addAll(getTime(mSet, false));
}
return result;
}
for(ArrayList<Integer> l : lists){
int sum=0;
for(int i: l){
sum+= (1<<(i-1));
}
if(isHour && sum>=12)
continue;
if(!isHour&&sum>=60)
continue;
return result;
}
[
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
int m = matrix.length;
int n = matrix[0].length;
int start = 0;
int end = m*n-1;
while(start<=end){
int mid=(start+end)/2;
int midX=mid/n;
int midY=mid%n;
if(matrix[midX][midY]==target)
return true;
if(matrix[midX][midY]<target){
start=mid+1;
}else{
end=mid-1;
}
}
return false;
}
}
198 | 568
111 Search a 2D Matrix II
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:
Integers in each row are sorted in ascending from left to right. Integers in each column are sorted in ascending
from top to bottom.
For example, consider the following matrix:
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
public boolean helper(int[][] matrix, int i1, int i2, int j1, int j2, int target){
if(i1>i2||j1>j2)
return false;
for(int j=j1;j<=j2;j++){
if(target < matrix[i1][j]){
return helper(matrix, i1, i2, j1, j-1, target);
}else if(target == matrix[i1][j]){
return true;
}
}
for(int i=i1;i<=i2;i++){
if(target < matrix[i][j1]){
return helper(matrix, i1, i-1, j1, j2, target);
}else if(target == matrix[i][j1]){
return true;
}
}
199 | 568
111 Search a 2D Matrix II
for(int j=j1;j<=j2;j++){
if(target > matrix[i2][j]){
return helper(matrix, i1, i2, j+1, j2, target);
}else if(target == matrix[i2][j]){
return true;
}
}
for(int i=i1;i<=i2;i++){
if(target > matrix[i][j2]){
return helper(matrix, i1, i+1, j1, j2, target);
}else if(target == matrix[i][j2]){
return true;
}
}
return false;
}
int i=m;
int j=0;
return false;
}
matrix = [
[ 1, 5, 9],
[10, 11, 13],
[12, 13, 15]
],
k = 8,
return 13.
while(lower<upper){
int mid = lower + ((upper-lower)>>1);
int count = count(matrix, mid);
if(count<k){
lower=mid+1;
}else{
upper=mid;
}
}
return upper;
}
while(i>=0&&j<m){
if(matrix[i][j]<=target){
count += i+1;
j++;
}else{
i--;
201 | 568
112 Kth Smallest Element in a Sorted Matrix
}
}
return count;
}
203 | 568
113 Design Snake Game
case "R":
y++;
break;
case "D":
x++;
break;
}
if(!isValid(x,y)){
return -1;
}
return true;
}
if(index==food.length){
queue.poll();
for(int[] p: queue){
if(p[0]==x&&p[1]==y)
return -1;
}
queue.offer(new int[]{x,y});
return len;
}
}
int[] p = positions[k];
int index = p[0]*n+p[1];
rootArray[index]=index;//set root to be itself for each node
for(int r=0;r<4;r++){
int i=p[0]+directions[r][0];
int j=p[1]+directions[r][1];
if(i>=0&&j>=0&&i<m&&j<n&&rootArray[i*n+j]!=-1){
//get neighbor’s root
int thisRoot = getRoot(rootArray, i*n+j);
if(thisRoot!=index){
rootArray[thisRoot]=index;//set previous root’s root
count--;
}
}
}
result.add(count);
}
return result;
}
205 | 568
114 Number of Islands II
return i;
}
0 3
| |
1 --- 2 4
Given n = 5 and edges = [[0, 1], [1, 2], [3, 4]], return 2.
207 | 568
115 Number of Connected Components in an Undirected Graph
if(xRoot!=yRoot){
count--;
root[xRoot]=yRoot;
}
return count;
}
There are k loops and each loop processing the root array costs log(n). Therefore, time complexity is O(k*log(n)).
Note:
class Solution {
int[] root = new int[1000]; //value is index
int result = 0;
return stones.length-result;
}
if(ri==rj){
return;
}
210 | 568
116 Most Stones Removed with Same Row or Column
root[getRoot(i)]=getRoot(j);
result--;
}
return i;
}
}
class Solution {
public int removeStones(int[][] stones) {
DisjointSet ds = new DisjointSet(20000);
for(int[] stone: stones){
ds.union(stone[0], stone[1]+10000);
}
class DisjointSet{
int[] parent;
public DisjointSet(int size){
parent = new int[size];
for(int i=0; i<size; i++){
parent[i] = i;
}
}
return i;
}
}
Input: nums =
[
[9,9,4],
[6,6,8],
[2,1,1]
]
Output: 4
Explanation: The longest increasing path is [1, 2, 6, 9].
return max[0];
}
public void dfs(int[][] matrix, int i, int j, int[] max, int len){
max[0]=Math.max(max[0], len);
int m=matrix.length;
int n=matrix[0].length;
213 | 568
117 Longest Increasing Path in a Matrix
}
}
int result = 0;
int m = matrix.length;
int n = matrix[0].length;
return result;
}
return ++mem[i][j];
}
Because of the memorization matrix, the upper bound time complexity of the DFS is O(m*n). With the loop in
the main method, the overall time complexity is O(m2̂ * n2̂)
[
["ABCE"],
["SFCS"],
["ADEE"]
]
word = "ABCCED", ->returns true, word = "SEE", ->returns true, word = "ABCB", ->returns false.
return result;
}
public boolean dfs(char[][] board, String word, int i, int j, int k){
int m = board.length;
int n = board[0].length;
if(board[i][j] == word.charAt(k)){
char temp = board[i][j];
board[i][j]=’#’;
if(k==word.length()-1){
return true;
}else if(dfs(board, word, i-1, j, k+1)
||dfs(board, word, i+1, j, k+1)
||dfs(board, word, i, j-1, k+1)
216 | 568
118 Word Search
return false;
}
return false;
}
public boolean dfs(char[][] board, String word, int i, int j, int k){
if(board[i][j]!=word.charAt(k)){
return false;
}
if(k>=word.length()-1){
return true;
}
int[] di={-1,0,1,0};
int[] dj={0,1,0,-1};
char t = board[i][j];
board[i][j]=’#’;
board[i][j]=t;
return false;
}
[
[’o’,’a’,’a’,’n’],
[’e’,’t’,’a’,’e’],
[’i’,’h’,’k’,’r’],
[’i’,’f’,’l’,’v’]
]
Return ["eat","oath"].
int m = board.length;
int n = board[0].length;
return result;
}
219 | 568
119 Word Search II
if (board[i][j] == word.charAt(k)) {
char temp = board[i][j];
board[i][j] = ’#’;
if (k == word.length() - 1) {
return true;
} else if (dfs(board, word, i - 1, j, k + 1)
|| dfs(board, word, i + 1, j, k + 1)
|| dfs(board, word, i, j - 1, k + 1)
|| dfs(board, word, i, j + 1, k + 1)) {
board[i][j] = temp;
return true;
}
} else {
return false;
}
return false;
}
int m=board.length;
int n=board[0].length;
public void dfs(char[][] board, boolean[][] visited, String str, int i, int j, Trie trie){
int m=board.length;
int n=board[0].length;
if(i<0 || j<0||i>=m||j>=n){
return;
}
if(visited[i][j])
return;
if(!trie.startsWith(str))
return;
if(trie.search(str)){
result.add(str);
}
visited[i][j]=true;
dfs(board, visited, str, i-1, j, trie);
dfs(board, visited, str, i+1, j, trie);
dfs(board, visited, str, i, j-1, trie);
dfs(board, visited, str, i, j+1, trie);
visited[i][j]=false;
}
}
//Trie Node
class TrieNode{
public TrieNode[] children = new TrieNode[26];
public String item = "";
}
//Trie
class Trie{
public TrieNode root = new TrieNode();
if(node.item.equals(word)){
return true;
}else{
return false;
}
}
11110
11010
11000
00000
Answer: 1
int m = grid.length;
int n = grid[0].length;
int count=0;
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
if(grid[i][j]==’1’){
count++;
merge(grid, i, j);
}
}
}
return count;
}
if(i<0||i>=m||j<0||j>=n||grid[i][j]!=’1’)
return;
grid[i][j]=’X’;
223 | 568
120 Number of Islands
merge(grid, i, j+1);
}
int m = grid.length;
int n = grid[0].length;
int count=0;
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
if(grid[i][j]==’1’){
root[i*n+j] = i*n+j;
count++;
}
}
}
if(x>=0&&x<m&&y>=0&&y<n&&grid[x][y]==’1’){
int cRoot = getRoot(root, i*n+j);
int nRoot = getRoot(root, x*n+y);
if(nRoot!=cRoot){
root[cRoot]=nRoot; //update previous node’s root to be current
count--;
}
}
}
}
}
}
return count;
}
return i;
}
[1, 0, 0, 0, 0]
[1, 0, 1, 1, 1]
[1, 1, 1, 0, 1]
[1, 0, 0, 0, 1]
[1, 0, 0, 0, 1]
A valid path is
[1, 0, 0, 0, 0]
[1, 0, 1, 1, 1]
[1, 1, 1, 0, 1]
[0, 0, 0, 0, 1]
[0, 0, 0, 0, 1]
result[0][0]=1;
return result;
}
int m=matrix.length;
226 | 568
121 Find a Path in a Matrix
list.clear();
list.addAll(temp);
return;
}
matrix[x][y]=prev;
temp.remove(temp.size()-1);
}
}
}
return false;
}
}
set.clear();
228 | 568
122 Sudoku Solver
}
if(board[k][j]!=’.’){
set.add(board[k][j]);
}
}
set.clear();
int x=i/3 * 3;
int y=j/3 * 3;
for(int m=x; m<x+3; m++){
for(int n=y; n<y+3; n++){
if(set.contains(board[m][n])){
return false;
}
if(board[m][n]!=’.’){
set.add(board[m][n]);
}
}
}
set.clear();
return true;
}
The time complexity is O(9m̂) where m represents the number of blanks to be filled. No extra space is needed.
231 | 568
123 Valid Sudoku
}
m[(int) (board[i][j] - ’1’)] = true;
}
}
}
return true;
}
int m = rooms.length;
int n = rooms[0].length;
public void fill(int[][] rooms, int i, int j, int start, boolean[][] visited){
int m=rooms.length;
int n=rooms[0].length;
if(i<0||i>=m||j<0||j>=n||rooms[i][j]<=0||visited[i][j]){
return;
}
visited[i][j]=false;
}
233 | 568
124 Walls and Gates
int m = rooms.length;
int n = rooms[0].length;
if(i<0||i>=m||j<0||j>=n||rooms[i][j]<distance){
return;
}
rooms[i][j] = distance;
int m = rooms.length;
int n = rooms[0].length;
while(!queue.isEmpty()){
int head = queue.poll();
int x=head/n;
int y=head%n;
X X X X
X O O X
X X O X
X O X X
X X X X
X X X X
X X X X
X O X X
125.1 Analysis
This problem is similar to Number of Islands. In this problem, only the cells on the boarders can not be sur-
rounded. So we can first merge those O’s on the boarders like in Number of Islands and replace O’s with ’#’, and
then scan the board and replace all O’s left (if any).
int m = board.length;
int n = board[0].length;
if(board[i][n-1] == ’O’){
merge(board, i, n-1);
}
}
236 | 568
125 Surrounded Regions
if(board[m-1][j] == ’O’){
merge(board, m-1, j);
}
}
int m=board.length;
int n=board[0].length;
if(board[m-1][j]==’O’){
bfs(board, m-1, j);
}
}
while(!queue.isEmpty()){
int top = queue.poll();
int i=top/n;
int j=top%n;
}
}
}
126.1 Analysis
This problem should be solved in place, i.e., no other array should be used. We can use the first column and the
first row to track if a row/column should be set to 0.
Since we used the first row and first column to mark the zero row/column, the original values are changed.
Step 1: First row contains zero = true; First column contains zero = false;
240 | 568
126 Set Matrix Zeroes
if(firstRowZero){
for(int i=0; i<matrix[0].length; i++)
matrix[0][i] = 0;
}
}
}
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
int m = matrix.length;
int n = matrix[0].length;
int x=0;
int y=0;
243 | 568
127 Spiral Matrix
//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;
}
}
int m = matrix.length;
int n = matrix[0].length;
int left=0;
int right=n-1;
int top = 0;
int bottom = m-1;
while(result.size()<m*n){
for(int j=left; j<=right; j++){
result.add(matrix[top][j]);
}
top++;
}
bottom--;
return result;
}
return spiralOrder(matrix,0,0,matrix.length,matrix[0].length);
}
public ArrayList<Integer> spiralOrder(int [][] matrix, int x, int y, int m, int n){
ArrayList<Integer> result = new ArrayList<Integer>();
if(m<=0||n<=0)
return result;
}
}
//left - move up
if(n>1){
for(int i=0;i<m-1;i++){
result.add(matrix[x--][y]);
}
}
if(m==1||n==1)
result.addAll(spiralOrder(matrix, x, y, 1, 1));
else
result.addAll(spiralOrder(matrix, x+1, y+1, m-2, n-2));
return result;
}
}
[
[1, 2, 3, 4],
[12, 13, 14, 5],
[11, 16, 15, 6],
[10, 9, 8, 7]
]
int x=0;
int y=0;
int step = 0;
for(int i=0;i<total;){
while(y+step<n){
i++;
result[x][y]=i;
y++;
}
y--;
x++;
while(x+step<n){
i++;
result[x][y]=i;
x++;
}
x--;
y--;
while(y>=0+step){
i++;
result[x][y]=i;
y--;
}
y++;
x--;
step++;
while(x>=0+step){
247 | 568
128 Spiral Matrix II
i++;
result[x][y]=i;
x--;
}
x++;
y++;
}
return result;
}
int k=1;
int top=0;
int bottom=n-1;
int left=0;
int right=n-1;
while(k<=n*n){
for(int i=left; i<=right; i++){
result[top][i]=k;
k++;
}
top++;
return result;
}
249 | 568
130 Range Sum Query 2D Immutable
Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper left corner (row1,
col1) and lower right corner (row2, col2).
130.1 Analysis
Since the assumption is that there are many calls to sumRegion method, we should use some extra space to store
the intermediate results.
The solution is similar to other sum related problems such as . The basic idea is demonstrated in the following
example:
250 | 568
130 Range Sum Query 2D Immutable
[Pleaseinsert\PrerenderUnicode{âĂŞ}intopreamble]-Immutable.png
Here we define an array sum[][] which stores the sum value from (0,0) to the current cell.
int m = matrix.length;
int n = matrix[0].length;
sum = new int[m][n];
}
}
}
public int sumRegion(int row1, int col1, int row2, int col2) {
if(this.sum==null)
return 0;
int bottomLeftX=row2;
int bottomLeftY= col1;
int result=0;
}else if(col1==0){
result = sum[row2][col2]
-sum[topRightX-1][topRightY];
}else{
result = sum[row2][col2]
-sum[topRightX-1][topRightY]
-sum[bottomLeftX][bottomLeftY-1]
+sum[row1-1][col1-1];
}
return result;
}
}
int[][] numReach;
int[][] distance;
int m = grid.length;
int n = grid[0].length;
int numBuilding = 0;
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
if(grid[i][j]==1){
boolean[][] visited = new boolean[m][n];
LinkedList<Integer> queue = new LinkedList<Integer>();
bfs(grid, i, j, i, j, 0, visited, queue);
numBuilding++;
}
}
}
int result=Integer.MAX_VALUE;
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
if(grid[i][j] == 0 && numReach[i][j]==numBuilding){
result = Math.min(result, distance[i][j]);
}
}
253 | 568
131 Shortest Distance from All Buildings
public void bfs(int[][] grid, int ox, int oy, int i, int j,
int distanceSoFar, boolean[][] visited, LinkedList<Integer> queue){
while(!queue.isEmpty()){
int size = queue.size();
distanceSoFar++;
}
}
public void visit(int[][] grid, int ox, int oy, int i, int j, int distanceSoFar, boolean[][] visited,
LinkedList<Integer> queue){
int m = grid.length;
int n = grid[0].length;
visited[i][j]=true;
numReach[i][j]++;
distance[i][j]+= distanceSoFar;
queue.offer(i*n+j);
}
}
1 - 0 - 0 - 0 - 1
| | | | |
0 - 0 - 0 - 0 - 0
| | | | |
0 - 0 - 1 - 0 - 0
The point (0,2) is an ideal meeting point, as the total travel distance of 2+2+2=6 is minimal. So return 6.
int sum=0;
for(Integer i: rows){
sum += Math.abs(i - rows.get(rows.size()/2));
}
Collections.sort(cols);
for(Integer i: cols){
sum+= Math.abs(i-cols.get(cols.size()/2));
}
return sum;
}
255 | 568
133 Game of Life
Given a board with m by n cells, each cell has an initial state live (1) or dead (0). Each cell interacts with its eight
neighbors (horizontal, vertical, diagonal) using the following four rules:
Any live cell with fewer than two live neighbors dies, as if caused by under-population. Any live cell with two
or three live neighbors lives on to the next generation. Any live cell with more than three live neighbors dies, as
if by over-population.. Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.
Write a function to compute the next state (after one update) of the board given its current state.
int m=board.length;
int n=board[0].length;
//<2 die
if(count<2){
board[i][j] &= 1;
}
//same state
if(count==2||count==3){
board[i][j] |= board[i][j]<<1;
}
//go live
if(count==3){
board[i][j] |=2;
}
//>3 die
256 | 568
133 Game of Life
if(count>3){
board[i][j] &=1;
}
}
}
}
}
}
int[][] matrix;
//check row
boolean win=true;
for(int i=0; i<matrix.length; i++){
if(matrix[row][i]!=player){
win=false;
break;
}
}
//check column
win=true;
for(int i=0; i<matrix.length; i++){
if(matrix[i][col]!=player){
win=false;
break;
}
}
258 | 568
134 TicTacToe
win=true;
for(int i=0; i<matrix.length; i++){
if(matrix[i][i]!=player){
win=false;
break;
}
}
return 0;
}
}
rows[row]+=val;
cols[col]+=val;
if(row==col){
dc1+=val;
}
if(col==n-row-1){
dc2+=val;
}
if(Math.abs(rows[row])==n
|| Math.abs(cols[col])==n
|| Math.abs(dc1)==n
|| Math.abs(dc2)==n){
return player;
}
return 0;
}
}
return C;
}
261 | 568
135 Sparse Matrix Multiplication
return C;
}
Since the matrix is sparse, time complexity is O(n2̂) which is much faster than O(n3̂).
/*
2 -> 4 -> 3
5 -> 6 -> 4
7 0 8
*/
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode fake = new ListNode(0);
ListNode p = fake;
ListNode p1 = l1;
ListNode p2 = l2;
int carry = 0;
while(p1!=null || p2!=null){
int sum = carry;
if(p1!=null){
sum += p1.val;
p1 = p1.next;
}
if(p2!=null){
sum += p2.val;
p2 = p2.next;
}
if(sum>9){
carry=1;
sum = sum-10;
}else{
carry = 0;
}
263 | 568
136 Add Two Numbers
return fake.next;
}
What if the digits are stored in regular order instead of reversed order?
Answer: We can simple reverse the list, calculate the result, and reverse the result.
ListNode(int x) {
val = x;
next = null;
}
}
printList(n1);
reorderList(n1);
printList(n1);
}
265 | 568
137 Reorder List
//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;
}
Merge List:
Note that pointers movements always starts with assigning the next node to a temporary variable t.
138.1 Analysis
If we have 2 pointers - fast and slow. It is guaranteed that the fast one will meet the slow one if there exists a
circle.
if(slow == fast)
return true;
}
return false;
}
}
269 | 568
139 Copy List with Random Pointer
A linked list is given such that each node contains an additional random pointer which could point to any node
in the list or null.
Return a deep copy of the list.
if (head == null)
return null;
RandomListNode p = head;
return newHead;
}
270 | 568
139 Copy List with Random Pointer
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:
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;
}
140.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.
while(l1!=null||l2!=null){
if(l1!=null&&l2!=null){
if(l1.val < l2.val){
p.next = l1;
l1=l1.next;
}else{
p.next=l2;
l2=l2.next;
}
p = p.next;
}else if(l1==null){
p.next = l2;
break;
}else if(l2==null){
p.next = l1;
break;
}
}
return head.next;
}
ListNode p1=l1;
ListNode p2=l2;
while(p1!=null && p2!=null){
if(p1.val < p2.val){
272 | 568
140 Merge Two Sorted Lists
p.next = p1;
p1 = p1.next;
}else{
p.next = p2;
p2 = p2.next;
}
p=p.next;
}
if(p1!=null){
p.next = p1;
}
if(p2!=null){
p.next = p2;
}
return head.next;
}
141.1 Problem
Given a singly linked list, group all odd nodes together followed by the even nodes. Please note here we are
talking about the node number and not the value in the nodes.
The program should run in O(1) space complexity and O(nodes) time complexity.
Example:
Given 1->2->3->4->5->NULL,
return 1->3->5->2->4->NULL.
141.2 Analysis
This problem can be solved by using two pointers. We iterate over the link and move the two pointers.
274 | 568
141 Odd Even Linked List
p1.next = p2.next;
p1 = p1.next;
p2.next = p1.next;
p2 = p2.next;
}
p1.next = connectNode;
return result;
}
142.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.
142.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;
}
}
276 | 568
142 Remove Duplicates from Sorted List
142.3 Solution 2
ListNode p = head;
return head;
}
}
ListNode p = t;
while(p.next!=null&&p.next.next!=null){
if(p.next.val == p.next.next.val){
int dup = p.next.val;
while(p.next!=null&&p.next.val==dup){
p.next = p.next.next;
}
}else{
p=p.next;
}
return t.next;
}
278 | 568
144 Partition List
Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or
equal to x.
You should preserve the original relative order of the nodes in each of the two partitions.
For example, given 1->4->3->2->5->2 and x = 3, return 1->2->2->4->3->5.
ListNode p = head;
ListNode prev = fakeHead1;
ListNode p2 = fakeHead2;
while(p != null){
if(p.val < x){
p = p.next;
prev = prev.next;
}else{
p2.next = p;
prev.next = p.next;
p = prev.next;
p2 = p2.next;
}
}
prev.next = fakeHead2.next;
return fakeHead1.next;
}
}
279 | 568
145 Intersection of Two Linked Lists
145.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
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int len1 = 0;
int len2 = 0;
ListNode p1=headA, p2=headB;
if (p1 == null || p2 == null)
return null;
while(p1 != null){
len1++;
p1 = p1.next;
}
while(p2 !=null){
len2++;
p2 = p2.next;
}
int diff = 0;
p1=headA;
p2=headB;
280 | 568
145 Intersection of Two Linked Lists
}
p1 = p1.next;
p2 = p2.next;
}
return null;
}
}
while(p.next != null){
if(p.next.val == val){
ListNode next = p.next;
p.next = next.next;
}else{
p = p.next;
}
}
return helper.next;
}
282 | 568
147 Swap Nodes in Pairs
Given a linked list, swap every two adjacent nodes and return its head.
For example, given 1->2->3->4, you should return the list as 2->1->4->3.
Your algorithm should use only constant space. You may not modify the values in the list, only nodes itself can
be changed.
return h.next;
}
ListNode p1 = head;
ListNode p2 = head.next;
283 | 568
147 Swap Nodes in Pairs
ListNode pre = h;
while(p1!=null && p2!=null){
pre.next = p2;
ListNode t = p2.next;
p2.next = p1;
pre = p1;
p1.next = t;
p1 = p1.next;
if(t!=null)
p2 = t.next;
}
return h.next;
}
ListNode p1 = head;
ListNode p2 = p1.next;
head.next = null;
while(p1!=null&& p2!=null){
ListNode t = p2.next;
p2.next = p1;
p1 = p2;
p2 = t;
}
return p1;
}
285 | 568
148 Reverse Linked List
return rest;
}
149.1 Analysis
int i=0;
ListNode p = head;
while(p!=null){
i++;
if(i==m-1){
prev = p;
}
if(i==m){
first.next = p;
}
if(i==n){
second.next = p.next;
p.next = null;
}
p= p.next;
}
if(first.next == null)
return head;
287 | 568
149 Reverse Linked List II
return head;
}
/*
* For your reference:
*
* DoublyLinkedListNode {
* int data;
* DoublyLinkedListNode next;
* DoublyLinkedListNode prev;
* }
*
*/
static DoublyLinkedListNode reverse(DoublyLinkedListNode head) {
DoublyLinkedListNode p = head;
DoublyLinkedListNode newHead = head;
while(p!=null){
DoublyLinkedListNode t = p.next;
p.next = p.prev;
p.prev = t;
289 | 568
150 Reverse Double Linked List
newHead= p;
p = t;
}
return newHead;
}
return head;
}
291 | 568
151 Remove Nth Node From End of List
while(fast.next != null){
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return head;
}
ListNode p = head;
ListNode prev = new ListNode(head.val);
while(p.next != null){
ListNode temp = new ListNode(p.next.val);
temp.next = prev;
prev = temp;
p = p.next;
}
ListNode p1 = head;
ListNode p2 = prev;
while(p1!=null){
if(p1.val != p2.val)
return false;
p1 = p1.next;
p2 = p2.next;
}
return true;
}
293 | 568
152 Palindrome Linked List
secondHead.next = null;
p = p.next;
q = q.next;
return true;
}
//stop recursion
if (right == null)
return true;
return y;
}
}
296 | 568
154 Reverse Nodes in kGroup
Given a linked list, reverse the nodes of a linked list k at a time and return its modified list. If the number of
nodes is not a multiple of k then left-out nodes in the end should remain as it is. You may not alter the values in
the nodes, only nodes itself may be changed.
For example,
ListNode p = head;
while(p!=null){
i++;
if(i%k==0){
prev = reverse(prev, p.next);
p = prev.next;
}else{
p = p.next;
}
}
return fake.next;
}
while(curr != next){
last.next = curr.next;
curr.next = prev.next;
prev.next = curr;
curr = last.next;
}
return last;
297 | 568
154 Reverse Nodes in kGroup
We can write the reverse method differently like the following. I personally it is more understandable.
while(p2 != next){
ListNode t = p2.next;
p2.next = p1;
p1 = p2;
p2 = t;
}
prev.next.next = next;
prev.next = p1;
return rNode;
Input:
1->2->3
Output:
1->2->4
ListNode p=h2;
while(p!=null){
if(p.val+1<=9){
p.val=p.val+1;
break;
}else{
p.val=0;
if(p.next==null){
p.next = new ListNode(1);
break;
}
p=p.next;
}
}
return reverse(h2);
}
ListNode p1=head;
ListNode p2=p1.next;
while(p2!=null){
ListNode t = p2.next;
p2.next=p1;
p1=p2;
p2=t;
}
300 | 568
155 Plus One Linked List
head.next=null;
return p1;
}
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);
}
}
return returnList;
}
}
302 | 568
157 Binary Tree Inorder Traversal
There are 3 solutions for solving this problem.
TreeNode p = root;
while(p!=null){
stack.push(p);
p=p.left;
}
while(!stack.isEmpty()){
TreeNode t = stack.pop();
result.add(t.val);
t = t.right;
while(t!=null){
stack.push(t);
t = t.left;
}
}
return result;
}
return result;
}
303 | 568
157 Binary Tree Inorder Traversal
result.add(p.val);
if(p.right!=null)
helper(p.right);
}
}
while(!stack.isEmpty()){
TreeNode top = stack.peek();
if(top.left!=null){
stack.push(top.left);
top.left=null;
}else{
result.add(top.val);
stack.pop();
if(top.right!=null){
stack.push(top.right);
}
}
}
return result;
}
• The order of "Postorder" is: left child ->right child ->parent node.
• Find the relation between the previously visited node and the current node
• Use a stack to track nodes
As we go down the tree to the lft, check the previously visited node. If the current node is the left or right child
of the previous node, then keep going down the tree, and add left/right node to stack when applicable. When
there is no children for current node, i.e., the current node is a leaf, pop it from the stack. Then the previous node
become to be under the current node for next loop. You can using an example to walk through the code.
if(root == null)
return lst;
305 | 568
158 Binary Tree Postorder Traversal
prev = curr;
}
return lst;
}
}
if(root==null) {
return res;
}
while(!stack.isEmpty()) {
TreeNode temp = stack.peek();
if(temp.left==null && temp.right==null) {
TreeNode pop = stack.pop();
res.add(pop.val);
}
else {
if(temp.right!=null) {
stack.push(temp.right);
temp.right = null;
}
if(temp.left!=null) {
stack.push(temp.left);
temp.left = null;
}
}
}
return res;
}
3
/ \
9 20
/ \
15 7
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;
}
308 | 568
159 Binary Tree Level Order Traversal
if(root==null){
return result;
}
nodeQueue.offer(root);
levelQueue.offer(1);//start from 1
while(!nodeQueue.isEmpty()){
TreeNode node = nodeQueue.poll();
int level = levelQueue.poll();
List<Integer> l=null;
if(result.size()<level){
l = new ArrayList<>();
result.add(l);
}else{
l = result.get(level-1);
}
l.add(node.val);
if(node.left!=null){
nodeQueue.offer(node.left);
levelQueue.offer(level+1);
}
if(node.right!=null){
nodeQueue.offer(node.right);
levelQueue.offer(level+1);
}
}
return result;
}
3
/ \
9 20
/ \
15 7
if(root == null){
return result;
}
numberList.add(head.val);
if(head.left != null){
next.offer(head.left);
}
if(head.right!= null){
next.offer(head.right);
}
if(current.isEmpty()){
current = next;
next = new LinkedList<TreeNode>();
result.add(numberList);
numberList = new ArrayList<Integer>();
}
}
//return Collections.reverse(result);
310 | 568
160 Binary Tree Level Order Traversal II
return reversedResult;
}
while (!q1.isEmpty()) {
TreeNode node = q1.poll();
int order = q2.poll();
//add to map
ArrayList<Integer> list = map.get(order);
if (list == null) {
list = new ArrayList<>();
map.put(order, list);
}
list.add(node.val);
if (node.left != null) {
q1.offer(node.left);
q2.offer(order - 1);
}
if (node.right != null) {
q1.offer(node.right);
q2.offer(order + 1);
}
}
}
312 | 568
161 Binary Tree Vertical Order Traversal
Time complexity is O(n*log(n)) and space complexity is O(n). n is the number of nodes on the tree.
TreeNode t = n.left;
n.left = n.right;
n.right = t;
helper(n.left);
helper(n.right);
}
if(root!=null){
queue.add(root);
}
while(!queue.isEmpty()){
TreeNode p = queue.poll();
if(p.left!=null)
queue.add(p.left);
if(p.right!=null)
queue.add(p.right);
return root;
}
314 | 568
163 Kth Smallest Element in a BST
Given a binary search tree, write a function kthSmallest to find the kth smallest element in it. (1 ≤ k ≤ BST’s total
elements)
TreeNode p = root;
int result = 0;
while(!stack.isEmpty() || p!=null){
if(p!=null){
stack.push(p);
p = p.left;
}else{
TreeNode t = stack.pop();
k--;
if(k==0)
result = t.val;
p = t.right;
}
}
return result;
}
if(i==k)
return t.val;
TreeNode r = t.right;
while(r!=null){
stack.push(r);
315 | 568
163 Kth Smallest Element in a BST
r=r.left;
}
return -1;
}
nodeQueue.offer(root);
sizeQueue.offer(1);
int max=1;
while(!nodeQueue.isEmpty()){
TreeNode head = nodeQueue.poll();
int size = sizeQueue.poll();
if(head.left!=null){
int leftSize=size;
if(head.val==head.left.val-1){
leftSize++;
max = Math.max(max, leftSize);
}else{
leftSize=1;
}
nodeQueue.offer(head.left);
sizeQueue.offer(leftSize);
}
if(head.right!=null){
int rightSize=size;
if(head.val==head.right.val-1){
rightSize++;
max = Math.max(max, rightSize);
}else{
rightSize=1;
}
nodeQueue.offer(head.right);
sizeQueue.offer(rightSize);
}
317 | 568
164 Binary Tree Longest Consecutive Sequence
return max;
}
class Solution {
int max;
int leftTotal = 0;
if(t.left == null){
leftTotal = 1;
}else if(t.val+1 == t.left.val){
leftTotal = leftMax+1;
}else{
leftTotal = 1;
}
int rightTotal = 0;
if(t.right == null){
rightTotal = 1;
}else if(t.val+1 == t.right.val){
rightTotal = rightMax+1;
}else{
rightTotal = 1;
}
return longer;
}
}
• The left subtree of a node contains only nodes with keys less than the node’s key.
• The right subtree of a node contains only nodes with keys greater than the node’s key.
• Both the left and right subtrees must also be binary search trees.
This solution also goes to the left subtree first. If the violation occurs close to the root but on the right subtree,
the method still cost time O(n) and space O(h).
The following solution can handle violations close to root node faster.
if(root.val<=min||root.val>=max){
return false;
}
if(!isLeftBST||!isRightBST){
return false;
319 | 568
165 Validate Binary Search Tree
return true;
}
1
/ \
2 5
/ \ \
3 4 6
1
\
2
\
3
\
4
\
5
\
6
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* 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){
321 | 568
166 Flatten Binary Tree to Linked List
p.right = p.left;
p.left = null;
}else if(!stack.empty()){
TreeNode temp = stack.pop();
p.right=temp;
}
p = p.right;
}
}
}
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.
/**
* 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){
323 | 568
167 Path Sum
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;
}
}
5
/ \
4 8
/ / \
11 13 4
/ \ / \
7 2 5 1
[
[5,4,11,2],
[5,8,4,5]
]
168.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.
325 | 568
168 Path Sum II
169.1 Analysis
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.
327 | 568
169 Construct Binary Tree from Inorder and Postorder Traversal
int k = 0;
for (int i = 0; i < inorder.length; i++) {
if (inorder[i] == rootValue) {
k = i;
break;
}
}
return root;
}
170.1 Analysis
Consider the following example:
in-order: 4 2 5 (1) 6 7 3 8
pre-order: (1) 2 4 5 3 7 6 8
From the pre-order array, we know that first element is the root. We can find the root in in-order array. Then
we can identify the left and right sub-trees of the root from in-order array.
Using the length of left sub-tree, we can identify left and right sub-trees in pre-order array. Recursively, we can
build up the tree.
public TreeNode construct(int[] preorder, int preStart, int preEnd, int[] inorder, int inStart, int
inEnd){
if(preStart>preEnd||inStart>inEnd){
return null;
}
329 | 568
170 Construct Binary Tree from Preorder and Inorder Traversal
return p;
}
TreeNode(int x) {
val = x;
}
}
return root;
}
}
331 | 568
172 Convert Sorted List to Binary Search Tree
Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST.
172.1 Thoughts
If you are given an array, the problem is quite straightforward. But things get a little more complicated when you
have a singly linked list instead of an array. Now you no longer have random access to an element in O(1) time.
Therefore, you need to create nodes bottom-up, and assign them to its parents. The bottom-up approach enables
us to access the list in its order at the same time as creating nodes.
ListNode(int x) {
val = x;
next = null;
}
}
TreeNode(int x) {
val = x;
}
}
h = head;
int len = getLength(head);
return sortedListToBST(0, len - 1);
}
332 | 568
172 Convert Sorted List to Binary Search Tree
int len = 0;
ListNode p = head;
while (p != null) {
len++;
p = p.next;
}
return len;
}
// mid
int mid = (start + end) / 2;
root.left = left;
root.right = right;
return root;
}
}
173.1 Thoughts
LinkedList is a queue in Java. The add() and remove() methods are used to manipulate the queue.
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public int minDepth(TreeNode root) {
if(root == null){
return 0;
}
nodes.add(root);
counts.add(1);
while(!nodes.isEmpty()){
TreeNode curr = nodes.remove();
int count = counts.remove();
if(curr.left != null){
nodes.add(curr.left);
counts.add(count+1);
}
if(curr.right != null){
nodes.add(curr.right);
counts.add(count+1);
334 | 568
173 Minimum Depth of Binary Tree
}
}
return 0;
}
}
1
/ \
2 3
the result is 6.
174.1 Analysis
1) Recursively solve this problem 2) Get largest left sum and right sum 2) Compare to the stored maximum
return current;
}
336 | 568
175 Balanced Binary Tree
Given a binary tree, determine if it is height-balanced.
For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees
of every node never differ by more than 1.
175.1 Analysis
This is a typical tree problem that can be solve by using recursion.
TreeNode(int x) {
val = x;
}
}
if (getHeight(root) == -1)
return false;
return true;
}
337 | 568
175 Balanced Binary Tree
}
}
176.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
1
/ \
2 2
\ \
3 3
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;
}
339 | 568
177 Binary Search Tree Iterator
177.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; }
* }
*/
340 | 568
177 Binary Search Tree Iterator
}
}
1 <---
/ \
2 3 <---
\
5 <---
178.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.
342 | 568
178 Binary Tree Right Side View
return result;
}
Similarly, we can also use two queues which makes the code slightly more readable.
q1.offer(root);
q2.offer(1);
int prev = 0;
while (!q1.isEmpty()) {
TreeNode h = q1.poll();
int level = q2.poll();
if (level != prev) {
result.add(h.val);
}
if (h.right != null) {
q1.offer(h.right);
q2.offer(level + 1);
}
if (h.left != null) {
q1.offer(h.left);
q2.offer(level + 1);
}
prev = level;
}
return result;
}
179.1 Analysis
This problem can be solved by using BST property, i.e., left <parent <right for each node. There are 3 cases to
handle.
return root;
}
while(t!=null){
if(p.val >t.val && q.val >t.val){
t = t.right;
}else if (p.val<t.val && q.val<t.val){
t = t.left;
}else{
return t;
}
}
return null;
}
344 | 568
180 Lowest Common Ancestor of a Binary Tree
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.
if(root==p || root==q)
return root;
if(l!=null&&r!=null){
return root;
}else if(l==null&&r==null){
return null;
}else{
return l==null?r:l;
}
}
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
CounterNode n = helper(root, p, q);
return n.node;
}
345 | 568
180 Lowest Common Ancestor of a Binary Tree
int c=left.count+right.count+(root==p?1:0)+(root==q?1:0);
}
}
class CounterNode{
public int count;
public TreeNode node;
helper(root, map);
int maxCount = 0;
for(int i: map.keySet()){
if(map.get(i)>maxCount){
maxCount=map.get(i);
}
}
return result;
}
347 | 568
181 Most Frequent Subtree Sum
return sum;
}
9
/ \
3 2
/ \ / \
4 1 # 6
/ \ / \ / \
# # # # # #
For example, the above binary tree can be serialized to the string "9,3,4,#,#,1,#,#,2,#,6,#,#", where # represents a
null node.
Given a string of comma separated values, verify whether it is a correct preorder traversal serialization of a
binary tree. Find an algorithm without reconstructing the tree.
while(stack.size()>=3
349 | 568
182 Verify Preorder Serialization of a Binary Tree
&& stack.get(stack.size()-1).equals("#")
&& stack.get(stack.size()-2).equals("#")
&& !stack.get(stack.size()-3).equals("#")){
stack.remove(stack.size()-1);
stack.remove(stack.size()-1);
stack.remove(stack.size()-1);
stack.add("#");
}
If only stack operations are allowed, the solution can be written in the following way:
1
/ \
2 3
/ \ / \
4 5 6 7
1 -> NULL
/ \
2 -> 3 -> NULL
/ \ / \
4->5->6->7 -> NULL
if(root!=null){
nodeQueue.offer(root);
depthQueue.offer(1);
}
while(!nodeQueue.isEmpty()){
TreeLinkNode topNode = nodeQueue.poll();
int depth = depthQueue.poll();
if(depthQueue.isEmpty()){
topNode.next = null;
}else if(depthQueue.peek()>depth){
topNode.next = null;
}else{
topNode.next = nodeQueue.peek();
}
if(topNode.left!=null){
nodeQueue.offer(topNode.left);
depthQueue.offer(depth+1);
}
if(topNode.right!=null){
351 | 568
183 Populating Next Right Pointers in Each Node
nodeQueue.offer(topNode.right);
depthQueue.offer(depth+1);
}
}
}
while(lastHead!=null){
lastCurrent = lastHead;
while(lastCurrent!=null){
if(currentHead == null){
currentHead = lastCurrent.left;
current = lastCurrent.left;
}else{
current.next = lastCurrent.left;
current = current.next;
}
if(currentHead != null){
current.next = lastCurrent.right;
current = current.next;
}
lastCurrent = lastCurrent.next;
}
184.1 Analysis
Similar to Populating Next Right Pointers in Each Node, we have 4 pointers at 2 levels of the tree.
while(lastHead!=null){
lastCurrent = lastHead;
while(lastCurrent!=null){
//left child is not null
if(lastCurrent.left!=null) {
if(currentHead == null){
currentHead = lastCurrent.left;
current = lastCurrent.left;
}else{
current.next = lastCurrent.left;
current = current.next;
354 | 568
184 Populating Next Right Pointers in Each Node II
}
}
lastCurrent = lastCurrent.next;
}
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
185.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,
count[0] = 1;
count[1] = 1;
356 | 568
185 Unique Binary Search Trees
return count[n];
}
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
186.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.
return result;
358 | 568
186 Unique Binary Search Trees II
1
/ \
2 3
The root-to-leaf path 1->2 represents the number 12. The root-to-leaf path 1->3 represents the number 13.
Return the sum = 12 + 13 = 25.
for(ArrayList<TreeNode> a: all){
StringBuilder sb = new StringBuilder();
for(TreeNode n: a){
sb.append(String.valueOf(n.val));
}
int currValue = Integer.valueOf(sb.toString());
result = result + currValue;
}
return result;
}
if(n.left!=null){
l.add(n.left);
dfs(n.left, l, all);
l.remove(l.size()-1);
}
360 | 568
187 Sum Root to Leaf Numbers
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;
}
The following two solutions are improvements to this solution. The idea is that we can skip some elements to
reduce time in the average case.
362 | 568
188 Count Complete Tree Nodes
if(left==right){
return (2<<(left-1))-1;
}else{
return countNodes(root.left)+countNodes(root.right)+1;
}
}
int height=0;
while(n.left!=null){
height++;
n = n.left;
}
return height;
}
int height=0;
while(n.right!=null){
height++;
n = n.right;
}
return height;
}
Each time, you will have to do traversals along the left and right edges. At level h, you iterate zero times (no
child). At level h - 1, you iterate once (one child). And so on. So that is 0 + 1 + 2 + ... + h steps just to compute
the left edges, which is h(1 + h)/2 = O(h2̂). The countNodes part has f(n) = 2 * 2 ...* 2 = 2ĥ which is the number
of nodes. Therefore, the time complexity is bounded by O(n) where n is the number of nodes in the tree.
if(level >=height){
return false;
}
if(level == height-1){
if(t.right == null){
miss[0]++;
}
if(t.left == null){
miss[0]++;
}
if(t.left!=null){
return false;
}
}
return true;
}
Average time complexity is O(n/2), which is half of the number of nodes in the tree.
while(root!=null){
if(target>root.val){
365 | 568
189 Closest Binary Search Tree Value
}
root = root.right;
}else if(target<root.val){
return result;
}
if(root==null)
return finalResult;
for(ArrayList<String> al : results){
StringBuilder sb = new StringBuilder();
sb.append(al.get(0));
for(int i=1; i<al.size();i++){
sb.append("->"+al.get(i));
}
finalResult.add(sb.toString());
}
return finalResult;
}
if(root.left!=null){
ArrayList<String> temp = new ArrayList<String>(curr);
dfs(root.left, list, temp);
}
if(root.right!=null){
ArrayList<String> temp = new ArrayList<String>(curr);
dfs(root.right, list, temp);
}
}
367 | 568
190 Binary Tree Paths
String sb = "";
ArrayList<String> result = new ArrayList<String>();
return result;
}
s = s+"->"+root.val;
if(root.left==null &&root.right==null){
result.add(s.substring(2));
return;
}
if(root.left!=null){
helper(root.left, result, s);
}
if(root.right!=null){
helper(root.right, result, s);
}
}
return bigger+1;
}
369 | 568
192 Recover Binary Search Tree
Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing its
structure.
inorder(root.left);
if(pre==null){
pre=root;
}else{
if(root.val<pre.val){
if(first==null){
first=pre;
}
second=root;
}
pre=root;
}
inorder(root.right);
}
inorder(root);
if(second!=null && first !=null){
int val = second.val;
second.val = first.val;
first.val = val;
}
}
}
370 | 568
193 Same Tree
Two binary trees are considered the same if they have identical structure and nodes have the same value.
This problem can be solved by using a simple recursive function.
if(p.val==q.val){
return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
}else{
return false;
}
}
371 | 568
194 Serialize and Deserialize Binary Tree
Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your serializa-
tion/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized to a
string and this string can be deserialized to the original tree structure.
queue.add(root);
while(!queue.isEmpty()){
TreeNode t = queue.poll();
if(t!=null){
sb.append(String.valueOf(t.val) + ",");
queue.add(t.left);
queue.add(t.right);
}else{
sb.append("#,");
}
}
sb.deleteCharAt(sb.length()-1);
System.out.println(sb.toString());
return sb.toString();
}
int i=1;
while(!queue.isEmpty()){
TreeNode t = queue.poll();
372 | 568
194 Serialize and Deserialize Binary Tree
if(t==null)
continue;
if(!arr[i].equals("#")){
t.left = new TreeNode(Integer.parseInt(arr[i]));
queue.offer(t.left);
}else{
t.left = null;
queue.offer(null);
}
i++;
if(!arr[i].equals("#")){
t.right = new TreeNode(Integer.parseInt(arr[i]));
queue.offer(t.right);
}else{
t.right = null;
queue.offer(null);
}
i++;
}
return root;
}
while(!stack.isEmpty()){
TreeNode h = stack.pop();
if(h!=null){
sb.append(h.val+",");
stack.push(h.right);
stack.push(h.left);
}else{
sb.append("#,");
}
}
if(data == null)
return null;
int[] t = {0};
String[] arr = data.split(",");
t[0]=t[0]+1;
root.left = helper(arr, t);
t[0]=t[0]+1;
root.right = helper(arr, t);
return root;
}
if(c==null)
return null;
if(c.right==null)
return next;
c = c.right;
while(c.left!=null)
c = c.left;
return c;
}
When the tree is balanced, time complexity is O(log(n)) and space is O(1). The worst case time complexity is
O(n).
375 | 568
196 Inorder Successor in BST II
Given a binary search tree and a node in it, find the in-order successor of that node in the BST.
The successor of a node p is the node with the smallest key greater than p.val. You will have direct access to
the node but not to the root of the tree. Each node will have a reference to its parent node. A node is defined as
the following:
//case 1: right child is not null -> go down to get the next
Node p = x.right;
while(p!=null){
result = p;
p = p.left;
}
if(result != null){
return result;
}
while(p!=null){
if(p.parent!=null && p.parent.left==p){
return p.parent;
}
p = p.parent;
}
return null;
}
376 | 568
196 Inorder Successor in BST II
If the tree is balanced, the time complexity is the height of the tree - O(log(n)). In the worst cast, the time is
O(n). Space complexity is constant.
1
/ \
2 3
/ \
4 5
return result;
}
378 | 568
197 Find Leaves of Binary Tree
if(root==null){
return 0;
}
list.get(curr).add(root.val);
return curr;
}
class Wrapper{
int size;
int lower, upper;
boolean isBST;
public Wrapper(){
lower = Integer.MAX_VALUE;
upper = Integer.MIN_VALUE;
isBST = false;
size = 0;
}
}
public class Solution {
public int largestBSTSubtree(TreeNode root) {
return helper(root).size;
}
if(node == null){
curr.isBST= true;
return curr;
}
Wrapper l = helper(node.left);
Wrapper r = helper(node.right);
return curr;
380 | 568
198 Largest BST Subtree
}
}
class TrieNode {
char c;
HashMap<Character, TrieNode> children = new HashMap<Character, TrieNode>();
boolean isLeaf;
public TrieNode() {}
public Trie() {
root = new TrieNode();
}
382 | 568
199 Implement Trie (Prefix Tree)
TrieNode t;
if(children.containsKey(c)){
t = children.get(c);
}else{
t = new TrieNode(c);
children.put(c, t);
}
children = t.children;
return t;
}
}
class TrieNode {
TrieNode[] arr;
boolean isEnd;
// Initialize your data structure here.
public TrieNode() {
this.arr = new TrieNode[26];
}
public Trie() {
root = new TrieNode();
}
return false;
}
if(p==root)
return null;
return p;
}
}
If the same words can be inserted more than once, what do you need to change to make it work?
void addWord(word)
bool search(word)
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.
class TrieNode{
char c;
HashMap<Character, TrieNode> children = new HashMap<Character, TrieNode>();
boolean isLeaf;
public TrieNode() {}
WordDictionary
public WordDictionary(){
root = new TrieNode();
}
TrieNode t = null;
if(children.containsKey(c)){
t = children.get(c);
}else{
t = new TrieNode(c);
children.put(c,t);
}
386 | 568
200 Add and Search Word Data structure design
children = t.children;
if(i == word.length()-1){
t.isLeaf = true;
}
}
}
char c = word.charAt(start);
if(children.containsKey(c)){
if(start == word.length()-1 && children.get(c).isLeaf){
return true;
}
return result;
}else{
return false;
}
}
}
class TrieNode{
TrieNode[] arr;
boolean isLeaf;
public TrieNode(){
arr = new TrieNode[26];
}
}
public WordDictionary(){
root = new TrieNode();
}
// Adds a word into the data structure.
public void addWord(String word) {
TrieNode p= root;
for(int i=0; i<word.length(); i++){
char c=word.charAt(i);
int index = c-’a’;
if(p.arr[index]==null){
TrieNode temp = new TrieNode();
p.arr[index]=temp;
p=temp;
}else{
p=p.arr[index];
}
}
p.isLeaf=true;
}
char c = word.charAt(start);
if (c == ’.’) {
boolean tResult = false;
for (int j = 0; j < 26; j++) {
if (p.arr[j] != null) {
if (dfsSearch(p.arr[j], word, start + 1)) {
tResult = true;
break;
}
}
}
if (tResult)
return true;
} else {
int index = c - ’a’;
if (p.arr[index] != null) {
return dfsSearch(p.arr[index], word, start + 1);
} else {
return false;
}
}
return false;
}
}
class TreeNode{
int start;
int end;
int sum;
TreeNode leftChild;
TreeNode rightChild;
390 | 568
201 Range Sum Query Mutable
if(root.start==root.end&& root.start==i){
root.sum=val;
return;
}
root.sum=root.leftChild.sum+root.rightChild.sum;
}
return result;
}
if(i==j){
return new TreeNode(i, j, nums[i]);
}
current.sum = current.leftChild.sum+current.rightChild.sum;
return current;
}
}
int[] btree;
int[] arr;
}
return sum;
}
}
202.1 Analysis
This problem is essentially a problem of processing 2*n edges. Each edge has a x-axis value and a height value.
The key part is how to use the height heap to process each edge.
class Edge {
int x;
int height;
boolean isStart;
// sort edges
Collections.sort(edges, new Comparator<Edge>() {
public int compare(Edge a, Edge b) {
if (a.x != b.x)
return Integer.compare(a.x, b.x);
394 | 568
202 The Skyline Problem
return a.isStart ? -1 : 1;
}
});
// process edges
PriorityQueue<Integer> heightHeap = new PriorityQueue<Integer>(10, Collections.reverseOrder());
if(heightHeap.isEmpty()){
result.add(new int[] {edge.x, 0});
}else if(edge.height > heightHeap.peek()){
result.add(new int[]{edge.x, heightHeap.peek()});
}
}
}
return result;
}
203.1 Analysis
This problem can be solved by using two queues.
class MyStack {
LinkedList<Integer> queue1 = new LinkedList<Integer>();
LinkedList<Integer> queue2 = new LinkedList<Integer>();
396 | 568
203 Implement Stack using Queues
class MyQueue {
value.push(x);
while(!temp.isEmpty()){
value.push(temp.pop());
}
}
}
398 | 568
205 Implement a Stack Using an Array in Java
This post shows how to implement a stack by using an array.
The requirements of the stack are: 1) the stack has a constructor which accepts a number to initialize its size,
2) the stack can hold any type of elements, 3) the stack has a push() and a pop() method.
@SuppressWarnings("unchecked")
public Stack(int cap) {
this.CAP = cap;
this.arr = (E[]) new Object[cap];
}
public E pop() {
if(this.size == 0){
return null;
}
this.size--;
E result = this.arr[top];
this.arr[top] = null;//prevent memory leaking
this.top--;
return result;
}
this.size++;
this.arr[++top] = e;
return true;
}
399 | 568
205 Implement a Stack Using an Array in Java
if(this.size==0){
return null;
}
sb.setLength(sb.length()-2);
return sb.toString();
}
System.out.println(stack);
stack.pop();
System.out.println(stack);
stack.pop();
System.out.println(stack);
}
}
Output:
hello, world
hello
null
This example is used twice in "Effective Java". In the first place, the stack example is used to illustrate memory
leak. In the second place, the example is used to illustrate when we can suppress unchecked warnings.
You may check out how to implement a queue by using an array.
import java.lang.reflect.Array;
import java.util.Arrays;
E[] arr;
int head = -1;
int tail = -1;
int size;
boolean push(E e) {
if (size == arr.length)
return false;
if(tail == -1){
tail = head;
}
return true;
}
boolean pop() {
if (size == 0) {
return false;
}
401 | 568
206 Implement a Queue using an Array in Java
E result = arr[tail];
arr[tail] = null;
size--;
tail = (tail+1)%arr.length;
if (size == 0) {
head = -1;
tail = -1;
}
return true;
}
E peek(){
if(size==0)
return null;
return arr[tail];
}
The following is the code. However, this code contains compilation errors in leetcode. Why?
403 | 568
207 Evaluate Reverse Polish Notation
returnValue = Integer.valueOf(stack.pop());
return returnValue;
}
}
The problem is that switch string statement is only available from JDK 1.7. Leetcode apparently use a JDK
version below 1.7.
int returnValue = 0;
for(String t : tokens){
if(!operators.contains(t)){
stack.push(t);
}else{
int a = Integer.valueOf(stack.pop());
int b = Integer.valueOf(stack.pop());
int index = operators.indexOf(t);
switch(index){
case 0:
stack.push(String.valueOf(a+b));
break;
case 1:
stack.push(String.valueOf(b-a));
break;
case 2:
stack.push(String.valueOf(a*b));
break;
case 3:
stack.push(String.valueOf(b/a));
break;
}
}
}
returnValue = Integer.valueOf(stack.pop());
return returnValue;
}
}
208.1 Analysis
A typical problem which can be solved by using a stack data structure.
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();
}
406 | 568
209 Longest Valid Parentheses
Given a string containing just the characters ’(’ and ’)’, find the length of the longest valid (well-formed) paren-
theses substring.
For "(()", the longest valid parentheses substring is "()", which has length = 2. Another example is ")()())", where
the longest valid parentheses substring is "()()", which has length = 4.
return result;
}
407 | 568
210 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.
class Elem{
public int value;
public int min;
public Elem next;
408 | 568
210 Min Stack
if(top == null)
return -1;
return top.value;
}
211.1 Analysis
The key to solve this problem is using a stack to track the existing chunk. Each chunk is represented a min and
max number. Each chunk is essentially an interval and the interval can not overlap.
while(!stack.isEmpty()){
int[] top = stack.peek();
stack.push(new int[]{min,max});
}
return stack.size();
}
410 | 568
212 Maximal Rectangle
Given a 2D binary matrix filled with 0’s and 1’s, find the largest rectangle containing all ones and return its area.
212.1 Analysis
This problem can be converted to the "Largest Rectangle in Histogram" problem.
int maxArea = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (matrix[i][j] == ’0’) {
height[i][j] = 0;
} else {
height[i][j] = i == 0 ? 1 : height[i - 1][j] + 1;
}
}
}
return maxArea;
}
int i = 0;
int max = 0;
411 | 568
212 Maximal Rectangle
}
}
return max;
}
Given s = "[123,[456,[789]]]",
case ’]’:
if(sb.length()>0){ //123, not [456],
stack.peek().add(new NestedInteger(Integer.parseInt(sb.toString())));
sb=sb.delete(0, sb.length());
}
413 | 568
213 Mini Parser
break;
case ’,’:
if(sb.length()>0){ //hande case "123," not "[456],"
stack.peek().add(new NestedInteger(Integer.parseInt(sb.toString())));
sb=sb.delete(0, sb.length());
}
break;
default: //digits
sb.append(c);
}
}
return null;
}
@Override
public Integer next() {
return stack.pop().getInteger();
}
@Override
public boolean hasNext() {
while(!stack.isEmpty()){
NestedInteger top = stack.peek();
if(top.isInteger()){
return true;
}else{
stack.pop();
for(int i=top.getList().size()-1; i>=0; i--){
stack.push(top.getList().get(i));
}
}
}
return false;
}
}
415 | 568
214 Flatten Nested List Iterator
stack.push(nestedList.iterator());
}
@Override
public Integer next() {
Integer result = current;
current = null;
return result;
}
@Override
public boolean hasNext() {
while(!stack.isEmpty() && current==null){
Iterator<NestedInteger> top = stack.peek();
if(!top.hasNext()){
stack.pop();
continue;
}
NestedInteger n = top.next();
if(n.isInteger()){
current = n.getInteger();
return true;
}else{
stack.push(n.getList().iterator());
}
}
return false;
}
}
int sum=0;
for(NestedInteger ni: nestedList){
if(ni.isInteger()){
sum += ni.getInteger() * depth;
}else{
sum += helper(ni.getList(), depth+1);
}
}
return sum;
}
while(!queue.isEmpty()){
NestedInteger top = queue.poll();
int dep = depth.poll();
if(top.isInteger()){
sum += dep*top.getInteger();
417 | 568
215 Nested List Weight Sum
}else{
for(NestedInteger ni: top.getList()){
queue.offer(ni);
depth.offer(dep+1);
}
}
}
return sum;
}
//two stacks: one is for processing nested integer, the other is for tracking layers.
Stack<NestedInteger> stack = new Stack<NestedInteger>();
Stack<Integer> layers = new Stack<Integer>();
int maxLayer=Integer.MIN_VALUE;
while(!stack.isEmpty()){
NestedInteger top = stack.pop();
int topLayer = layers.pop();
maxLayer=Math.max(maxLayer, topLayer);
if(top.isInteger()){
if(map.containsKey(topLayer)){
map.get(topLayer).add(top.getInteger());
}else{
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(top.getInteger());
map.put(topLayer, list);
}
}else{
for(NestedInteger ni: top.getList()){
stack.push(ni);
layers.push(topLayer+1);
}
}
419 | 568
216 Nested List Weight Sum II
// calcualte sum
int result=0;
for(int i=maxLayer; i>=1; i--){
if(map.get(i)!=null){
for(int v: map.get(i)){
result += v*(maxLayer-i+1);
}
}
}
return result;
}
class Node{
int num;
ArrayList<Node> list;
char symbol;
boolean isList;
421 | 568
217 Decode String
stack.push(new Node(1));
String t = "";
while (i < s.length()) {
char c = s.charAt(i);
// new Node
if (c >= ’0’ && c <= ’9’) {
t += c;
} else if (c == ’[’) {
if (t.length() > 0) {
int num = Integer.parseInt(t);
stack.push(new Node(num));
t = "";
}
} else if (c == ’]’) {
Node top = stack.pop();
if (stack.isEmpty()) {
} else {
stack.peek().list.add(top);
}
} else {
stack.peek().list.add(new Node(c));
}
i++;
}
return getString(stack.peek());
}
return s;
}
}
import java.util.ArrayList;
import java.util.Stack;
423 | 568
218 Evaluate math expression with plus, minus and parentheses
sb = new StringBuilder();
}
sb.append(c);
if (i == s.length() - 1
|| s.charAt(i + 1) < ’0’ || s.charAt(i + 1) > ’9’) {
top.list.add(new Node(
isPositive == null ? true : isPositive,
Integer.valueOf(sb.toString())));
isPositive = null;
sb = null;
}
} else if (c == ’(’) {
Node t = new Node(isPositive, null);
isPositive = null;
top.list.add(t);
stack.push(t);
} else if (c == ’)’) {
int val = stack.pop().evaluate();
top = stack.peek();
top.list.get(top.list.size() - 1).value = val;
} else if (c == ’-’ || c == ’+’) {
if (c == ’-’) {
isPositive = false;
} else {
isPositive = true;
}
}
}
return stack.peek().evaluate();
}
//sort array
Arrays.sort(nums);
int j=nums.length-1;
if(nums[j]>share){
return false;
}
while(j>=0 && nums[j]==share){
j--;
k--;
}
425 | 568
219 Partition to K Equal Sum Subsets
return true;
}
buckets[i]-=nums[j];
}
if(buckets[i]==0) break;//
}
return false;
}
For example,
[1,2,3] have the following permutations:
[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], and [3,2,1].
[1]
[2, 1]
[1, 2]
[3, 2, 1]
[2, 3, 1]
[2, 1, 3]
[3, 1, 2]
[1, 3, 2]
[1, 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.
//System.out.println(temp);
427 | 568
220 Permutations
return result;
}
swap(nums, i, start);
helper(start+1, nums, result);
swap(nums, i, start);
}
}
430 | 568
221 Permutations II
return returnList;
}
"123"
"132"
"213"
"231"
"312"
"321"
Given n and k, return the kth permutation sequence. (Note: Given n will be between 1 and 9 inclusive.)
// 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;
432 | 568
222 Permutation Sequence
return result.toString();
}
}
output[s - 1] = true;
buf.append(Integer.toString(s));
}
return buf.toString();
}
}
434 | 568
223 Number of Squareful Arrays
class Solution {
int count = 0;
if(start==A.length-1){
count++;
return;
}
swap(A, i, start);
helper(A, start+1);
swap(A, i, start);
}
}
if(left==0&&right==0){
result.add(s);
return;
}
if(left>0){
dfs(result, s+"(", left-1, right);
}
if(right>0){
dfs(result, s+")", left, right-1);
}
}
result.add("");
437 | 568
224 Generate Parentheses
diff.add(0);
if (i < 2 * n - 1) {
temp1.add(s + "(");
temp2.add(k + 1);
}
return result;
}
[7]
[2, 2, 3]
private void helper(int[] candidates, int start, int target, int sum,
439 | 568
225 Combination Sum
if(sum==target){
result.add(new ArrayList<>(list));
return;
}
public void helper(List<List<Integer>> result, List<Integer> curr, int start, int target, int[]
candidates){
if(target==0){
result.add(new ArrayList<Integer>(curr));
return;
}
if(target<0){
return;
}
int prev=-1;
for(int i=start; i<candidates.length; i++){
if(prev!=candidates[i]){ // each time start from different element
curr.add(candidates[i]);
helper(result, curr, i+1, target-candidates[i], candidates); // and use next element only
curr.remove(curr.size()-1);
prev=candidates[i];
}
}
}
441 | 568
227 Combination Sum III
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]]
227.1 Analysis
Related problems: Combination Sum, Combination Sum II.
public void helper(List<List<Integer>> result, List<Integer> curr, int k, int start, int sum){
if(sum<0){
return;
}
442 | 568
228 Combination Sum IV
Given an integer array with all positive numbers and no duplicates, find the number of possible combinations
that add up to a positive integer target.
dp[0]=1;
return dp[target];
}
443 | 568
229 Wildcard Matching
Implement wildcard pattern matching with support for ’?’ and ’*’.
return j == p.length();
}
444 | 568
230 Regular Expression Matching
Implement regular expression matching with support for ’.’ and ’*’.
’.’ Matches any single character. ’*’ Matches zero or more of the preceding element.
The matching should cover the entire input string (not partial).
The function prototype should be: bool isMatch(const char *s, const char *p)
Some examples: isMatch("aa","a") return false isMatch("aa","aa") return true isMatch("aaa","aa") return false
isMatch("aa", "a*") return true isMatch("aa", ".*") return true isMatch("ab", ".*") return true isMatch("aab", "c*a*b")
return true
230.1 Analysis
First of all, this is one of the most difficulty problems. It is hard to think through all different cases. The problem
should be simplified to handle 2 basic cases:
For the 1st case, if the first char of pattern is not ".", the first char of pattern and string should be the same.
Then continue to match the remaining part.
For the 2nd case, if the first char of pattern is "." or first char of pattern == the first i char of string, continue to
match the remaining part.
if(p.length() == 0)
return s.length() == 0;
}else{
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;
445 | 568
230 Regular Expression Matching
}
}
}
// 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;
}
}
return count;
}
if (s1.charAt(i) != s2.charAt(j)) {
return false;
}
if (i + 2 < s1.length()
&& s1.charAt(i + 1) == s2.charAt(j)
&& s1.charAt(i + 2) == s2.charAt(j)) {
int m = i + 2;
int n = j + 1;
while (m < s1.length() && s1.charAt(m) == s2.charAt(j)) {
448 | 568
231 Expressive Words
m++;
}
while (n < s2.length() && s2.charAt(n) == s2.charAt(n - 1)) {
n++;
}
if (n - j > m - i) {
return false;
}
return res;
}
232.1 Analysis
This is a partition problem which can be solved by using depth first search.
int i = 0;
int j = list.size() - 1;
return false;
}
450 | 568
232 Get Target Number Using Number List and Arithmetic Operations
return result;
}
if(s==null)
return result;
return result;
}
452 | 568
234 Flip Game II
You are playing the following Flip Game with your friend: Given a string that contains only these two characters:
+ and -, you and your friend take turns to flip two consecutive "++" into "–". The game ends when a person can
no longer make a move and therefore the other person will be the winner.
Write a function to determine if the starting player can guarantee a win.
For example, given s = "++++", return true. The starting player can guarantee a win by flipping the middle
"++" to become "+–+".
return canWinHelper(s.toCharArray());
}
arr[i]=’+’;
arr[i+1]=’+’;
//if there is a flip which makes the other player lose, the first play wins
if(!win){
return true;
}
}
}
return false;
}
453 | 568
235 Word Pattern
Given a pattern and a string str, find if str follows the same pattern. Here follow means a full match, such that
there is a bijection between a letter in pattern and a non-empty word in str.
return true;
}
454 | 568
236 Word Pattern II
This is the extension problem of Word Pattern I.
Given a pattern and a string str, find if str follows the same pattern.
Here follow means a full match, such that there is a bijection between a letter in pattern and a non-empty
substring in str.
Examples: pattern = "abab", str = "redblueredblue" should return true. pattern = "aaaa", str = "asdasdasdasd"
should return true. pattern = "aabb", str = "xyzabcxzyabc" should return false.
public boolean helper(String pattern, String str, int i, int j, HashMap<Character, String> map){
if(i==pattern.length() && j==str.length()){
return true;
}
if(i>=pattern.length() || j>=str.length())
return false;
char c = pattern.charAt(i);
for(int k=j+1; k<=str.length(); k++){
String sub = str.substring(j, k);
if(!map.containsKey(c) && !map.containsValue(sub)){
map.put(c, sub);
if(helper(pattern, str, i+1, k, map))
return true;
map.remove(c);
}else if(map.containsKey(c) && map.get(c).equals(sub)){
if(helper(pattern, str, i+1, k, map))
return true;
}
}
return false;
}
Since containsValue() method is used here, the time complexity is O(n). We can use another set to track the
value set which leads to time complexity of O(1):
455 | 568
236 Word Pattern II
public boolean helper(String pattern, String str, int i, int j, HashMap<Character, String> map,
HashSet<String> set){
if(i==pattern.length() && j==str.length()){
return true;
}
if(i>=pattern.length() || j>=str.length())
return false;
char c = pattern.charAt(i);
for(int k=j+1; k<=str.length(); k++){
String sub = str.substring(j, k);
if(!map.containsKey(c) && !set.contains(sub)){
map.put(c, sub);
set.add(sub);
if(helper(pattern, str, i+1, k, map, set))
return true;
map.remove(c);
set.remove(sub);
}else if(map.containsKey(c) && map.get(c).equals(sub)){
if(helper(pattern, str, i+1, k, map, set))
return true;
}
}
return false;
}
if(s1.length()==0 || s1.equals(s2))
return true;
return false;
}
457 | 568
238 Remove Invalid Parentheses
Remove the minimum number of invalid parentheses in order to make the input string valid. Return all possible
results.
Note: The input string may contain letters other than the parentheses ( and ).
Examples: "()())()" ->["()()()", "(())()"] "(a)())()" ->["(a)()()", "(a())()"] ")(" ->[""]
return result;
}
public void dfs(String left, String right, int countLeft, int maxLeft){
if(left.length()==0){
if(countLeft==0 && right.length()!=0){
if(maxLeft > max){
max = maxLeft;
}
return;
}
if(left.charAt(0)==’(’){
dfs(left.substring(1), right+"(", countLeft+1, maxLeft+1);//keep (
dfs(left.substring(1), right, countLeft, maxLeft);//drop (
}else if(left.charAt(0)==’)’){
if(countLeft>0){
dfs(left.substring(1), right+")", countLeft-1, maxLeft);
}
458 | 568
238 Remove Invalid Parentheses
}else{
dfs(left.substring(1), right+String.valueOf(left.charAt(0)), countLeft, maxLeft);
}
}
}
while(j>=0){
if(s.charAt(i)==s.charAt(j)){
i++;
}
j--;
}
if(i==s.length())
return s;
460 | 568
239 Shortest Palindrome
} else {
if ((result = scanFromCenter(s, i - 1, i - 1)) != null)
return result;
}
}
return result;
}
return sb.append(s).toString();
}
helper(num, 0, n, result);
return result;
}
if(i==0){
for(char c=’1’; c<=’9’; c++){
num[i]=c;
helper(num, i+1, max, result);
}
}else{
num[i]=’a’;
helper(num, num.length, max, result);
462 | 568
240 Lexicographical Numbers
int result=0;
for(int i=0; i<arr.length; i++){
if(arr[i]>=’0’&&arr[i]<=’9’)
result = result*10+arr[i]-’0’;
else
break;
}
return result;
}
if(i>=a.length()){
return -1;
}
return 1;
}
});
return result;
}
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
if (n <= 0 || n < k)
return result;
return result;
}
464 | 568
242 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"].
return result;
}
Time complexity is O(kn̂), where k is the biggest number of letters a digit can map (k=4) and n is the length of
the digit string.
465 | 568
242 Letter Combinations of a Phone Number
l.add("");
l.clear();
l.addAll(temp);
}
return l;
}
for(ArrayList<String> l: result){
StringBuilder sb = new StringBuilder();
for(String str: l){
sb.append(str+".");
}
sb.setLength(sb.length() - 1);
finalResult.add(sb.toString());
}
return finalResult;
}
467 | 568
243 Restore IP Addresses
t.add(sub);
dfs(result, s, start+i, t);
t.remove(t.size()-1);
}
}
8 = 2 x 2 x 2;
= 2 x 4.
Write a function that takes an integer n and return all possible combinations of its factors.
Note: You may assume that n is always positive. Factors should be greater than 1 and less than n.
public void helper(int start, int product, int n, List<List<Integer>> result, List<Integer> curr){
if(start>n || product > n )
return ;
if(product==n) {
ArrayList<Integer> t = new ArrayList<Integer>(curr);
result.add(t);
return;
}
if(n%i==0){
curr.add(i);
helper(i, i*product, n, result, curr);
curr.remove(curr.size()-1);
}
}
}
469 | 568
245 Subsets
Given a set of distinct integers, S, return all possible subsets.
Note: 1) Elements in a subset must be in non-descending order. 2) The solution set must not contain duplicate
subsets.
245.1 Thoughts
Given a set S of n distinct integers, there is a relation between Sn and Sn-1. The subset of Sn-1 is the union of
subset of Sn-1 and each element in Sn-1 + one more element. Therefore, a Java solution can be quickly formalized.
Arrays.sort(S);
470 | 568
245 Subsets
single.add(S[i]);
temp.add(single);
result.addAll(temp);
}
return result;
}
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
246.1 Thoughts
Comparing this problem with Subsets can help better understand the problem.
Arrays.sort(num);
//add each single number as a set, only if current element is different with previous
472 | 568
246 Subsets II
return result;
}
Feed the method [1,2,3] the following will be result at each iteration.
[2]
[2][2,2]
[2][2,2][1,2][1,2,2][1]
Get [] finally.
Let dp[i] to be the minimum number of coins required to get the amount i.
dp[i] = 1, if i==coin
otherwise, dp[i]=min(dp[i-coin]+1, dp[i]) if dp[i-coin] is reachable.
We initially set dp[i] to be MAX_VALUE.
Arrays.fill(dp, Integer.MAX_VALUE);
dp[0]=0;
474 | 568
247 Coin Change
continue;
}
dp[i]=Math.min(dp[i-coin]+1, dp[i]);
}
}
}
if(dp[amount]==Integer.MAX_VALUE){
return -1;
}
return dp[amount];
}
Let dp[i] to be the minimum number of coins required to get the amount i.
dp[i+coin] = min(dp[i+coin], dp[i]+1) if dp[i] is reachable.
dp[i+coin] = dp[i+coin] is dp[i] is not reachable.
We initially set dp[i] to be MAX_VALUE.
Arrays.fill(dp, Integer.MAX_VALUE);
dp[0]=0;
}
}
}
if(dp[amount]==Integer.MAX_VALUE){
return -1;
}
return dp[amount];
}
if (temp == amount)
return step;
return -1;
}
248.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;
}
477 | 568
248 Palindrome Partitioning
left++;
right--;
}
return true;
}
if (s == null)
return result;
if (s.length() <= 1) {
result.add(s);
return result;
}
return result;
}
249.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.
return cut[n-1];
}
479 | 568
250 House Robber
You are a professional robber planning to rob houses along a street. Each house has a certain amount of money
stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system
connected and it will 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 alerting the police.
if(nums.length==1)
return nums[0];
return dp[nums.length-1];
}
50 1 1 50
480 | 568
250 House Robber
int even = 0;
int odd = 0;
mem[0] = 0;
if(mem[size]!=-1){
return mem[size];
}
//two cases
int firstSelected = helper(size-2, mem, nums) + nums[nums.length -size];
int firstUnselected = helper(size-1, mem, nums);
251.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.
if(nums.length==1)
return nums[0];
return dp[j];
}
482 | 568
252 House Robber III
The houses form a binary tree. If the root is robbed, its left and right can not be robbed.
252.1 Analysis
Traverse down the tree recursively. We can use an array to keep 2 values: the maximum money when a root is
selected and the maximum value when a root if NOT selected.
return result;
}
483 | 568
253 Jump Game
Given an array of non-negative integers, you are initially positioned at the first index of the array. Each element
in the array represents your maximum jump length at that position. Determine if you are able to reach the last
index. For example: A = [2,3,1,1,4], return true. A = [3,2,1,0,4], return false.
253.1 Analysis
We can track the maximum index that can be reached. The key to solve this problem is to find: 1) when the
current position can not reach next position (return false) , and 2) when the maximum index can reach the end
(return true).
The largest index that can be reached is: i + A[i].
int max = A[0]; //max stands for the largest index that can be reached.
//update max
if(i + A[i] > max){
max = i + A[i];
}
484 | 568
253 Jump Game
return true;
}
return false;
}
254.1 Analysis
This is an extension of Jump Game.
The solution is similar, but we also track the maximum steps of last jump.
int lastReach = 0;
int reach = 0;
int step = 0;
return step;
}
486 | 568
255 Best Time to Buy and Sell Stock
Say you have an array for which the ith element is the price of a given stock on day i.
If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock),
design an algorithm to find the maximum profit.
return result;
}
487 | 568
256 Best Time to Buy and Sell Stock II
Say you have an array for which the ith element is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy
one and sell one share of the stock multiple times). However, you may not engage in multiple transactions at the
same time (ie, you must sell the stock before you buy again).
256.1 Analysis
This problem can be viewed as finding all ascending sequences. For example, given 5, 1, 2, 3, 4, buy at 1 & sell at
4 is the same as buy at 1 &sell at 2 & buy at 2& sell at 3 & buy at 3 & sell at 4.
We can scan the array once, and find all pairs of elements that are in ascending order.
488 | 568
257 Best Time to Buy and Sell Stock III
Say you have an array for which the ith element is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete at most two transactions.
Note: A transaction is a buy & a sell. You may not engage in multiple transactions at the same time (ie, you
must sell the stock before you buy again).
257.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]
int profit = 0;
for (int i = 0; i < prices.length; i++) {
profit = Math.max(profit, left[i] + right[i]);
489 | 568
257 Best Time to Buy and Sell Stock III
return profit;
}
258.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).
258.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:
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.
491 | 568
258 Best Time to Buy and Sell Stock IV
return global[k];
}
-2 (K) -3 3
-5 -10 1
10 30 -5 (P)
//init dp table
int[][] h = new int[m][n];
//calculate dp table
for (int i = m - 2; i >= 0; i--) {
for (int j = n - 2; j >= 0; j--) {
int down = Math.max(h[i + 1][j] - dungeon[i][j], 1);
int right = Math.max(h[i][j + 1] - dungeon[i][j], 1);
h[i][j] = Math.min(right, down);
}
}
return h[0][0];
}
493 | 568
260 Decode Ways
A message containing letters from A-Z is being encoded to numbers using the following mapping:
’A’ ->1 ’B’ ->2 ... ’Z’ ->26
Given an encoded message containing digits, determine the total number of ways to decode it.
return dp[s.length()-1];
}
494 | 568
261 Perfect Squares
Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which
sum to n.
For example, given n = 12, return 3 because 12 = 4 + 4 + 4; given n = 13, return 2 because 13 = 4 + 9.
return dp[n];
}
495 | 568
262 Word Break
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".
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 dictionary
• Initial state t[0] == true
496 | 568
262 Word Break
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()];
}
}
Arrays.fill(pos, -1);
pos[0]=0;
return pos[s.length()]!=-1;
}
499 | 568
263 Word Break II
for(String word:dict){
int len = word.length();
int end = i+len;
if(end > s.length())
continue;
if(s.substring(i,end).equals(word)){
if(dp[end] == null){
dp[end] = new ArrayList<String>();
}
dp[end].add(word);
}
}
}
return result;
}
result.add(path);
return;
}
}
}
}
}
if(pos[s.length()]==null){
return new ArrayList<String>();
}else{
ArrayList<String> result = new ArrayList<String>();
dfs(pos, result, "", s.length());
return result;
}
}
public void dfs(ArrayList<String> [] pos, ArrayList<String> result, String curr, int i){
if(i==0){
result.add(curr.trim());
return;
}
for(String s: pos[i]){
String combined = s + " "+ curr;
dfs(pos, result, combined, i-s.length());
}
}
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".
while(start<S.length()){
int j=0;
if(S.charAt(i)==T.charAt(j)){
j++;
}
if(j==T.length()){
if(result.equals("")||(i-start+1)<result.length()){
result = S.substring(start, i+1);
}
start=start+1;
break;
}
if(i==S.length()-1){
return result;
}
}
}
return result;
}
502 | 568
265 Maximal Square
Given a 2D binary matrix filled with 0’s and 1’s, find the largest square containing all 1’s and return its area.
For example, given the following matrix:
1101
1101
1111
Return 4.
265.1 Analysis
This problem can be solved by dynamic programming. The changing condition is: t[i][j] = min(t[i][j-1], t[i-1][j],
t[i-1][j-1]) + 1. It means the square formed before this point.
int result=0;
int[][] dp = new int[matrix.length][matrix[0].length];
503 | 568
265 Maximal Square
return result*result;
}
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;
505 | 568
266 Minimum Path Sum
return dp[m-1][n-1];
}
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;
}
507 | 568
267 Unique Paths
//top row
for(int j=0; j<n; j++){
dp[0][j] = 1;
}
return dp[m-1][n-1];
}
if(mem[m][n]!=-1){
return mem[m][n];
}
return mem[m][n];
}
[
[0,0,0],
[0,1,0],
[0,0,0]
]
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){
dp[0][i] = 0;
}else{
dp[0][i] = dp[0][i-1];
}
}
509 | 568
268 Unique Paths II
}
}
return dp[m-1][n-1];
}
int m = costs.length-1;
return Math.min(Math.min(costs[m][0], costs[m][1]), costs[m][2]);
}
Or a different way of writing the code without original array value changed.
511 | 568
269 Paint House
return result;
}
int preMin=0;
int preSecond=0;
int preIndex=-1;
if(currMin>costs[i][j]){
currSecond = currMin;
currMin=costs[i][j];
currIndex = j;
} else if(currSecond>costs[i][j] ){
currSecond = costs[i][j];
}
}
preMin=currMin;
preSecond=currSecond;
preIndex =currIndex;
}
513 | 568
270 Paint House II
}
return result;
}
515 | 568
271 Edit Distance in Java
return dp[len1][len2];
}
Arrays.fill(arr, -1);
}
return calDistance(word1, word2, mem, m-1, n-1);
}
private int calDistance(String word1, String word2, int[][] mem, int i, int j){
if(i<0){
return j+1;
}else if(j<0){
return i+1;
}
if(mem[i][j]!=-1){
return mem[i][j];
}
if(word1.charAt(i)==word2.charAt(j)){
mem[i][j]=calDistance(word1, word2, mem, i-1, j-1);
}else{
int prevMin = Math.min(calDistance(word1, word2, mem, i, j-1), calDistance(word1, word2, mem, i-1,
j));
prevMin = Math.min(prevMin, calDistance(word1, word2, mem, i-1, j-1));
mem[i][j]=1+prevMin;
}
return mem[i][j];
}
272.1 Analysis
The problem itself is very difficult to understand. It can be stated like this: Give a sequence S and T, how many
distinct sub sequences from S equals to T? How do you define "distinct" subsequence? Clearly, the ’distinct’ here
mean different operation combination, not the final string of subsequence. Otherwise, the result is always 0 or 1.
– from Jason’s comment
When you see string problem that is about subsequence or matching, dynamic programming method should
come to mind naturally. The key is to find the initial and changing condition.
return table[S.length()][T.length()];
}
518 | 568
272 Distinct Subsequences Total
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()];
}
if(j-i+1>maxLen){
maxLen = j-i+1;
longest = s.substring(i, j+1);
}
}
}
}
return longest;
}
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
520 | 568
273 Longest Palindromic Substring
From the table, we can clearly see that the longest string is in cell table[1][5].
if (s.length() == 1) {
return s;
}
return longest;
}
274.1 Analysis
522 | 568
274 Longest Common Subsequence
return dp[m][n];
}
275.1 Analysis
Given two strings a and b, let dp[i][j] be the length of the common substring ending at a[i] and b[j].
The dp table looks like the following given a="abc" and b="abcd".
524 | 568
275 Longest Common Substring
int m = a.length();
int n = b.length();
int max = 0;
}
}
return max;
}
This is a similar problem like longest common subsequence. The difference of the solution is that for this
problem when a[i]!=b[j], dp[i][j] are all zeros by default. However, in the longest common subsequence problem,
dp[i][j] values are carried from the previous values, i.e., dp[i-1][j] and dp[i][j-1].
276.1 Analysis
The key to solve this problem is using a double linked list which enables us to quickly move nodes.
The LRU cache is a hash table of keys and double linked nodes. The hash table makes the time of get() to be
O(1). The list of double linked nodes make the nodes adding/removal operations O(1).
class Node{
int key;
int value;
Node prev;
Node next;
By analyzing the get and put, we can summarize there are 3 basic operations: 1) remove(Node t), 2) set-
Head(Node t), and 3) HashMap put()/remove(). We only need to define the first two operations.
526 | 568
276 LRU Cache
class LRUCache {
HashMap<Integer, Node> map = null;
int cap;
Node head = null;
Node tail = null;
Node t = map.get(key);
remove(t);
setHead(t);
return t.value;
}
remove(t);
setHead(t);
}else{
if(map.size()>=cap){
map.remove(tail.key);
remove(tail);
}
//remove a node
private void remove(Node t){
if(t.prev!=null){
t.prev.next = t.next;
}else{
head = t.next;
}
if(t.next!=null){
t.next.prev = t.prev;
}else{
tail = t.prev;
}
}
t.next = head;
t.prev = null;
head = t;
if(tail==null){
tail = head;
}
}
}
class RandomizedSet {
HashMap<Integer, Integer> valueMap;
HashMap<Integer, Integer> idxMap;
/** Inserts a value to the set. Returns true if the set did not already contain the specified
element. */
public boolean insert(int val) {
if(valueMap.containsKey(val)){
return false;
}
valueMap.put(val, valueMap.size());
idxMap.put(idxMap.size(), val);
return true;
}
/** Removes a value from the set. Returns true if the set contained the specified element. */
public boolean remove(int val) {
if(valueMap.containsKey(val)){
int idx = valueMap.get(val);
valueMap.remove(val);
idxMap.remove(idx);
return true;
}
return false;
529 | 568
277 Insert Delete GetRandom O(1)
if(valueMap.size()==1){
return idxMap.get(0);
}
return idxMap.get(idx);
}
}
/** Inserts a value to the collection. Returns true if the collection did not already contain the
specified element. */
public boolean insert(int val) {
//add to map2
int size2 = map2.size();
map2.put(size2+1, val);
if(map1.containsKey(val)){
map1.get(val).add(size2+1);
return false;
}else{
HashSet<Integer> set = new HashSet<Integer>();
set.add(size2+1);
map1.put(val, set);
return true;
}
}
531 | 568
278 Insert Delete GetRandom O(1) Duplicates allowed
/** Removes a value from the collection. Returns true if the collection contained the specified
element. */
public boolean remove(int val) {
if(map1.containsKey(val)){
HashSet<Integer> set = map1.get(val);
int toRemove = set.iterator().next();
if(set.size()==0){
map1.remove(val);
}
if(toRemove == map2.size()){
map2.remove(toRemove);
return true;
}
map2.remove(size2);
map2.remove(toRemove);
map2.put(toRemove, key);
return true;
}
return false;
}
if(map2.size()==1){
return map2.get(1);
}
279.1 Analysis
At first, a hash map seems to be good for insertion and deletion. But how to make getMostFrequent O(1)? Regular
sorting algorithm takes nlogn, so we can not use that. As a result we can use a linked list to track the maximum
frequency.
import java.util.*;
class Node {
int value;
Node prev;
Node next;
HashSet<Integer> set;
/**
* Inserts a value to the collection.
*/
public void insert(int val) {
if(map.containsKey(val)){
Node n = map.get(val);
n.set.remove(val);
533 | 568
279 Design a Data Structure with Insert, Delete and GetMostFrequent of O(1)
if(n.next!=null){
n.next.set.add(val); // next + 1
map.put(val, n.next);
}else{
Node t = new Node(n.value+1);
t.set.add(val);
n.next = t;
t.prev = n;
map.put(val, t);
}
//update head
if(head.next!=null)
head = head.next;
}else{
if(tail==null||head==null){
Node n = new Node(1);
n.set.add(val);
map.put(val, n);
head = n;
tail = n;
return;
}
if(tail.value>1){
Node n = new Node(1);
n.set.add(val);
map.put(val, n);
tail.prev = n;
n.next = tail;
tail = n;
}else{
tail.set.add(val);
map.put(val, tail);
}
/**
* Removes a value from the collection.
*/
public void remove(int val) {
Node n = map.get(val);
n.set.remove(val);
if(n.value==1){
map.remove(val);
}else{
n.prev.set.add(val);
map.put(val, n.prev);
}
System.out.println(fc.getMostFrequent());
fc.remove(2);
fc.remove(2);
System.out.println(fc.getMostFrequent());
}
}
In the implementation above, we only add nodes to the list. We can also delete nodes that does not hold any
elements.
int e = queue.poll();
set.add(e);
return e;
}
536 | 568
281 Design Twitter
Design a simplified version of Twitter where users can post tweets, follow/unfollow another user and is able to
see the 10 most recent tweets in the user’s news feed. Your design should support the following methods:
postTweet(userId, tweetId): Compose a new tweet. getNewsFeed(userId): Retrieve the 10 most recent tweet ids
in the user’s news feed. Each item in the news feed must be posted by users who the user followed or by the
user herself. Tweets must be ordered from most recent to least recent. follow(followerId, followeeId): Follower
follows a followee. unfollow(followerId, followeeId): Follower unfollows a followee.
class Wrapper{
ArrayList<Integer> list;
int index;
/** Retrieve the 10 most recent tweet ids in the user’s news feed. Each item in the news feed must be
posted by users who the user followed or by the user herself. Tweets must be ordered from most
recent to least recent. */
public List<Integer> getNewsFeed(int userId) {
537 | 568
281 Design Twitter
top.index--;
if(top.index>=0)
queue.offer(top);
}
return result;
}
set.remove(followeeId);
}
}
540 | 568
283 Single Number II
283.1 Problem
Given an array of integers, every element appears three times except for one. Find that single one.
541 | 568
284 Twitter Codility Problem Max Binary Gap
Problem: Get maximum binary Gap.
For example, 9’s binary form is 1001, the gap is 2.
while (N > 0) {
// get right most bit & shift right
r = N & 1;
N = N >> 1;
if (1 == r) {
max = count > max ? count : max;
count = 0;
}
}
return max;
}
Time is O(n).
while (N > 0) {
int k = N & -N;
N = N & (N - 1);
542 | 568
284 Twitter Codility Problem Max Binary Gap
}
pre = curr;
}
return len;
}
Time is O(log(n)).
285.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 func-
tion should return 3.
544 | 568
286 Reverse Bits
286.1 Problem
Reverse bits of a given 32 bits unsigned integer.
For example, given input 43261596 (represented in binary as 00000010100101000001111010011100), return 964176192
(represented in binary as 00111001011110000010100101000000).
Follow up: If this function is called many times, how would you optimize it?
Related problem: Reverse Integer
return n;
}
if ((a ^ b) != 0) {
return n ^= (1 << i) | (1 << j);
}
return n;
}
545 | 568
287 Repeated DNA Sequences
287.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"].
int hash=0;
int mask = (1<<20) -1;
if(i>=9){
hash&=mask;
if(temp.contains(hash) && !added.contains(hash)){
result.add(s.substring(i-9, i+1));
added.add(hash);
}
temp.add(hash);
}
}
return result;
546 | 568
287 Repeated DNA Sequences
288.1 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. 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
548 | 568
289 Sum of Two Integers
Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -.
Example: Given a = 1 and b = 2, return 3.
while(b!=0){
int c = a&b;
a=a^b;
b=c<<1;
}
return a;
}
549 | 568
290 Counting Bits
Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the number
of 1’s in their binary representation and return them as an array.
Example:
For num = 5 you should return [0,1,1,2,1,2].
return result;
}
while(num!=0){
if(num%2==1){
result++;
}
num = num/2;
}
return result;
}
550 | 568
290 Counting Bits
return result;
}
int result = 0;
return result;
}
552 | 568
292 Gray Code
The gray code is a binary numeral system where two successive values differ in only one bit.
Given a non-negative integer n representing the total number of bits in the code, print the sequence of gray
code. A gray code sequence must begin with 0.
For example, given n = 2, return [0,1,3,2]. Its gray code sequence is:
00 - 0
01 - 1
11 - 3
10 - 2
return result;
}
553 | 568
293 UTF8 Validation
A character in UTF8 can be from 1 to 4 bytes long, subjected to the following rules:
For 1-byte character, the first bit is a 0, followed by its unicode code. For n-bytes character, the first n-bits are all
one’s, the n+1 bit is 0, followed by n-1 bytes with most significant 2 bits being 10. This is how the UTF-8 encoding
would work:
Given an array of integers representing the data, return whether it is a valid utf-8 encoding.
i++;
}
return count==0;
}
554 | 568
294 Course Schedule
There are a total of n courses you have to take, labeled from 0 to n - 1. Some courses may have prerequisites,
for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]. Given the total
number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?
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.
294.1 Analysis
This problem can be converted to finding if a graph contains a cycle.
while(!queue.isEmpty()){
int top = queue.remove();
for(int i=0; i<len; i++){
// if a course’s prerequisite can be satisfied by a course in queue
555 | 568
294 Course Schedule
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;
}
}
visit[i]=1;
return true;
}
295.1 Analysis
If we use the BFS solution of Course Schedule, a valid sequence can easily be recorded.
//initialize result
int[] result = new int[numCourses];
int j=0;
while(!queue.isEmpty()){
int c = queue.remove();
result[j++]=c;
558 | 568
295 Course Schedule II
}
}
//return result
if(numNoPre==numCourses){
return result;
}else{
return new int[0];
}
}
0
|
1
/ \
2 3
return [1]
560 | 568
296 Minimum Height Trees
if(leaves.size()==0){
return result;
}
while(n>2){
n = n-leaves.size();
for(int l: leaves){
int neighbor = graph.get(l).iterator().next();
graph.get(neighbor).remove(l);
if(graph.get(neighbor).size()==1){
newLeaves.add(neighbor);
}
}
leaves = newLeaves;
}
return leaves;
}
297.1 Analysis
This problem can be converted to finding the cycle from a graph. It can be solved by using DFS (Recursion) or
BFS (Queue).
for(boolean b: visited){
if(!b)
return false;
}
return true;
}
visited[curr] = true;
for(int i: map.get(curr)){
if(i!=parent && !helper(i, curr, map, visited)){
return false;
}
}
562 | 568
297 Graph Valid Tree
return true;
}
list.get(a).add(b);
list.get(b).add(a);
}
while(!q.isEmpty()){
int head = q.poll();
if(visited.contains(head)){
return false;
}
visited.add(head);
if(visited.size()<n){
return false;
}
return true;
}
/**
* Definition for undirected graph.
* class UndirectedGraphNode {
* int label;
564 | 568
298 Clone Graph
* ArrayList<UndirectedGraphNode> neighbors;
* UndirectedGraphNode(int x) { label = x; neighbors = new ArrayList<UndirectedGraphNode>(); }
* };
*/
public class Solution {
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
if(node == null)
return null;
queue.add(node);
map.put(node, newHead);
while(!queue.isEmpty()){
UndirectedGraphNode curr = queue.pop();
ArrayList<UndirectedGraphNode> currNeighbors = curr.neighbors;
}
return newHead;
}
}
queue.offer(node);
while(!queue.isEmpty()){
UndirectedGraphNode top = queue.poll();
map.put(top, new UndirectedGraphNode(top.label));
for(UndirectedGraphNode n: top.neighbors){
if(!map.containsKey(n))
queue.offer(n);
}
}
queue.offer(node);
HashSet<UndirectedGraphNode> set = new HashSet<UndirectedGraphNode>();
set.add(node);
while(!queue.isEmpty()){
UndirectedGraphNode top = queue.poll();
for(UndirectedGraphNode n: top.neighbors){
if(!set.contains(n)){
queue.offer(n);
set.add(n);
}
map.get(top).neighbors.add(map.get(n));
}
}
return map.get(node);
}
299.1 Analysis
This is an application of Hierholzer’s algorithm to find a Eulerian path.
PriorityQueue should be used instead of TreeSet, because there are duplicate entries.
dfs("JFK");
return result;
}
result.addFirst(s);
}
}
567 | 568
300 Pow(x, n)
Problem:
Implement pow(x, n).
This is a great example to illustrate how to solve a problem during a technical interview. The first and second
solution exceeds time limit; the third and fourth are accepted.
if(n<0){
return 1/helper(x, -n);
}
if(n%2==0){
return v*v;
}else{
return v*v*x;
}
}
568 | 568