Coding Interview in Java
Coding Interview in Java
2
Remove Duplicates from Sorted Array
16
30 3Sum
31 4Sum
58
60
32 3Sum Closest 62
3 Remove Element 18
33 Wiggle Sort 63
4 Move Zeroes 19
34 Wiggle Subsequence 64
5 Candy 20
35 Longest Common Prefix 65
6 Trapping Rain Water 22
36 Next Permutation 66
7 Product of Array Except Self 24
Program Creek 37 Search Insert Position 68
8 Minimum Size Subarray Sum 26
38 Median of Two Sorted Arrays 70
9 Summary Ranges 28
39 Find Minimum in Rotated Sorted Array 72
10 Missing Ranges 29
40 Find Minimum in Rotated Sorted Array II 74
11 Merge Intervals 30
41 Find First and Last Position of Element in Sorted Array 76
12 Insert Interval 31
42 Guess Number Higher or Lower 78
13 Partition Labels 34
43 First Bad Version 80
14 Find And Replace in String 36
44 Search in Rotated Sorted Array 82
15 One Edit Distance 37
45 Search in Rotated Sorted Array II 84
16 Merge Sorted Array 38
46 Longest Increasing Subsequence 85
17 Is Subsequence 40
47 Count of Smaller Numbers After Self 88
18 Backspace String Compare 41
48 Russian Doll Envelopes 91
19 Repeated String Match 43
49 HIndex 93
20 Container With Most Water 44
50 HIndex II 95
21 Reverse Vowels of a String 45
51 Valid Anagram 96
22 Valid Palindrome 46
52 Group Shifted Strings 98
23 Shortest Word Distance 47
53 Palindrome Pairs 100
24 Shortest Word Distance II 48
54 Line Reflection 102
55 Isomorphic Strings 103 85 Max Sum of Rectangle No Larger Than K 155 115 Number of Connected Components in an Undirected Graph 207
56 Two Sum 104 86 Maximum Sum of Subarray Close to K 158 116 Most Stones Removed with Same Row or Column 210
57 Maximum Size Subarray Sum Equals k 105 87 Sliding Window Maximum 160 117 Longest Increasing Path in a Matrix 213
58 Subarray Sum Equals K 107 88 Moving Average from Data Stream 162 118 Word Search 216
59 Maximum Subarray 108 89 Find Median from Data Stream 163 119 Word Search II 219
60 Maximum Product Subarray 111 90 Data Stream as Disjoint Intervals 165 120 Number of Islands 223
61 Longest Substring Without Repeating Characters 112 91 Linked List Random Node 167 121 Find a Path in a Matrix 226
62 Longest Substring with At Most K Distinct Characters 114 92 Shuffle an Array 168 122 Sudoku Solver 228
63 Substring with Concatenation of All Words 116 93 Sort List 170 123 Valid Sudoku 231
64 Minimum Window Substring 118 94 Quicksort Array in Java 172 124 Walls and Gates 233
65 Longest Substring with At Least K Repeating Characters 120 95 Kth Largest Element in an Array 175 125 Surrounded Regions 236
66 Permutation in String 122 96 Sort Colors 177 126 Set Matrix Zeroes 240
67 Longest Consecutive Sequence 124 97 Maximum Gap 178 127 Spiral Matrix 243
68 Majority Element 126 98 Group Anagrams 180 128 Spiral Matrix II 247
69 Majority Element II 128 99 Ugly Number 181 129 Rotate Image 249
70 Increasing Triplet Subsequence 129 100 Ugly Number II 182 130 Range Sum Query 2D Immutable 250
71 Find the Second Largest Number in an Array 131 101 Super Ugly Number 183 131 Shortest Distance from All Buildings 253
72 Word Ladder 132 102 Find K Pairs with Smallest Sums 184 132 Best Meeting Point 255
73 Word Ladder II 134 103 Rotate Array in Java 185 133 Game of Life 256
74 Top K Frequent Elements 136 104 Reverse Words in a String II 188 134 TicTacToe 258
75 Meeting Rooms II 139 105 Missing Number 189 135 Sparse Matrix Multiplication 261
76 Meeting Rooms 141 106 Find the Duplicate Number 190 136 Add Two Numbers 263
77 Range Addition 142 107 First Missing Positive 192 137 Reorder List 265
78 Merge K Sorted Arrays in Java 144 108 Queue Reconstruction by Height 194 138 Linked List Cycle 269
79 Merge k Sorted Lists 146 109 Binary Watch 195 139 Copy List with Random Pointer 270
80 Rearrange String k Distance Apart 147 110 Search a 2D Matrix 198 140 Merge Two Sorted Lists 272
81 Minimum Cost to Hire K Workers 149 111 Search a 2D Matrix II 199 141 Odd Even Linked List 274
82 Contains Duplicate 151 112 Kth Smallest Element in a Sorted Matrix 201 142 Remove Duplicates from Sorted List 276
83 Contains Duplicate II 152 113 Design Snake Game 203 143 Remove Duplicates from Sorted List II 278
84 Contains Duplicate III 153 114 Number of Islands II 205 144 Partition List 279
145 Intersection of Two Linked Lists 280 175 Balanced Binary Tree 337 205 Implement a Stack Using an Array in Java 399
146 Remove Linked List Elements 282 176 Symmetric Tree 339 206 Implement a Queue using an Array in Java 401
147 Swap Nodes in Pairs 283 177 Binary Search Tree Iterator 340 207 Evaluate Reverse Polish Notation 403
148 Reverse Linked List 285 178 Binary Tree Right Side View 342 208 Valid Parentheses 406
149 Reverse Linked List II 287 179 Lowest Common Ancestor of a Binary Search Tree 344 209 Longest Valid Parentheses 407
150 Reverse Double Linked List 289 180 Lowest Common Ancestor of a Binary Tree 345 210 Min Stack 408
151 Remove Nth Node From End of List 291 181 Most Frequent Subtree Sum 347 211 Max Chunks To Make Sorted 410
152 Palindrome Linked List 293 182 Verify Preorder Serialization of a Binary Tree 349 212 Maximal Rectangle 411
153 Delete Node in a Linked List 296 183 Populating Next Right Pointers in Each Node 351 213 Mini Parser 413
154 Reverse Nodes in kGroup 297 184 Populating Next Right Pointers in Each Node II 354 214 Flatten Nested List Iterator 415
155 Plus One Linked List 300 185 Unique Binary Search Trees 356 215 Nested List Weight Sum 417
156 Binary Tree Preorder Traversal 302 186 Unique Binary Search Trees II 358 216 Nested List Weight Sum II 419
157 Binary Tree Inorder Traversal 303 187 Sum Root to Leaf Numbers 360 217 Decode String 421
158 Binary Tree Postorder Traversal 305 188 Count Complete Tree Nodes 362 218 Evaluate math expression with plus, minus and parentheses 423
159 Binary Tree Level Order Traversal 308 189 Closest Binary Search Tree Value 365 219 Partition to K Equal Sum Subsets 425
160 Binary Tree Level Order Traversal II 310 190 Binary Tree Paths 367 220 Permutations 427
161 Binary Tree Vertical Order Traversal 312 191 Maximum Depth of Binary Tree 369 221 Permutations II 430
162 Invert Binary Tree 314 192 Recover Binary Search Tree 370 222 Permutation Sequence 432
163 Kth Smallest Element in a BST 315 193 Same Tree 371 223 Number of Squareful Arrays 434
164 Binary Tree Longest Consecutive Sequence 317 194 Serialize and Deserialize Binary Tree 372 224 Generate Parentheses 437
165 Validate Binary Search Tree 319 195 Inorder Successor in BST 375 225 Combination Sum 439
166 Flatten Binary Tree to Linked List 321 196 Inorder Successor in BST II 376 226 Combination Sum II 441
167 Path Sum 323 197 Find Leaves of Binary Tree 378 227 Combination Sum III 442
168 Path Sum II 325 198 Largest BST Subtree 380 228 Combination Sum IV 443
169 Construct Binary Tree from Inorder and Postorder Traversal 327 199 Implement Trie (Prefix Tree) 382 229 Wildcard Matching 444
170 Construct Binary Tree from Preorder and Inorder Traversal 329 200 Add and Search Word Data structure design 386 230 Regular Expression Matching 445
171 Convert Sorted Array to Binary Search Tree 331 201 Range Sum Query Mutable 390 231 Expressive Words 448
172 Convert Sorted List to Binary Search Tree 332 202 The Skyline Problem 394 232 Get Target Number Using Number List and Arithmetic Operations 450
173 Minimum Depth of Binary Tree 334 203 Implement Stack using Queues 396 233 Flip Game 452
174 Binary Tree Maximum Path Sum 336 204 Implement Queue using Stacks 398 234 Flip Game II 453
235 Word Pattern 454 265 Maximal Square 503 295 Course Schedule II 558
236 Word Pattern II 455 266 Minimum Path Sum 505 296 Minimum Height Trees 560
237 Scramble String 457 267 Unique Paths 507 297 Graph Valid Tree 562
238 Remove Invalid Parentheses 458 268 Unique Paths II 509 298 Clone Graph 564
239 Shortest Palindrome 460 269 Paint House 511 299 Reconstruct Itinerary 567
240 Lexicographical Numbers 462 270 Paint House II 513 300 Pow(x, n) 568
242 Letter Combinations of a Phone Number 465 272 Distinct Subsequences Total 518
247 Coin Change 474 277 Insert Delete GetRandom O(1) 529
248 Palindrome Partitioning 477 278 Insert Delete GetRandom O(1) Duplicates allowed 531
249 Palindrome Partitioning II 479 279 Design a Data Structure with Insert, Delete and GetMostFrequent of O(1) 533
254 Jump Game II 486 284 Twitter Codility Problem Max Binary Gap 542
255 Best Time to Buy and Sell Stock 487 285 Number of 1 Bits 544
256 Best Time to Buy and Sell Stock II 488 286 Reverse Bits 545
257 Best Time to Buy and Sell Stock III 489 287 Repeated DNA Sequences 546
258 Best Time to Buy and Sell Stock IV 491 288 Bitwise AND of Numbers Range 548
261 Perfect Squares 495 291 Maximum Product of Word Lengths 552
Every title in the PDF is linked back to the original blog. When it is clicked, it opens the original post in your 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,
browser. If you want to discuss any problem, please go to the post and leave your comment there. the array is changed to 1, 2, 3, 3, 3.
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 Remove Duplicates from Sorted Array
Given a sorted array, remove the duplicates in place such that each element appear only once and return the new
length. Do not allocate extra space for another array, you must do this in place with constant memory.
For example, given input array A = [1,1,2], your function should return length = 2, and A is now [1,2].
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;
}
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.
*/
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;
}
return result;
}
}else{
left[i]=height[i];
max = height[i];
}
}
6 Trapping Rain Water 7 Product of Array Except Self
//scan from right to left
max = height[height.length-1];
Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how right[height.length-1]=height[height.length-1]; Given an array of n integers where n >1, nums, return an array output such that output[i] is equal to the product
much water it is able to trap after raining. for(int i=height.length-2; i>=0; i--){ of all the elements of nums except nums[i].
For example, given [0,1,0,2,1,0,1,3,2,1,2,1], return 6. if(height[i]<max){ Solve it without division and in O(n).
right[i]=max; For example, given [1,2,3,4], return [24,12,8,6].
}else{
6.1 Analysis right[i]=height[i];
max = height[i]; 7.1 Java Solution 1
This problem is similar to Candy. It can be solve by scanning from both sides and then get the total. }
}
public int[] productExceptSelf(int[] nums) {
6.2 Java Solution //calculate totoal int[] result = new int[nums.length];
for(int i=0; i<height.length; i++){
result+= Math.min(left[i],right[i])-height[i]; int[] t1 = new int[nums.length];
} int[] t2 = new int[nums.length];
//multiply
for(int i=0; i<nums.length; i++){
result[i] = t1[i] * t2[i];
}
return result;
}
public int trap(int[] height) {
int result = 0;
}
int left=1;
for(int i=0; i<nums.length; i++){ Similarly, we can also write it in a more readable way.
result[i]=result[i]*left;
left = left*nums[i]; public int minSubArrayLen(int s, int[] nums) {
} 8 Minimum Size Subarray Sum if(nums==null||nums.length==0)
return 0;
return result;
} Given an array of n positive integers and a positive integer s, find the minimal length of a subarray of which the int i=0;
sum ≥ s. If there isn’t one, return 0 instead. int j=0;
For example, given the array [2,3,1,2,4,3] and s = 7, the subarray [4,3] has the minimal length of 2 under the int sum=0;
problem constraint.
int minLen = Integer.MAX_VALUE;
}else{
if(i==nums.length)
break;
sum = sum+nums[i];
i++;
}
}
if(exists)
return result;
else
return 0;
public List<String> findMissingRanges(int[] nums, int lower, int upper) { 11.2 Java Solution
9.2 Java Solution List<String> result = new ArrayList<>();
int start = lower;
public List<Interval> merge(List<Interval> intervals) {
public List<String> summaryRanges(int[] nums) { if(lower==Integer.MAX_VALUE){ if(intervals == null || intervals.size()<=1){
List<String> result = new ArrayList<String>(); return result; return intervals;
} }
if(nums == null || nums.length==0)
return result; for(int i=0; i<nums.length; i++){ Collections.sort(intervals, Comparator.comparing((Interval itl)->itl.start));
//handle duplicates, e.g., [1,1,1] lower=1 upper=1
if(nums.length==1){ if(i<nums.length-1 && nums[i]==nums[i+1]){ List<Interval> result = new ArrayList<>();
result.add(nums[0]+""); continue; Interval t = intervals.get(0);
} }
for(int i=1; i<intervals.size(); i++){
int pre = nums[0]; // previous element if(nums[i] == start){ Interval c = intervals.get(i);
int first = pre; // first element of each range start++; if(c.start <= t.end){
}else{ t.end = Math.max(t.end, c.end);
for(int i=1; i<nums.length; i++){ result.add(getRange(start, nums[i]-1)); }else{
if(nums[i]==pre+1){ if(nums[i]==Integer.MAX_VALUE){ result.add(t);
if(i==nums.length-1){ return result; t = c;
result.add(first+"->"+nums[i]); } }
} start = nums[i]+1; }
}else{ }
if(first == pre){ } result.add(t);
result.add(first+"");
}else{ if(start<=upper){ return result;
result.add(first + "->"+pre); result.add(getRange(start, upper)); }
} }
pre = nums[i];
}
return result;
}
* }
*/ return result;
public class Solution { }
public ArrayList<Interval> insert(ArrayList<Interval> intervals, Interval newInterval) {
public int helper(List<Interval> intervals, Interval newInterval) {
12 Insert Interval ArrayList<Interval> result = new ArrayList<Interval>(); int low = 0;
int high = intervals.size() - 1;
for(Interval interval: intervals){
Problem: if(interval.end < newInterval.start){ while (low < high) {
Given a set of non-overlapping & sorted intervals, insert a new interval into the intervals (merge if necessary). result.add(interval); int mid = low + (high - low) / 2;
}else if(interval.start > newInterval.end){
Example 1: result.add(newInterval); if (newInterval.start <= intervals.get(mid).start) {
Given intervals [1,3],[6,9], insert and merge [2,5] in as [1,5],[6,9]. newInterval = interval; high = mid;
}else if(interval.end >= newInterval.start || interval.start <= newInterval.end){ } else {
Example 2: newInterval = new Interval(Math.min(interval.start, newInterval.start), low = mid + 1;
Given [1,2],[3,5],[6,7],[8,10],[12,16], insert and merge [4,9] in as [1,2],[3,10],[12,16]. Math.max(newInterval.end, interval.end)); }
} }
This is because the new interval [4,9] overlaps with [3,5],[6,7],[8,10]. }
return high == 0 ? 0 : high - 1;
result.add(newInterval); }
12.1 Java Solution 1 return result; The best time is O(log(n)) and worst case time is O(n).
}
When iterating over the list, there are three cases for the current range. }
if (intervals.size() == 0) {
result.add(newInterval);
return result;
}
int[] t = list.get(0);
for(int i=1; i<list.size(); i++){
int[] range = list.get(i);
int prev = 0;
if (prev != startIndex) {
sb.append(S.substring(prev, startIndex));
}
if(arr == null){ }
arr = new int[]{i, i};
map.put(c, arr); if (prev < S.length()) {
}else{ sb.append(S.substring(prev));
arr[1]=i; }
}
} return sb.toString();
}
ArrayList<int[]> list = new ArrayList<>();
list.addAll(map.values());
else
A[k--] = B[j--];
}
}
if(Math.abs(m-n)>1){
return false; 16.2 Java Solution 1
}
if(i<m||j<n){ The loop condition also can use m+n like the following.
count++;
public void merge(int A[], int m, int B[], int n) {
}
int i = m - 1;
int j = n - 1;
if(count==1)
int k = m + n - 1;
return true;
while (k >= 0) {
return false;
if (j < 0 || (i >= 0 && A[i] > B[j]))
}
A[k--] = A[i--];
}else{
i--;
j--;
}
}else{
17 Is Subsequence 18 Backspace String Compare if(i>=0 || j>=0){
return false;
}
Given a string s and a string t, check if s is subsequence of t. Given two strings S and T, return if they are equal when both are typed into empty text editors. # means a }
You may assume that there is only lower case English letters in both s and t. t is potentially a very long (length backspace character. }
= 500,000) string, and s is a short string (<=100). Example 1:
A subsequence of a string is a new string which is formed from the original string by deleting some (can return i<0 && j<0;
Input: S = "ab#c", T = "ad#c" }
be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ace" is a
Output: true
subsequence of "abcde" while "aec" is not).
Explanation: Both S and T become "ac".
int i=0;
int j=0; 18.1 Java Solution
while(i<s.length() && j<t.length()){
if(s.charAt(i)==t.charAt(j)){ This problem requires O(N) time and O(1) space.
i++;
public boolean backspaceCompare(String S, String T) {
}
int i = S.length()-1;
int j = T.length()-1;
j++;
while(i>=0 || j>=0){
if(i==s.length())
int c1=0;
return true;
while(i>=0 && (c1>0 || S.charAt(i)==’#’)){
}
if(S.charAt(i)==’#’){
c1++;
return false;
}else{
}
c1--;
}
i--;
}
int c2=0;
while(j>=0 && (c2>0 || T.charAt(j)==’#’)){
if(T.charAt(j)==’#’){
c2++;
}else{
c2--;
}
j--;
}
if (i == A.length()) {
while(i<j){
i = 0;
if(!vowList.contains(arr[i])){
result++;
i++;
} 20.3 Java Solution continue;
} else {
}
k++;
if (k == A.length()) { public int maxArea(int[] height) {
if (height == null || height.length < 2) { if(!vowList.contains(arr[j])){
return -1;
return 0; j--;
}
} continue;
i = k;
}
j = 0;
result = 0; int max = 0;
int left = 0; char t = arr[i];
}
int right = height.length - 1; arr[i]=arr[j];
}
arr[j]=t;
return max;
}
ArrayList<Integer> l1 = map.get(word1);
ArrayList<Integer> l2 = map.get(word2);
int i=0;
int j=0; public int shortestWordDistance(String[] words, String word1, String word2) {
while(i<l1.size() && j<l2.size()){ if(words==null||words.length==0)
result = Math.min(result, Math.abs(l1.get(i)-l2.get(j))); return -1;
if(l1.get(i)<l2.get(j)){
i++; 25 Shortest Word Distance III if(word1==null || word2==null)
}else{ return -1;
j++;
} This is a follow-up problem of Shortest Word Distance. The only difference is now word1 could be the same as boolean isSame = false;
} word2.
Given a list of words and two words word1 and word2, return the shortest distance between these two words if(word1.equals(word2))
return result; in the list. isSame = true;
} word1 and word2 may be the same and they represent two individual words in the list.
int shortest= Integer.MAX_VALUE;
For example, Assume that words = ["practice", "makes", "perfect", "coding", "makes"].
The time complexity of the shortest method is now O(M+N). Since M+N <size of word list, the time is O(K) Given word1 = “makes”, word2 = “coding”, return 1. Given word1 = "makes", word2 = "makes", return 3. int prev=-1;
where k is the list size.
int i1=-1;
int i2=-1;
25.1 Java Solution 1
for(int i=0; i<words.length; i++){
In this problem, word1 and word2 can be the same. The two variables used to track indices should take turns to if(isSame){
update. if(words[i].equals(word1)){
if(prev!=-1){
public int shortestWordDistance(String[] words, String word1, String word2) {
shortest=Math.min(shortest, i-prev);
if(words==null || words.length<1 || word1==null || word2==null)
}
return 0;
prev = i;
}
int m=-1;
}else{
int n=-1;
if(word1.equals(words[i])){
i1=i;
int min = Integer.MAX_VALUE;
if(i2!=-1){
int turn=0;
shortest = Math.min(shortest, i-i2);
if(word1.equals(word2))
}
turn = 1;
}else if(word2.equals(words[i])){
i2=i;
for(int i=0; i<words.length; i++){
if(i1!=-1){
String s = words[i];
shortest = Math.min(shortest, i-i1);
if(word1.equals(s) && (turn ==1 || turn==0)){
}
m = i;
}
if(turn==1) turn=2;
}
if(n!=-1)
}
min = Math.min(min, m-n);
}else if(word2.equals(s) && (turn==2 || turn==0)){
return shortest;
n = i;
}
if(turn==2) turn =1;
if(m!=-1)
min = Math.min(min, n-m);
}
}
return min;
}
for(int i: list){
result[k++] = i;
}
return result;
26 Intersection of Two Arrays } 27 Intersection of Two Arrays II
Given two arrays, write a function to compute their intersection. Given two arrays, write a function to compute their intersection.
26.3 Any improvement? Example: Given nums1 = [1, 2, 2, 1], nums2 = [2, 2], return [2, 2].
public int[] intersection(int[] nums1, int[] nums2) { public int[] intersect(int[] nums1, int[] nums2) {
HashSet<Integer> set1 = new HashSet<Integer>(); HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
for(int i: nums1){ for(int i: nums1){
set1.add(i); if(map.containsKey(i)){
} map.put(i, map.get(i)+1);
}else{
HashSet<Integer> set2 = new HashSet<Integer>(); map.put(i, 1);
for(int i: nums2){ }
if(set1.contains(i)){ }
set2.add(i);
} ArrayList<Integer> list = new ArrayList<Integer>();
} for(int i: nums2){
if(map.containsKey(i)){
int[] result = new int[set2.size()]; if(map.get(i)>1){
int i=0; map.put(i, map.get(i)-1);
for(int n: set2){ }else{
result[i++] = n; map.remove(i);
} }
list.add(i);
return result; }
} }
k--;
}
}
}
Problem: Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all
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 unique quadruplets in the array which gives the sum of target.
array which gives the sum of zero. Note: Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d) The solution set
Note: Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c) The solution set must not must not contain duplicate quadruplets.
contain duplicate triplets.
For example, given array S = {1 0 -1 0 -2 2}, and target = 0.
For example, given array S = {-1 0 1 2 -1 -4},
A solution set is:
A solution set is: (-1, 0, 0, 1)
(-1, 0, 1) (-2, -1, 1, 2)
(-1, -1, 2) (-2, 0, 0, 2)
while(k<l &&nums[l]==nums[l+1] ){
l--;
}
while(k<l &&nums[k]==nums[k-1]){
k++; 32 3Sum Closest 33 Wiggle Sort
}
}
Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Given an unsorted array nums, reorder it in-place such that nums[0] <nums[1] >nums[2] <nums[3].... Example:
Return the sum of the three integers. You may assume that each input would have exactly one solution.
Input: nums = [3,5,2,1,6,4]
}
For example, given array S = {-1 2 1 -4}, and target = 1. Output: One possible answer is [3,5,1,6,2,4]
}
} The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
return result;
} 33.1 Java Solution
32.1 Analysis
public void wiggleSort(int[] nums) {
This problem is similar to 2 Sum. This kind of problem can be solved by using a similar approach, i.e., two
if (nums == null || nums.length <= 1) {
pointers from both left and right.
return;
}
return result;
}
The problem is converted to finding the turning point. When nums[i] <nums[i+1], we want to keep going to the To solve this problem, we need to find the two loop conditions. One is the length of the shortest string. The other 1,2,3 [U+FFFD] 1,3,2
right until finding the largest one, which is the turning point. Similarly, when nums[i] >nums[i+1], we want to 3,2,1 [U+FFFD] 1,2,3
is iteration over every element of the string array.
keep going to the right until finding the smallest one, which is the turning point. We always want to use the 1,1,5 [U+FFFD] 1,5,1
largest or smallest as the turning point because that guarantees the optimal solution.
35.3 Java Solution
public int wiggleMaxLength(int[] nums) {
if(nums == null || nums.length==0) 36.1 Analysis
return 0; public String longestCommonPrefix(String[] strs) {
if(nums.length<2){ if(strs==null || strs.length ==0){ The steps to solve this problem: 1) scan from right to left, find the first element that is less than its previous one.
return nums.length; return "";
} } 4 5 6 3 2 1
|
int count=1; if(strs.length == 1){ p
return strs[0];
} 2) scan from right to left, find the first element that is greater than p.
for(int i=1, j=0; i<nums.length; j=i, i++){
if(nums[j]<nums[i]){ 4 5 6 3 2 1
int i=0;
count++; |
while(true){
while(i<nums.length-1 && nums[i]<=nums[i+1]){ q
boolean flag = true;
i++; for(int j=1; j<strs.length; j++){
} if(strs[j].length()<=i || strs[j-1].length() <=i 3) swap p and q
}else if(nums[j]>nums[i]){ || strs[j].charAt(i) != strs[j-1].charAt(i)){
count++; 4 5 6 3 2 1
flag = false;
while(i<nums.length-1 && nums[i]>=nums[i+1]){ swap
break;
i++; 4 6 5 3 2 1
}
} }
} 4) reverse elements [p+1, nums.length]
} if(flag){
4 6 1 2 3 5
i++;
return count; }else{
} break;
}
}
36.2 Java Solution
} }
}
if (mark == -1) {
reverse(nums, 0, nums.length - 1); return i;
return; }
} 37 Search Insert Position
int idx = nums.length-1;
for (int i = nums.length-1; i >= mark+1; i--) { Given a sorted array and a target value, return the index if the target is found. If not, return the index where it
if (nums[i] > nums[mark]) { would be if it were inserted in order. You may assume no duplicates in the array.
idx = i; Here are few examples.
break;
} [1,3,5,6], 5 -> 2
} [1,3,5,6], 2 -> 1
[1,3,5,6], 7 -> 4
swap(nums, mark, idx); [1,3,5,6], 0 -> 0
return l;
}
while(i<=j){
int mid = (i+j)/2;
j1 = m1;
i2 = m2+1;
}
38.1 Java Solution 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 can be converted to the problem of finding kth element, k is (A’s length + B’ Length)/2.
If any of the two arrays is empty, then the kth element is the non-empty array’s kth element. If k == 0, the kth 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
element is the first element of A or B. array each time.
For normal cases(all other cases), we need to move the pointer at the pace of half of the array size to get If we pick the middle element, we can compare the middle element with the leftmost (or rightmost) element. If
O(log(n)) time. 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
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
in time log(n).
int total = nums1.length+nums2.length;
In addition, in any rotated sorted array, the rightmost element should be less than the left-most element,
if(total%2==0){
otherwise, the sorted array is not rotated and we can simply pick the leftmost element as the minimum.
return (getKth(nums1, 0, nums1.length-1, nums2, 0, nums2.length-1, total/2)
+ getKth(nums1, 0, nums1.length-1, nums2, 0, nums2.length-1, total/2-1))/2.0;
}else{
return getKth(nums1,0, nums1.length-1, nums2, 0, nums2.length-1, total/2);
}
}
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); 39.2 Java Solution 1 - Recursion
j2 = m2;
i1 = m1+1; Define a helper function, otherwise, we will need to use Arrays.copyOfRange() function, which may be expensive
}else{ for large arrays.
k = k-(m2-i2+1);
/*
int middle = (right-left)/2 + left;
To understand the boundaries, use the following 3 examples:
// already sorted
[2,1], [2,3,1], [3,1,2]
if(num[right] > num[left]){
*/ return num[left];
public int findMin(int[] nums) {
//right shift one
if(nums==null || nums.length==0)
}else if(num[right] == num[left]){
return -1;
return findMin(num, left+1, right);
//go right
int i=0;
}else if(num[middle] >= num[left]){
int j=nums.length-1;
return findMin(num, middle, right);
//go left
while(i<=j){
}else{
if(nums[i]<=nums[j])
return findMin(num, left, middle);
return nums[i];
}
}
int m=(i+j)/2;
if(nums[m]>=nums[i]){
i=m+1;
}else{
40.2 Java Solution 2 - Iteration
j=m;
} public int findMin(int[] nums) {
} int i=0;
int j=nums.length-1;
return -1;
} while(i<=j){
}
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 43 First Bad Version
(high + low) >>> 1 = 0100 0000 0000 0000 0000 0000 0000 0000 = 1073741824
You are a product manager and currently leading a team to develop a new product. Unfortunately, the latest
version of your product fails the quality check. Since each version is developed based on the previous version, all
the versions after a bad version are also bad.
Suppose you have n versions [1, 2, ..., n] and you want to find out the first bad one, which causes all the
following ones to be bad.
You are given an API bool isBadVersion(version) which will return whether version is bad. Implement a
function to find the first bad version. You should minimize the number of calls to the API.
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;
return -1;
if(target == nums[mid])
44 Search in Rotated Sorted Array return mid; 45 Search in Rotated Sorted Array II
if(nums[left] <= nums[mid]){
Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 might become 4 5 if(nums[left]<=target && target<nums[mid]){ Follow up for "Search in Rotated Sorted Array": what if duplicates are allowed? Write a function to determine if
6 7 0 1 2). return binarySearch(nums,left, mid-1, target); a given target is in the array.
You are given a target value to search. If found in the array return its index, otherwise return -1. You may }else{
assume no duplicate exists in the array. return binarySearch(nums, mid+1, right, target);
} 45.1 Java Solution
}else {
44.1 Analysis if(nums[mid]<target&& target<=nums[right]){
public boolean search(int[] nums, int target) {
return binarySearch(nums,mid+1, right, target);
int left=0;
In order to use binary search on the rotated sorted array, we need to determine how to update the left and right }else{
int right=nums.length-1;
pointers. There are two major cases as shown below: return binarySearch(nums, left, mid-1, target);
}
while(left<=right){
}
int mid = (left+right)/2;
}
if(nums[mid]==target)
return true;
if(nums[left]<nums[mid]){
44.3 Java Solution 2 - Iterative
if(nums[left]<=target&& target<nums[mid]){
right=mid-1;
public int search(int[] nums, int target) { }else{
int left = 0; left=mid+1;
int right= nums.length-1; }
}else if(nums[left]>nums[mid]){
while(left<=right){ if(nums[mid]<target&&target<=nums[right]){
int mid = left + (right-left)/2; left=mid+1;
if(target==nums[mid]) }else{
return mid; right=mid-1;
}
if(nums[left]<=nums[mid]){ }else{
if(nums[left]<=target&& target<nums[mid]){ left++;
right=mid-1; }
}else{ }
left=mid+1;
} return false;
}else{ }
if(nums[mid]<target&& target<=nums[right]){
left=mid+1;
Once the two cases are identified, the problem is straightforward to solve. We only need to check if the target }else{
right=mid-1;
element is in the sorted side, and based on that move left or right pointers.
}
}
}
44.2 Java Solution 1- Recusive
return -1;
public int search(int[] nums, int target) { }
return binarySearch(nums, 0, nums.length-1, target);
}
public int binarySearch(int[] nums, int left, int right, int target){
if(left>right)
max[i]=Math.max(max[i], max[j]+1);
}
}
}
Let max[i] represent the length of the longest increasing subsequence so far. If any element before i is smaller public int lengthOfLIS(int[] nums) {
than nums[i], then max[i] = max(max[i], max[j]+1). if(nums==null || nums.length==0)
Here is an example: return 0;
This solution is simple. However, note that time complexity of adding an element to a list is O(n), because return result;
elements after the insertion position need to be shifted. So the time complexity is O(n2̂(logn)). }
return max;
} public int hIndex(int[] citations) {
Arrays.sort(citations);
int result = 0;
48.2 Java Solution 2 - Binary Search for(int i=citations.length-1; i>=0; i--){
int cnt = citations.length-i;
We can sort the envelopes by height in ascending order and width in descending order. Then look at the width if(citations[i]>=cnt){
result = cnt;
and find the longest increasing subsequence. This problem is then converted to the problem of finding Longeset
}else{
Increasing Subsequence.
break;
public int maxEnvelopes(int[][] envelopes) { }
Comparator c = Comparator.comparing((int[] arr) -> arr[0]) }
.thenComparing((int[] arr) -> arr[1], Comparator.reverseOrder());
Arrays.sort(envelopes, c); return result;
}
for(int c: citations){ Follow up for H-Index: What if the citations array is sorted in ascending order? Could you optimize your Given two strings s and t, write a function to determine if t is an anagram of s.
counter[Math.min(len,c)]++; algorithm?
}
51.1 Java Solution 1
int k=len; 50.1 Java Solution
for(int s=counter[len]; k > s; s += counter[k]){ Assuming the string contains only lowercase alphabets, here is a simple solution.
k--; Given the array is sorted, we should use binary search.
} public boolean isAnagram(String s, String t) {
int hIndex(int[] citations) { if(s==null || t==null)
return k; int len = citations.length; return false;
}
if (len == 0) { if(s.length()!=t.length())
return 0; return false;
}
int[] arr = new int[26];
if (len == 1) { for(int i=0; i<s.length(); i++){
if (citations[0] == 0) { arr[s.charAt(i)-’a’]++;
return 0; arr[t.charAt(i)-’a’]--;
} else { }
return 1;
} for(int i: arr){
} if(i!=0)
return false;
int i = 0; }
int j = len - 1;
while (i < j) { return true;
int m = i + (j - i + 1) / 2; }
if (citations[m] > len - m) {
j = m - 1;
} else {
i = m; 51.2 Java Solution 2
}
} If the inputs contain unicode characters, an array with length of 26 is not enough.
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);
}
}
}
}
}
return result;
}
53 Palindrome Pairs 54 Line Reflection
public boolean isPalindrome(String s){
int i=0;
Given a list of unique words. Find all pairs of distinct indices (i, j) in the given list, so that the concatenation of int j=s.length()-1; Given n points on a 2D plane, find if there is such a line parallel to y-axis that reflects the given points.
the two words, i.e. words[i] + words[j] is a palindrome. Example 1: Given points = [[1,1],[-1,1]], return true.
Example 1: Given words = ["bat", "tab", "cat"] Return [[0, 1], [1, 0]] The palindromes are ["battab", "tabbat"] while(i<=j){ Example 2: Given points = [[1,1],[-1,-1]], return false.
if(s.charAt(i)!=s.charAt(j)){ Follow up: Could you do better than O(n2)?
return false;
53.1 Java Solution }
i++; 54.1 Java Solution
j--;
public List<List<Integer>> palindromePairs(String[] words) { } For this problem, we first find the smallest and largest x-value for all points and get the line’s x-axis is (minX +
List<List<Integer>> result = new ArrayList<>();
maxX) / 2, then for each point, check if each point has a reflection points in the set.
if(words == null || words.length < 2){ return true;
return result; } public boolean isReflected(int[][] points) {
} if(points==null || points.length<2)
Time complexity is O(n*k2̂), where n is the number of words and k is the average length of each word. return true;
HashMap<String, Integer> map = new HashMap<>();
for(int i=0; i<words.length; i++){ HashMap<Integer, HashSet<Integer>> map = new HashMap<Integer, HashSet<Integer>>();
map.put(words[i], i);
} int min=Integer.MAX_VALUE;
int max=Integer.MIN_VALUE;
for(int i=0; i<words.length; i++){
String s = words[i]; for(int[] arr: points){
min = Math.min(min, arr[0]);
for(int k=0; k<=s.length(); k++){ max = Math.max(max, arr[0]);
String left = s.substring(0, k); HashSet<Integer> set = map.get(arr[0]);
String right= s.substring(k); if(set==null){
set = new HashSet<Integer>();
//if left part is palindrome, find reversed right part map.put(arr[0], set);
if(isPalindrome(left)){ }
String reversedRight = new StringBuilder(right).reverse().toString();
if(map.containsKey(reversedRight) && map.get(reversedRight) != i){ set.add(arr[1]);
ArrayList<Integer> l = new ArrayList<>();
l.add(map.get(reversedRight)); }
l.add(i);
result.add(l); int y = min+max;
}
} for(int[] arr: points){
int left = arr[0];
//if right part is a palindrome, find reversed left part int right = y-left;
if(isPalindrome(right)){ if(map.get(right)==null || !map.get(right).contains(arr[1])){
String reversedLeft = new StringBuilder(left).reverse().toString(); return false;
if(map.containsKey(reversedLeft) }
&& map.get(reversedLeft) != i }
&& right.length() != 0){
//make sure right is not "", already handled in the if above return true;
ArrayList<Integer> l = new ArrayList<>(); }
l.add(i);
l.add(map.get(reversedLeft));
result.add(l);
}
}
map1.put(c1, c2);
map2.put(c2, c1);
}
}
return true;
public int maxSubArrayLen(int[] nums, int k) {
}
HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
Time complexity is O(n) and space complexity is O(n), where n is the length of the input string. int max = 0;
int sum=0;
for(int i=0; i<nums.length; i++){
sum += nums[i];
if(sum==k){
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;
}
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."
return result;
}
Time is O(n).
int sum = 0;
Program Creek 109 | 568 Program Creek 110 | 568 111 | 568
61 Longest Substring Without Repeating Characters
result = Math.max(arr.length - start, result); Now if this question is extended to be "the longest substring that contains k unique characters", what should
we do?
return result;
count++;
Program Creek 115 | 568 116 | 568 Program Creek 117 | 568
64 Minimum Window Substring
}
}
}
return result;
64 Minimum Window Substring } 65 Longest Substring with At Least K Repeating
Given a string S and a string T, find the minimum window in S which will contain all the characters in T in
Characters
complexity O(n).
For example, S = "ADOBECODEBANC", T = "ABC", Minimum window is "BANC". Find the length of the longest substring T of a given string (consists of lowercase letters only) such that every
character in T appears no less than k times.
Example 1:
64.1 Java Solution
Input:
s = "aaabb", k = 3
public String minWindow(String s, String t) {
HashMap<Character, Integer> goal = new HashMap<>(); Output:
int goalSize = t.length(); 3
int minLen = Integer.MAX_VALUE; The longest substring is "aaa", as ’a’ is repeated 3 times.
String result = "";
//target dictionary
for(int k=0; k<t.length(); k++){
65.1 Java Solution
goal.put(t.charAt(k), goal.getOrDefault(t.charAt(k), 0)+1);
}
This problem can be solved using DFS. When all chars in the input string occurs >=k, return the length. But we
first need to split the input string by using the characters whose occurrence <k.
int i=0;
int total=0; public int longestSubstring(String s, int k) {
HashMap<Character, Integer> map = new HashMap<>(); HashMap<Character, Integer> counter = new HashMap<Character, Integer>();
for(int j=0; j<s.length(); j++){
char c = s.charAt(j); for(int i=0; i<s.length(); i++){
if(!goal.containsKey(c)){
continue; char c = s.charAt(i);
} if(counter.containsKey(c)){
counter.put(c, counter.get(c)+1);
//if c is a target character in the goal, and count is < goal, increase the total }else{
int count = map.getOrDefault(c, 0); counter.put(c, 1);
if(count<goal.get(c)){ }
total++;
} }
if(j!=i){ }
max = Math.max(max, longestSubstring(s.substring(i, j), k));
}
i=j+1;
}
j++; 66 Permutation in String
}
if(i!=j) Given two strings s1 and s2, write a function to return true if s2 contains the permutation of s1. In other words,
max = Math.max(max, longestSubstring(s.substring(i, j), k)); one of the first string’s permutations is the substring of the second string.
For example:
return max;
} Input: s1 = "ab" s2 = "eidbaooo"
Output: True
Explanation: s2 contains one permutation of s1 ("ba").
if (j - i + 1 == s1.length()) {
return true;
}
} else {
while (i < j) {
if (s2.charAt(i) == s2.charAt(j)) {
i++;
break;
}
return false;
Program Creek 121 | 568 122 | 568 Program Creek 123 | 568
67 Longest Consecutive Sequence
67.1 Java Solution 1 Assuming the majority exists and since the majority always takes more than half of space, the middle element is
guaranteed to be the majority. Sorting array takes O(nlog(n)). So the time complexity of this solution is nlog(n).
Because it requires O(n) complexity, we can not solve the problem by sorting the array first. Sorting takes at least
public int majorityElement(int[] num) {
O(nlogn) time.
if (num.length == 1) {
We can use a HashSet to add and remove elements. HashSet is implemented by using a hash table. Elements
return num[0];
are not ordered. The add, remove and contains methods have constant time complexity O(1). }
for (int e : num) This problem can be solved in time of O(n) with constant space complexity. The basic idea is that the majority
set.add(e); element can negate all other element’s count.
while (set.contains(left)) {
count++;
set.remove(left);
left--;
}
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;
70.2 Java Solution
return false;
start = "hit"
end = "cog"
71.2 Solution dict = ["hot","dot","dog","lot","log"]
The optimal time is linear to the length of the array N. We can iterate over the array, whenever the largest elements
One shortest transformation is "hit" ->"hot" ->"dot" ->"dog" ->"cog", the program should return its length 5.
get updated, its current value becomes the second largest.
return second;
}
class WordNode{
String word;
int numSteps;
wordDict.add(endWord);
while(!queue.isEmpty()){
WordNode top = queue.remove();
String word = top.word;
if(word.equals(endWord)){
int minLen = Integer.MAX_VALUE; public Node(String word, int depth, Node prev){
while(!queue.isEmpty()){ this.word=word;
Node top = queue.poll(); this.depth=depth;
this.prev=prev;
//top if have shorter result already }
if(result.size()>0 && top.depth>minLen){ }
return result;
}
if(t.equals(endWord)){
//add to result
Program Creek 133 | 568 134 | 568 Program Creek 135 | 568
74 Top K Frequent Elements 74 Top K Frequent Elements
Given a non-empty array of integers, return the k most frequent elements. Time is O(n). HashMap<Integer, Integer> counter = new HashMap<Integer, Integer>();
136 | 568 Program Creek 137 | 568 Program Creek 138 | 568
75 Meeting Rooms II
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.
return result;
}
int[] arr1 = { 1, 3, 5, 7 };
int[] arr2 = { 2, 4, 6, 8 };
int[] arr3 = { 0, 9, 10, 11 };
Result: "abcabc"
79.2 Java Solution
The same letters are at least distance 3 from each other.
}
while(!queue.isEmpty()){
class Worker{
int cnt = Math.min(k, len); int quality;
ArrayList<Character> temp = new ArrayList<Character>(); int wage;
81 Minimum Cost to Hire K Workers double ratio;
for(int i=0; i<cnt; i++){
if(queue.isEmpty()) public Worker(int q, int w){
return ""; There are N workers. The i-th worker has a quality[i] and a minimum wage expectation wage[i]. this.quality = q;
Now we want to hire exactly K workers to form a paid group. When hiring a group of K workers, we must this.wage = w;
char c = queue.poll(); pay them according to the following rules: Every worker in the paid group should be paid in the ratio of their this.ratio = (double)w/q;
sb.append(String.valueOf(c)); quality compared to other workers in the paid group. Every worker in the paid group must be paid at least their }
minimum wage expectation. Return the least amount of money needed to form a paid group satisfying the above }
map.put(c, map.get(c)-1); conditions.
Example:
if(map.get(c)>0){
temp.add(c); Input: quality = [10,20,5], wage = [70,50,30], K = 2
} Output: 105.00000
Explanation: We pay 70 to 0-th worker and 35 to 2-th worker.
len--;
}
if(q.size()>K){
int extra = q.poll();
sum += extra;
}
if(q.size() == K){
result = Math.min(result, sum * w.ratio);
}
}
return result;
}
Program Creek 148 | 568 149 | 568 Program Creek 150 | 568
82 Contains Duplicate 83 Contains Duplicate II 84 Contains Duplicate III
Given an array of integers, find if the array contains any duplicates. Your function should return true if any value 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 Given an array of integers, find out whether there are two distinct indices i and j in the array such that the
appears at least twice in the array, and it should return false if every element is distinct. array such that nums[i] = nums[j] and the difference between i and j is at most k. difference between nums[i] and nums[j] is at most t and the difference between i and j is at most k.
82.1 Java Solution 83.1 Java Solution 1 - HashMap 84.1 Java Solution 1 - Simple
This solution simple. Its time complexity is O(nlog(k)).
public boolean containsDuplicate(int[] nums) { public boolean containsNearbyDuplicate(int[] nums, int k) {
if(nums==null || nums.length==0) HashMap<Integer, Integer> map = new HashMap<Integer, Integer>(); public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
return false; if(nums==null||nums.length<2||k<0||t<0)
for(int i=0; i<nums.length; i++){ return false;
HashSet<Integer> set = new HashSet<Integer>(); if(map.containsKey(nums[i])){
for(int i: nums){ int pre = map.get(nums[i]); TreeSet<Long> set = new TreeSet<Long>();
if(!set.add(i)){ if(i-pre<=k) for(int i=0; i<nums.length; i++){
return true; return true; long curr = (long) nums[i];
} }
} long leftBoundary = (long) curr-t;
map.put(nums[i], i); long rightBoundary = (long) curr+t+1; //right boundary is exclusive, so +1
return false; } SortedSet<Long> sub = set.subSet(leftBoundary, rightBoundary);
} if(sub.size()>0)
return false; return true;
}
set.add(curr);
if(i>=k){ // or if(set.size()>=k+1)
83.2 Java Solution 2 - HashSet set.remove((long)nums[i-k]);
}
}
public boolean containsNearbyDuplicate(int[] nums, int k) {
if(nums==null || nums.length<2 || k==0) return false;
return false; }
int i=0;
if(set.size()>=k+1){
set.remove(nums[i++]);
}
}
return false;
}
public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
if (k < 1 || t < 0)
int row=matrix.length;
85.2 Java Solution 1
int col=matrix[0].length;
public int getLargestSumCloseToK(int[] arr, int k){ public int getLargestSumCloseToK(int[] arr, int k){
Program Creek 154 | 568 155 | 568 Program Creek 156 | 568
85 Max Sum of Rectangle No Larger Than K 86 Maximum Sum of Subarray Close to K
for(int i=0; i<arr.length; i++){ 86 Maximum Sum of Subarray Close to K Integer ceiling = set.ceiling(sum-k);
sum=sum+arr[i]; if(ceiling!=null){
result = Math.max(result, sum-ceiling);
Integer ceiling = set.ceiling(sum-k); Given an array, find the maximum sum of subarray close to k but not larger than k. }
if(ceiling!=null){
result = Math.max(result, sum-ceiling); set.add(sum);
} 86.1 Java Solution }
set.add(sum); The solution to this problem is obvious when we draw the following diagram. return result;
} }
return result;
}
Program Creek 157 | 568 158 | 568 Program Creek 159 | 568
87 Sliding Window Maximum
if(!deque.isEmpty()&&deque.peekFirst()==i-k)
deque.poll();
while(!deque.isEmpty()&&nums[deque.peekLast()]<nums[i]){
deque.removeLast();
87 Sliding Window Maximum } 88 Moving Average from Data Stream
deque.offer(i);
Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the Given a stream of integers and a window size, calculate the moving average of all integers in the sliding window.
very right. You can only see the k numbers in the window. Each time the sliding window moves right by one if(i+1>=k)
position. result[i+1-k]=nums[deque.peek()];
} 88.1 Java Solution
87.1 Java Solution return result; This problem is solved by using a queue.
}
class MovingAverage {
double sum;
int size;
LinkedList<Integer> list;
if(list.size()<=size){
return sum/list.size();
}
sum -= list.poll();
return sum/size;
}
}
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. 90.1 Analysis
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. 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.
set.remove(ceil);
}
}
set.add(t);
} 91 Linked List Random Node 92 Shuffle an Array
public List<Interval> getIntervals() { Given a singly linked list, return a random node’s value from the linked list. Each node must have the same Shuffle a set of numbers without duplicates.
return new ArrayList(set); probability of being chosen.
//Arrays.asList(set.toArray(new Interval[0])); Follow up: What if the linked list is extremely large and its length is unknown to you? Could you solve this
} efficiently without using extra space? 92.1 Java Solution
}
How we make sure each the probability of each element get shuffled is very similar to the streaming random
91.1 Java Solution problem.
The algorithm is straightforward to understand, but the question is why it works. To have a working shuffle
This problem is trivial, so I focus on the follow-up problem. algorithm, every element in the array results in each position should be equal.
We want the probability of being chosen is 1/count.
Given a list 1 ->2 ->3 ->4 ->5 ->... ->n, the only time we can possibly select the third node is when the pointer
points to 3. The probability of selecting the third node is 1/3 * 3/4 * 4/5 * ... * (n-1)/n = 1/n.
/** @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;
}
class Solution {
int[] original = null;
int[] shuffle = null;
Random rand = null;
Program Creek 169 | 568 170 | 568 Program Creek 171 | 568
94 Quicksort Array in Java 94 Quicksort Array in Java
This post shows two versions of the Java implementation. The first one picks the rightmost element as the pivot if (i <= j) {
int temp = arr[i];
and the second one picks the middle element as the pivot.
arr[i] = arr[j];
arr[j] = temp;
i++;
94.1 Version 1: Rightmost element as pivot
j--;
}
The following is the Java Implementation using rightmost element as the pivot.
}
public class QuickSort {
// recursively sort two sub parts
public static void main(String[] args) { if (low < j)
int[] arr = {4, 5, 1, 2, 3, 3}; quickSort(arr, low, j);
quickSort(arr, 0, arr.length-1);
System.out.println(Arrays.toString(arr)); if (high > i)
} quickSort(arr, i, high);
}
public static void quickSort(int[] arr, int start, int end){ }
172 | 568 Program Creek 173 | 568 Program Creek 174 | 568
95 Kth Largest Element in an Array
int low;
int high;
public Bucket(){
low = -1;
high = -1;
97 Maximum Gap } 98 Group Anagrams
}
Given an unsorted array, find the maximum difference between the successive elements in its sorted form. public int maximumGap(int[] num) { Given an array of strings, return all groups of strings that are anagrams.
Try to solve it in linear time/space. Return 0 if the array contains less than 2 elements. You may assume all if(num == null || num.length < 2){ An anagram is a type of word play, the result of rearranging the letters of a word or phrase to produce a new word or
elements in the array are non-negative integers and fit in the 32-bit signed integer range. return 0; phrase, using all the original letters exactly once; for example, Torchwood can be rearranged into Doctor Who.
}
From: interval * (num[i] - min) = 0 and interval * (max -num[i]) = n // initialize an array of buckets HashMap<String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>();
interval = num.length / (max - min) Bucket[] buckets = new Bucket[num.length+1]; //project to (0 - n) for(String str: strs){
for(int i=0; i<buckets.length; i++){ char[] arr = new char[26];
buckets[i] = new Bucket(); for(int i=0; i<str.length(); i++){
The following diagram shows an example.
} arr[str.charAt(i)-’a’]++;
}
double interval = (double) num.length / (max - min); String ns = new String(arr);
//distribute every number to a bucket array
for(int i=0; i<num.length; i++){ if(map.containsKey(ns)){
int index = (int) ((num[i] - min) * interval); map.get(ns).add(str);
}else{
if(buckets[index].low == -1){ ArrayList<String> al = new ArrayList<String>();
buckets[index].low = num[i]; al.add(str);
buckets[index].high = num[i]; map.put(ns, al);
}else{ }
buckets[index].low = Math.min(buckets[index].low, num[i]); }
buckets[index].high = Math.max(buckets[index].high, num[i]);
} result.addAll(map.values());
}
return result;
//scan buckets to find maximum gap }
int result = 0;
int prev = buckets[0].high;
for(int i=1; i<buckets.length; i++){
if(buckets[i].low != -1){ 98.2 Time Complexity
result = Math.max(result, buckets[i].low-prev);
prev = buckets[i].high; If the average length of verbs is m and array length is n, then the time is O(n*m).
}
return result;
}
class Bucket{
return list.get(list.size()-1);
}
i=0
0 1 2 3 4 5 6
102 Find K Pairs with Smallest Sums 103 Rotate Array in Java 0 1 2 3 4 6 5
...
6 0 1 2 3 4 5
You are given two integer arrays nums1 and nums2 sorted in ascending order and an integer k. Rotate an array of n elements to the right by k steps. i=1
Define a pair (u,v) which consists of one element from the first array and one element from the second array. 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 6 0 1 2 3 5 4
Find the k pairs (u1,v1),(u2,v2) ...(uk,vk) with the smallest sums. do you know to solve this problem? ...
Example: 5 6 0 1 2 3 4
i=2
Given nums1 = [1,7,11], nums2 = [2,4,6], k = 3 103.1 Solution 1 - Intermediate Array 5 6 0 1 2 4 3
...
Return: [1,2],[1,4],[1,6] In a straightforward way, we can create a new array and then copy elements to the new array. Then change the 4 5 6 0 1 2 3
original array by using System.arraycopy().
The first 3 pairs are returned from the sequence:
[1,2],[1,4],[1,6],[7,2],[7,4],[11,2],[7,6],[11,4],[11,6] public void rotate(int[] nums, int k) {
if(k > nums.length) 103.3 Solution 3 - Reversal
k=k%nums.length;
Can we do this in O(1) space and in O(n) time? The following solution does.
102.1 Java Solution int[] result = new int[nums.length]; Assuming we are given 1,2,3,4,5,6 and order 2. The basic idea is:
This problem is similar to Super Ugly Number. The basic idea is using an array to track the index of the next for(int i=0; i < k; i++){ 1. Divide the array two parts: 1,2,3,4 and 5, 6
element in the other array. result[i] = nums[nums.length-k+i]; 2. Reverse first part: 4,3,2,1,5,6
The best way to understand this solution is using an example such as nums1=1,3,11 and nums2=2,4,8. } 3. Reverse second part: 4,3,2,1,6,5
4. Reverse the whole array: 5,6,1,2,3,4
public List<int[]> kSmallestPairs(int[] nums1, int[] nums2, int k) { int j=0;
int total=nums1.length*nums2.length; for(int i=k; i<nums.length; i++){
if(total<k){ result[i] = nums[j]; public static void rotate(int[] arr, int order) {
k=total; j++; if (arr == null || arr.length==0 || order < 0) {
} } throw new IllegalArgumentException("Illegal argument!");
}
List<int[]> result = new ArrayList<int[]>(); System.arraycopy( result, 0, nums, 0, nums.length );
int[] idx = new int[nums1.length];//track each element’s cursor in nums2 } if(order > arr.length){
while(k>0){ order = order %arr.length;
int min=Integer.MAX_VALUE; Space is O(n) and time is O(n). You can check out the difference between System.arraycopy() and Arrays.copyOf(). }
int minIdx=-1;
for(int i=0; i<nums1.length; i++){ //length of first part
if(idx[i]<nums2.length && nums1[i]+nums2[idx[i]]<min){ 103.2 Solution 2 - Bubble Rotate int a = arr.length - order;
minIdx=i;
min=nums1[i]+nums2[idx[i]]; Can we do this in O(1) space? reverse(arr, 0, a-1);
} reverse(arr, a, arr.length-1);
This solution is like a bubble sort.
} reverse(arr, 0, arr.length-1);
result.add(new int[]{nums1[minIdx],nums2[idx[minIdx]]}); public static void rotate(int[] arr, int order) {
idx[minIdx]++; if (arr == null || order < 0) { }
k--; throw new IllegalArgumentException("Illegal argument!");
} } public static void reverse(int[] arr, int left, int right){
if(arr == null || arr.length == 1)
return result; for (int i = 0; i < order; i++) { return;
} for (int j = arr.length - 1; j > 0; j--) {
int temp = arr[j]; while(left < right){
arr[j] = arr[j - 1]; int temp = arr[left];
arr[j - 1] = temp; arr[left] = arr[right];
} arr[right] = temp;
} left++;
} right--;
}
}
reverse(s, i, s.length-1);
105.2 Java Solution 2 - Bit
return r;
}
106.1 Java Solution - Finding Cycle 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]]
The following shows how fast and slow pointers solution works. It basically contains 2 steps: 1) find the meeting For example, given an array 1,2,0,4, the algorithm does the following:
point 2) start from the beginning and the meeting point respectively and find the intersection point.
} while(start<=end){
int mid=(start+end)/2;
int midX=mid/n;
return result; int midY=mid%n;
}
if(matrix[midX][midY]==target)
public ArrayList<String> getTime(ArrayList<ArrayList<Integer>> lists, boolean isHour){ return true;
ArrayList<String> result = new ArrayList<String>();
if(matrix[midX][midY]<target){
for(ArrayList<Integer> l : lists){ start=mid+1;
int sum=0; }else{
for(int i: l){ end=mid-1;
sum+= (1<<(i-1)); }
} }
if(isHour && sum>=12)
continue; return false;
}
if(!isHour&&sum>=60) }
Program Creek 196 | 568 Program Creek 197 | 568 198 | 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]){
111 Search a 2D Matrix II return true; 112 Kth Smallest Element in a Sorted Matrix
}
}
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties: Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth smallest
Integers in each row are sorted in ascending from left to right. Integers in each column are sorted in ascending for(int i=i1;i<=i2;i++){ element in the matrix.
from top to bottom. if(target > matrix[i][j2]){ Note that it is the kth smallest element in the sorted order, not the kth distinct element.
For example, consider the following matrix: return helper(matrix, i1, i+1, j1, j2, target); Example:
}else if(target == matrix[i][j2]){
[ return true; matrix = [
[1, 4, 7, 11, 15], } [ 1, 5, 9],
[2, 5, 8, 12, 19], } [10, 11, 13],
[3, 6, 9, 16, 22], [12, 13, 15]
[10, 13, 14, 17, 24], return false; ],
[18, 21, 23, 26, 30] }
] k = 8,
return 13.
Given target = 5, return true.
111.2 Java Solution 2
112.1 Java Solution
111.1 Java Solution 1 Time Complexity: O(m + n)
This problem is similar to Search a 2D Matrix II. The start point of such a sorted matrix is left-bottom corner.
In a naive approach, we can use the matrix boundary to reduce the search space. Here is a simple recursive public boolean searchMatrix(int[][] matrix, int target) {
implementation. int m=matrix.length-1; public int kthSmallest(int[][] matrix, int k) {
int n=matrix[0].length-1; int m=matrix.length;
public boolean searchMatrix(int[][] matrix, int target) {
int i1=0; int i=m; int lower = matrix[0][0];
int i2=matrix.length-1; int j=0; int upper = matrix[m-1][m-1];
int j1=0;
int j2=matrix[0].length-1; while(i>=0 && j<=n){ while(lower<upper){
if(target < matrix[i][j]){ int mid = lower + ((upper-lower)>>1);
return helper(matrix, i1, i2, j1, j2, target); i--; int count = count(matrix, mid);
} }else if(target > matrix[i][j]){ if(count<k){
j++; lower=mid+1;
public boolean helper(int[][] matrix, int i1, int i2, int j1, int j2, int target){ }else{ }else{
return true; upper=mid;
if(i1>i2||j1>j2) } }
return false; } }
} case "R":
} y++;
break;
return count; case "D":
} x++;
113 Design Snake Game break;
}
Design a Snake game that is played on a device with screen size = width x height. Play the game online if you if(!isValid(x,y)){
are not familiar with the game. return -1;
The snake is initially positioned at the top left corner (0,0) with length = 1 unit. }
You are given a list of food’s positions in row-column order. When a snake eats the food, its length and the
game’s score both increase by 1. return process(x, y);
Each food appears one by one on the screen. For example, the second food will not appear until the first food }
was eaten by the snake.
When a food does appear on the screen, it is guaranteed that it will not appear on a block occupied by the public boolean isValid(int x, int y){
if(x<0 || x>=row || y<0 || y>=col)
snake.
return false;
return true;
113.1 Java Solution
}
Program Creek 202 | 568 203 | 568 Program Creek 204 | 568
114 Number of Islands II
return i;
}
public List<Integer> numIslands2(int m, int n, int[][] positions) { Given n = 5 and edges = [[0, 1], [1, 2], [3, 4]], return 2.
int[] rootArray = new int[m*n];
Arrays.fill(rootArray,-1);
115.1 Java Solution - Union-find
ArrayList<Integer> result = new ArrayList<Integer>();
This problem can be solved by using union-find beautifully. Initially, there are n nodes. The nodes that are
int[][] directions = {{-1,0},{0,1},{1,0},{0,-1}};
involved in each edge is merged.
int count=0;
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;
}
return count;
}
public int getRoot(int[] arr, int i){ 116 Most Stones Removed with Same Row or
while(arr[i]!=i){
arr[i]= arr[arr[i]]; Column
i=arr[i];
}
return i; The easiest solution for this problem is the union-find. The number of island problem can help understand how
} union-find works.
The basic idea is that we use a disjoint set to track each component. Whenever two stones can be connected,
There are k loops and each loop processing the root array costs log(n). Therefore, time complexity is O(k*log(n)). the number of islands decrease one. The final result, the number of movement, is the total number of stones - the
number of islands.
Example 1:
Note:
class Solution {
int[] root = new int[1000]; //value is index
int result = 0;
Program Creek 208 | 568 Program Creek 209 | 568 210 | 568
116 Most Stones Removed with Same Row or Column 116 Most Stones Removed with Same Row or Column
Program Creek 211 | 568 Program Creek 212 | 568 213 | 568
117 Longest Increasing Path in a Matrix 117 Longest Increasing Path in a Matrix
}
}
int[][] mem = new int[m][n]; word = "ABCCED", ->returns true, word = "SEE", ->returns true, word = "ABCB", ->returns false.
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
int t = helper(matrix, mem, i, j); 118.1 Java Solution
result = Math.max(result, t);
} This problem can be solve by using a typical DFS algorithm.
}
public boolean exist(char[][] board, String word) {
return result; int m = board.length;
} int n = board[0].length;
private int helper(int[][] matrix, int[][] mem, int i, int j) { boolean result = false;
if (mem[i][j] > 0) { for(int i=0; i<m; i++){
return mem[i][j]; for(int j=0; j<n; j++){
} if(dfs(board,word,i,j,0)){
result = true;
int[] dx = {-1, 0, 1, 0}; }
int[] dy = {0, 1, 0, -1}; }
}
for (int k = 0; k < 4; k++) {
int x = i + dx[k]; return result;
int y = j + dy[k]; }
if (x >= 0 && y >= 0 public boolean dfs(char[][] board, String word, int i, int j, int k){
&& x < matrix.length int m = board.length;
&& y < matrix[0].length int n = board[0].length;
&& matrix[x][y] > matrix[i][j]) {
mem[i][j] = Math.max(mem[i][j], helper(matrix, mem, x, y)); if(i<0 || j<0 || i>=m || j>=n){
} return false;
} }
Program Creek 214 | 568 Program Creek 215 | 568 216 | 568
118 Word Search 118 Word Search
return false;
} 119.1 Java Solution 1
Similar to Word Search, this problem can be solved by DFS. However, this solution exceeds time limit.
int m = board.length;
int n = board[0].length;
Program Creek 217 | 568 Program Creek 218 | 568 219 | 568
119 Word Search II 119 Word Search II 119 Word Search II
public void dfs(char[][] board, boolean[][] visited, String str, int i, int j, Trie trie){ if(node.item.equals(word)){
if (i < 0 || j < 0 || i >= m || j >= n || k > word.length() - 1) { int m=board.length; return true;
return false; int n=board[0].length; }else{
} return false;
if(i<0 || j<0||i>=m||j>=n){ }
if (board[i][j] == word.charAt(k)) { return; }
char temp = board[i][j]; }
board[i][j] = ’#’; public boolean startsWith(String prefix){
if(visited[i][j]) TrieNode node = root;
if (k == word.length() - 1) { return; for(char c: prefix.toCharArray()){
return true; if(node.children[c-’a’]==null)
} else if (dfs(board, word, i - 1, j, k + 1) str = str + board[i][j]; return false;
|| dfs(board, word, i + 1, j, k + 1) node = node.children[c-’a’];
|| dfs(board, word, i, j - 1, k + 1) if(!trie.startsWith(str)) }
|| dfs(board, word, i, j + 1, k + 1)) { return; return true;
board[i][j] = temp; }
return true; if(trie.search(str)){ }
} result.add(str);
}
} else {
return false; visited[i][j]=true;
} dfs(board, visited, str, i-1, j, trie);
dfs(board, visited, str, i+1, j, trie);
return false; dfs(board, visited, str, i, j-1, trie);
} dfs(board, visited, str, i, j+1, trie);
visited[i][j]=false;
}
}
119.2 Java Solution 2 - Trie
If the current candidate does not exist in all words’ prefix, we can stop backtracking immediately. This can be //Trie Node
class TrieNode{
done by using a trie structure.
public TrieNode[] children = new TrieNode[26];
public class Solution { public String item = "";
Set<String> result = new HashSet<String>(); }
Program Creek 220 | 568 Program Creek 221 | 568 Program Creek 222 | 568
120 Number of Islands 120 Number of Islands
merge(grid, i, j+1); }
}
return i;
}
120 Number of Islands 120.2 Java Solution 2 - Union-Find Check out Number of Island II.
Time is O(m*n*log(k)).
Given a 2-d grid map of ’1’s (land) and ’0’s (water), count the number of islands. An island is surrounded by
water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of public int numIslands(char[][] grid) {
the grid are all surrounded by water. if(grid==null || grid.length==0 || grid[0].length==0)
Example 1: return 0;
223 | 568 Program Creek 224 | 568 Program Creek 225 | 568
121 Find a Path in a Matrix
list.clear();
list.addAll(temp);
return;
}
121 Find a Path in a Matrix int[] dx = {-1, 0, 1, 0}; 122 Sudoku Solver
int[] dy = {0, 1, 0, -1};
Given a 2d matrix, find a path from the top left corner to bottom right corner. Assume there exists at least one for(int k=0; k<4; k++){ Write a program to solve a Sudoku puzzle by filling the empty cells.
path, and you only need to find one valid path. You can move up, right, down, left at any position. int x = i+dx[k];
For example, given int y = j+dy[k];
122.1 Java Solution
[1, 0, 0, 0, 0] if(x>=0&&y>=0&&x<=m-1&&y<=m-1 && matrix[x][y]==1){
[1, 0, 1, 1, 1] temp.add(new int[]{x,y});
[1, 1, 1, 0, 1] public void solveSudoku(char[][] board) {
int prev = matrix[x][y];
[1, 0, 0, 0, 1] helper(board);
matrix[x][y]=0;
[1, 0, 0, 0, 1] }
set.clear();
return true;
}
Program Creek 229 | 568 Program Creek 230 | 568 231 | 568
123 Valid Sudoku 124 Walls and Gates
} int m = rooms.length;
m[(int) (board[i][j] - ’1’)] = true; int n = rooms[0].length;
}
} for(int i=0; i<m; i++){
} for(int j=0; j<n; j++){
124 Walls and Gates if(rooms[i][j]==0){
//check each 3*3 matrix fill(rooms, i, j, 0);
for (int block = 0; block < 9; block++) { }
boolean[] m = new boolean[9]; 124.1 Java Solution 1 - DFS }
for (int i = block / 3 * 3; i < block / 3 * 3 + 3; i++) { }
for (int j = block % 3 * 3; j < block % 3 * 3 + 3; j++) { }
if (board[i][j] != ’.’) { public void wallsAndGates(int[][] rooms) {
if (m[(int) (board[i][j] - ’1’)]) { if(rooms==null || rooms.length==0||rooms[0].length==0) public void fill(int[][] rooms, int i, int j, int distance){
return false; return; int m=rooms.length;
} int n=rooms[0].length;
m[(int) (board[i][j] - ’1’)] = true; int m = rooms.length;
} int n = rooms[0].length; if(i<0||i>=m||j<0||j>=n||rooms[i][j]<distance){
} return;
} boolean[][] visited = new boolean[m][n]; }
}
for(int i=0; i<m; i++){ rooms[i][j] = distance;
return true; for(int j=0; j<n; j++){
} if(rooms[i][j]==0){ fill(rooms, i-1, j, distance+1);
fill(rooms, i-1, j, 0, visited); fill(rooms, i, j+1, distance+1);
fill(rooms, i, j+1, 0, visited); fill(rooms, i+1, j, distance+1);
fill(rooms, i+1, j, 0, visited); fill(rooms, i, j-1, distance+1);
fill(rooms, i, j-1, 0, visited); }
visited = new boolean[m][n];
}
}
} 124.2 Java Solution 2 - BFS
}
public void fill(int[][] rooms, int i, int j, int start, boolean[][] visited){ public void wallsAndGates(int[][] rooms) {
int m=rooms.length; if(rooms==null || rooms.length==0||rooms[0].length==0)
int n=rooms[0].length; return;
Program Creek 232 | 568 233 | 568 Program Creek 234 | 568
124 Walls and Gates 125 Surrounded Regions
} }
Program Creek 235 | 568 236 | 568 Program Creek 237 | 568
125 Surrounded Regions 125 Surrounded Regions
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;
Program Creek 238 | 568 Program Creek 239 | 568 240 | 568
126 Set Matrix Zeroes 126 Set Matrix Zeroes
Program Creek 241 | 568 Program Creek 242 | 568 243 | 568
127 Spiral Matrix 127 Spiral Matrix 127 Spiral Matrix
} }
//right - move down bottom--; }
for(int i=0;i<m-1;i++){
result.add(matrix[x++][y]); // prevent duplicate column //left - move up
} if(right<left) if(n>1){
break; for(int i=0;i<m-1;i++){
//bottom - move left result.add(matrix[x--][y]);
for(int i=0;i<n-1;i++){ for(int i=bottom; i>=top; i--){ }
result.add(matrix[x][y--]); result.add(matrix[i][left]); }
} }
left++; if(m==1||n==1)
//left - move up } result.addAll(spiralOrder(matrix, x, y, 1, 1));
for(int i=0;i<m-1;i++){ else
result.add(matrix[x--][y]); return result; result.addAll(spiralOrder(matrix, x+1, y+1, m-2, n-2));
} }
return result;
x++; }
y++; }
m=m-2; 127.2 Java Solution 2
n=n-2;
} We can also recursively solve this problem. The solution’s performance is not better than Solution 1. Therefore,
Solution 1 should be preferred.
return result;
} public class Solution {
} public ArrayList<Integer> spiralOrder(int[][] matrix) {
if(matrix==null || matrix.length==0)
Similarly, we can write the solution this way: return new ArrayList<Integer>();
Program Creek 244 | 568 Program Creek 245 | 568 Program Creek 246 | 568
128 Spiral Matrix II
i++;
result[x][y]=i;
x--;
}
x++;
128 Spiral Matrix II y++; 129 Rotate Image
}
Given an integer n, generate a square matrix filled with elements from 1 to n2̂ in spiral order. For example, given return result; You are given an n x n 2D matrix representing an image.
n = 4, } Rotate the image by 90 degrees (clockwise).
Follow up: Could you do this in-place?
[
[1, 2, 3, 4],
[12, 13, 14, 5],
[11, 16, 15, 6],
128.2 Java Solution 2 129.1 In-place Solution
[10, 9, 8, 7]
By using the relation "matrix[i][j] = matrix[n-1-j][i]", we can loop through the matrix.
] public int[][] generateMatrix(int n) {
int[][] result = new int[n][n]; public void rotate(int[][] matrix) {
int n = matrix.length;
int k=1; for (int i = 0; i < n / 2; i++) {
128.1 Java Solution 1 int top=0; for (int j = 0; j < Math.ceil(((double) n) / 2.); j++) {
int bottom=n-1; int temp = matrix[i][j];
int left=0; matrix[i][j] = matrix[n-1-j][i];
public int[][] generateMatrix(int n) {
int right=n-1; matrix[n-1-j][i] = matrix[n-1-i][n-1-j];
int total = n*n;
matrix[n-1-i][n-1-j] = matrix[j][n-1-i];
int[][] result= new int[n][n];
while(k<=n*n){ matrix[j][n-1-i] = temp;
for(int i=left; i<=right; i++){ }
int x=0;
result[top][i]=k; }
int y=0;
k++; }
int step = 0;
}
top++;
for(int i=0;i<total;){
while(y+step<n){
for(int i=top; i<=bottom; i++){
i++;
result[i][right]=k;
result[x][y]=i;
k++;
y++;
}
right--;
}
y--;
for(int i=right; i>=left; i--){
x++;
result[bottom][i]=k;
k++;
while(x+step<n){
}
i++;
bottom--;
result[x][y]=i;
x++;
for(int i=bottom; i>=top; i--){
}
result[i][left] = k;
x--;
k++;
y--;
}
left++;
while(y>=0+step){
}
i++;
result[x][y]=i;
return result;
y--;
}
}
y++;
x--;
step++;
while(x>=0+step){
[Pleaseinsert\PrerenderUnicode{âĂŞ}intopreamble]-Immutable.png
public NumMatrix(int[][] matrix) {
if(matrix==null || matrix.length==0||matrix[0].length==0)
return;
}
}
}
public int sumRegion(int row1, int col1, int row2, int col2) {
./figures/Range-Sum-Query-2D-\begingroup \let \relax \relax \endgroup [Pleaseinsert\PrerenderUnicode{âĂŞ}intopreamble]-Immutable.png
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];
}
Here we define an array sum[][] which stores the sum value from (0,0) to the current cell.
return result;
}
130.2 Java Solution }
250 | 568 Program Creek 251 | 568 Program Creek 252 | 568
131 Shortest Distance from All Buildings
131 Shortest Distance from All Buildings public void bfs(int[][] grid, int ox, int oy, int i, int j, 132 Best Meeting Point
int distanceSoFar, boolean[][] visited, LinkedList<Integer> queue){
You want to build a house on an empty land which reaches all buildings in the shortest amount of distance. You visit(grid, i, j, i, j, distanceSoFar, visited, queue); A group of two or more people wants to meet and minimize the total travel distance. You are given a 2D grid of
can only move up, down, left and right. You are given a 2D grid of values 0, 1 or 2, where: int n = grid[0].length; values 0 or 1, where each 1 marks the home of someone in the group. The distance is calculated using Manhattan
Each 0 marks an empty land which you can pass by freely. Each 1 marks a building which you cannot pass Distance, where distance(p1, p2) = |p2.x - p1.x| + |p2.y - p1.y|.
through. Each 2 marks an obstacle which you cannot pass through. while(!queue.isEmpty()){ For example, given three people living at (0,0), (0,4), and (2,2):
For example, given three buildings at (0,0), (0,4), (2,2), and an obstacle at (0,2). The point (1,2) is an ideal empty int size = queue.size();
distanceSoFar++; 1 - 0 - 0 - 0 - 1
land to build a house, as the total travel distance of 3+3+1=7 is minimal. So return 7.
| | | | |
for(int k=0; k<size; k++){ 0 - 0 - 0 - 0 - 0
| | | | |
131.1 Java Solution int top = queue.poll();
i=top/n; 0 - 0 - 1 - 0 - 0
This problem can be solve by BFS. We define one matrix for tracking the distance from each building, and another j=top%n;
matrix for tracking the number of buildings which can be reached. The point (0,2) is an ideal meeting point, as the total travel distance of 2+2+2=6 is minimal. So return 6.
visit(grid, ox, oy, i-1, j, distanceSoFar, visited, queue);
public class Solution { visit(grid, ox, oy, i+1, j, distanceSoFar, visited, queue);
visit(grid, ox, oy, i, j-1, distanceSoFar, visited, queue); 132.1 Java Solution
int[][] numReach; visit(grid, ox, oy, i, j+1, distanceSoFar, visited, queue);
int[][] distance; } This problem is converted to find the median value on x-axis and y-axis.
}
}
if(count>3){
board[i][j] &=1;
}
}
}
133 Game of Life 134 TicTacToe
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
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 board[i][j] = board[i][j]>>1; Design a Tic-tac-toe game that is played between two players on a n x n grid.
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 } 134.1 Java Solution 1 - Naive
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. We can simply check the row, column and the diagonals and see if there is a winner.
Because we need to solve the problem in place, we can use the higher bit to record the next state. And at the end, /** Initialize your data structure here. */
shift right a bit to get the next state for each cell. public TicTacToe(int n) {
matrix = new int[n][n];
public void gameOfLife(int[][] board) {
}
if(board==null || board.length==0||board[0].length==0)
return;
/** Player {player} makes a move at ({row}, {col}).
@param row The row of the board.
int m=board.length;
@param col The column of the board.
int n=board[0].length;
@param player The player, can be either 1 or 2.
@return The current winning condition, can be either:
int[] x = {-1, -1, 0, 1, 1, 1, 0, -1};
0: No one wins.
int[] y = {0, 1, 1, 1, 0, -1, -1, -1};
1: Player 1 wins.
2: Player 2 wins. */
for(int i=0; i<m; i++){
public int move(int row, int col, int player) {
for(int j=0; j<n; j++){
matrix[row][col]=player;
int count=0;
for(int k=0; k<8; k++){
//check row
int nx=i+x[k];
boolean win=true;
int ny=j+y[k];
for(int i=0; i<matrix.length; i++){
if(nx>=0&&nx<m&&ny>=0&&ny<n&&(board[nx][ny]&1)==1){
if(matrix[row][i]!=player){
count++;
win=false;
}
break;
}
}
}
//<2 die
if(count<2){
if(win) return player;
board[i][j] &= 1;
}
//check column
win=true;
//same state
for(int i=0; i<matrix.length; i++){
if(count==2||count==3){
if(matrix[i][col]!=player){
board[i][j] |= board[i][j]<<1;
win=false;
}
break;
}
//go live
}
if(count==3){
board[i][j] |=2;
if(win) return player;
}
win=true; dc1+=val;
for(int i=0; i<matrix.length; i++){ }
if(matrix[i][i]!=player){ if(col==n-row-1){
win=false; dc2+=val;
break; }
} 135 Sparse Matrix Multiplication
} if(Math.abs(rows[row])==n
|| Math.abs(cols[col])==n
if(win) return player; || Math.abs(dc1)==n Given two sparse matrices A and B, return the result of AB.
|| Math.abs(dc2)==n){ You may assume that A’s column number is equal to B’s row number.
//check forward diagonal return player;
win=true; }
for(int i=0; i<matrix.length; i++){ 135.1 Naive Method
if(matrix[i][matrix.length-i-1]!=player){ return 0;
win=false; } We can implement Sum(A_ik * B_kj) ->C_ij as a naive solution.
break; }
} public int[][] multiply(int[][] A, int[][] B) {
} //validity check
Program Creek 259 | 568 Program Creek 260 | 568 261 | 568
135 Sparse Matrix Multiplication 136 Add Two Numbers
Since the matrix is sparse, time complexity is O(n2̂) which is much faster than O(n3̂). 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.
136 Add Two Numbers
You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and
each of their nodes contain a single digit. Add the two numbers and return it as a linked list.
Input: (2 ->4 ->3) + (5 ->6 ->4) Output: 7 ->0 ->8
/*
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;
}
Program Creek 262 | 568 263 | 568 Program Creek 264 | 568
137 Reorder List 137 Reorder List
137.1 Java Solution Because the problem requires "in-place" ListNode second = slow.next;
operations, we can only change their pointers, not creating a slow.next = null;// need to close first part 137.2 Takeaway Messages
new list. This problem can be solved by doing the following 3 // now should have two lists: head and fast The three steps can be used to solve other problems of linked list. The following diagrams illustrate how each of
the steps works.
steps: // reverse order for second part Reverse List:
second = reverseOrder(second);
• Break list in the middle to two lists (use fast & slow pointers)
• Reverse the order of the second list ListNode p1 = head;
ListNode p2 = second;
• Merge two list back together
//merge two lists here
The following code is a complete runnable class with testing.
while (p2 != null) {
//Class definition of ListNode ListNode temp1 = p1.next;
class ListNode { ListNode temp2 = p2.next;
int val;
ListNode next; p1.next = p2;
p2.next = temp1;
ListNode(int x) {
val = x; p1 = temp1;
next = null; p2 = temp2;
} }
} }
}
public class ReorderList {
public static ListNode reverseOrder(ListNode head) {
public static void main(String[] args) {
ListNode n1 = new ListNode(1); if (head == null || head.next == null) {
ListNode n2 = new ListNode(2); return head;
ListNode n3 = new ListNode(3); }
ListNode n4 = new ListNode(4);
n1.next = n2; ListNode pre = head;
n2.next = n3; ListNode curr = head.next;
n3.next = n4;
while (curr != null) {
printList(n1); ListNode temp = curr.next;
curr.next = pre;
reorderList(n1); pre = curr;
curr = temp;
printList(n1); }
}
// set head node’s next
public static void reorderList(ListNode head) { head.next = null;
Merge List:
if (head != null && head.next != null) { return pre;
}
265 | 568 Program Creek 266 | 568 Program Creek 267 | 568
137 Reorder List
138 Linked List Cycle 139 Copy List with Random Pointer
Given a linked list, determine if it has a cycle in it. 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.
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 139.1 Java Solution 1
circle.
We can solve this problem by doing the following steps:
• copy every node, i.e., duplicate every node, and insert it to the list
• copy random pointers for all newly created nodes
• break the list to two
if (head == null)
return null;
RandomListNode p = head;
if(slow == fast)
// break list to two
return true;
p = head;
}
RandomListNode newHead = head.next;
while (p != null) {
return false;
RandomListNode temp = p.next;
}
p.next = temp.next;
}
if (temp.next != null)
temp.next = temp.next.next;
p = p.next;
}
return newHead;
}
The break list part above move pointer 2 steps each time, you can also move one at a time which is simpler, like p.next = p1;
the following: p1 = p1.next;
}else{
while(p != null && p.next != null){ p.next = p2;
RandomListNode temp = p.next; p2 = p2.next;
p.next = temp.next; 140 Merge Two Sorted Lists }
p = temp; p=p.next;
} }
Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the
nodes of the first two lists. if(p1!=null){
p.next = p1;
139.2 Java Solution 2 - Using HashMap }
140.1 Analysis
From Xiaomeng’s comment below, we can use a HashMap which makes it simpler. if(p2!=null){
The key to solve the problem is defining a fake head. Then compare the first elements from each list. Add the p.next = p2;
public RandomListNode copyRandomList(RandomListNode head) { smaller one to the merged list. Finally, when one of them is empty, simply append it to the merged list, since it }
if (head == null) is already sorted.
return null; return head.next;
HashMap<RandomListNode, RandomListNode> map = new HashMap<RandomListNode, RandomListNode>(); }
RandomListNode newHead = new RandomListNode(head.label); 140.2 Java Solution
RandomListNode p = head;
RandomListNode q = newHead; public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
map.put(head, newHead); ListNode head = new ListNode(0);
ListNode p = head;
p = p.next;
while (p != null) { while(l1!=null||l2!=null){
RandomListNode temp = new RandomListNode(p.label); if(l1!=null&&l2!=null){
map.put(p, temp); if(l1.val < l2.val){
q.next = temp; p.next = l1;
q = temp; l1=l1.next;
p = p.next; }else{
} p.next=l2;
l2=l2.next;
p = head; }
q = newHead; p = p.next;
while (p != null) { }else if(l1==null){
if (p.random != null) p.next = l2;
q.random = map.get(p.random); break;
else }else if(l2==null){
q.random = null; p.next = l1;
break;
p = p.next; }
q = q.next; }
}
return head.next;
return newHead; }
}
Or write this way:
ListNode p1=l1;
ListNode p2=l2;
while(p1!=null && p2!=null){
if(p1.val < p2.val){
Program Creek 271 | 568 272 | 568 Program Creek 273 | 568
141 Odd Even Linked List
p1.next = p2.next;
p1 = p1.next;
p2.next = p1.next;
141 Odd Even Linked List p2 = p2.next; 142 Remove Duplicates from Sorted List
}
Given a sorted linked list, delete all duplicates such that each element appear only once.
141.1 Problem p1.next = connectNode;
For example,
Given a singly linked list, group all odd nodes together followed by the even nodes. Please note here we are return result;
} Given 1->1->2, return 1->2.
talking about the node number and not the value in the nodes. Given 1->1->2->3->3, return 1->2->3.
The program should run in O(1) space complexity and O(nodes) time complexity.
Example:
Given 1->2->3->4->5->NULL,
142.1 Thoughts
return 1->3->5->2->4->NULL.
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.
141.2 Analysis
142.2 Solution 1
This problem can be solved by using two pointers. We iterate over the link and move the two pointers.
/**
* 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;
142.3 Solution 2
ListNode p = head; Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or
original list. equal to x.
while( p!= null && p.next != null){ For example, given 1->1->1->2->3, return 2->3. You should preserve the original relative order of the nodes in each of the two partitions.
if(p.val == p.next.val){ For example, given 1->4->3->2->5->2 and x = 3, return 1->2->2->4->3->5.
p.next = p.next.next;
}else{ 143.1 Java Solution
p = p.next; 144.1 Java Solution
}
} public ListNode deleteDuplicates(ListNode head) {
ListNode t = new ListNode(0); public class Solution {
return head; t.next = head; public ListNode partition(ListNode head, int x) {
} if(head == null) return null;
} ListNode p = t;
while(p.next!=null&&p.next.next!=null){ ListNode fakeHead1 = new ListNode(0);
if(p.next.val == p.next.next.val){ ListNode fakeHead2 = new ListNode(0);
int dup = p.next.val; fakeHead1.next = head;
while(p.next!=null&&p.next.val==dup){
p.next = p.next.next; ListNode p = head;
} ListNode prev = fakeHead1;
}else{ ListNode p2 = fakeHead2;
p=p.next;
} while(p != null){
if(p.val < x){
} p = p.next;
prev = prev.next;
return t.next; }else{
}
p2.next = p;
prev.next = p.next;
p = prev.next;
p2 = p2.next;
}
}
prev.next = fakeHead2.next;
return fakeHead1.next;
}
}
while(p1 != null){
len1++;
p1 = p1.next;
}
while(p2 !=null){
len2++;
p2 = p2.next;
}
int diff = 0;
p1=headA;
p2=headB;
ListNode pre = h;
while(p1!=null && p2!=null){
pre.next = p2;
ListNode t = p2.next;
147 Swap Nodes in Pairs p2.next = p1; 148 Reverse Linked List
pre = p1;
p1.next = t;
Given a linked list, swap every two adjacent nodes and return its head. Reverse a singly linked list.
For example, given 1->2->3->4, you should return the list as 2->1->4->3. p1 = p1.next;
Your algorithm should use only constant space. You may not modify the values in the list, only nodes itself can
be changed. if(t!=null) 148.1 Java Solution 1 - Iterative
p2 = t.next;
}
147.1 Java Solution 1
return h.next;
Use two template variable to track the previous and next node of each pair. }
head.next = null;
while(p1!=null&& p2!=null){
147.2 Java Solution 2 ListNode t = p2.next;
p2.next = p1;
Each time I do the same problem I often get the different solutions. Here is another way of writing this solution. p1 = p2;
p2 = t;
public ListNode swapPairs(ListNode head) { }
if(head==null || head.next==null)
return head; return p1;
}
//a fake head
ListNode h = new ListNode(0);
h.next = head;
148.2 Java Solution 2 - Recursive
ListNode p1 = head;
ListNode p2 = head.next;
public ListNode reverseList(ListNode head) {
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;
Program Creek 286 | 568 287 | 568 Program Creek 288 | 568
150 Reverse Double Linked List
newHead= p;
p = t;
}
return newHead;
150 Reverse Double Linked List } 151 Remove Nth Node From End of List
Given a double linked list’s head node, reverse the list and return the new head node. Given a linked list, remove the nth node from the end of list and return its head.
For example, given linked list 1->2->3->4->5 and n = 2, the result is 1->2->3->5.
while(fast.next != null){ We can create a new list in reversed order and then compare each node. The time and space are O(n). while(p1!=null && p2!=null){
fast = fast.next; ListNode temp = p2.next;
public boolean isPalindrome(ListNode head) {
slow = slow.next; p2.next = p1;
if(head == null)
} p1 = p2;
return true;
p2 = temp;
slow.next = slow.next.next; }
ListNode p = head;
ListNode prev = new ListNode(head.val);
return head; secondHead.next = null;
}
while(p.next != null){
//compare two sublists now
ListNode temp = new ListNode(p.next.val);
ListNode p = (p2==null?p1:p2);
temp.next = prev;
ListNode q = head;
prev = temp;
while(p!=null){
p = p.next;
if(p.val != q.val)
}
return false;
ListNode p1 = head;
p = p.next;
ListNode p2 = prev;
q = q.next;
while(p1!=null){
}
if(p1.val != p2.val)
return false;
return true;
}
p1 = p1.next;
p2 = p2.next;
}
152.2 Java Solution 2 - Break and reverse second half public boolean isPalindrome(ListNode head) {
left = head;
We can use a fast and slow pointer to get the center of the list, then reverse the second list and compare two
sublists. The time is O(n) and space is O(1). boolean result = helper(head);
return result;
public boolean isPalindrome(ListNode head) { }
Program Creek 292 | 568 293 | 568 Program Creek 294 | 568
152 Palindrome Linked List
//current left and right 153 Delete Node in a Linked List 154 Reverse Nodes in kGroup
boolean y = (left.val == right.val);
//move left to next Write a function to delete a node (except the tail) in a singly linked list, given only access to that node. Given a linked list, reverse the nodes of a linked list k at a time and return its modified list. If the number of
left = left.next; Supposed the linked list is 1 ->2 ->3 ->4 and you are given the third node with value 3, the linked list should 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
become 1 ->2 ->4 after calling your function. the nodes, only nodes itself may be changed.
return y; For example,
}
} 153.1 Java Solution Given this linked list: 1->2->3->4->5
For k = 2, you should return: 2->1->4->3->5
Time is O(n) and space is O(n). For k = 3, you should return: 3->2->1->4->5
public void deleteNode(ListNode node) {
node.val = node.next.val;
node.next = node.next.next;
} 154.1 Java Solution
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;
} }
We can write the reverse method differently like the following. I personally it is more understandable.
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 rNode;
Program Creek 298 | 568 Program Creek 299 | 568 300 | 568
155 Plus One Linked List
head.next=null;
return p1;
}
156 Binary Tree Preorder Traversal 157 Binary Tree Inorder Traversal
Preorder binary tree traversal is a classic interview problem. The key to solve this problem is using a stack to There are 3 solutions for solving this problem.
store left and right children, and push right child first so that it is processed after the left child.
public class TreeNode { • The order of "inorder" is: left child ->parent ->right child
int val; • Use a stack to track nodes
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; } public List<Integer> inorderTraversal(TreeNode root) {
} ArrayList<Integer> result = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
public class Solution {
public ArrayList<Integer> preorderTraversal(TreeNode root) { TreeNode p = root;
ArrayList<Integer> returnList = new ArrayList<Integer>(); while(p!=null){
stack.push(p);
if(root == null) p=p.left;
return returnList; }
}
return returnList;
} 157.2 Java Solution 2 - Recursive
}
The recursive solution is trivial.
return result;
}
The following solution is simple, but it changes the tree structure, i.e., remove pointers to left and right children. //go up the tree from left node
//need to check if there is a right child
public List<Integer> inorderTraversal(TreeNode root) { //if yes, push it to stack
List<Integer> result = new ArrayList<Integer>(); //otherwise, process parent and pop stack
if(root==null) }else if(curr.left == prev){
return result; if(curr.right != null){
Stack<TreeNode> stack = new Stack<TreeNode>(); stack.push(curr.right);
158.1 Java Solution 1
stack.push(root); }else{
stack.pop();
The key to to iterative postorder traversal is the following:
while(!stack.isEmpty()){ lst.add(curr.val);
TreeNode top = stack.peek(); • The order of "Postorder" is: left child ->right child ->parent node. }
if(top.left!=null){
stack.push(top.left); • Find the relation between the previously visited node and the current node //go up the tree from right node
top.left=null; • Use a stack to track nodes //after coming back from right node, process parent node and pop stack.
}else{ }else if(curr.right == prev){
result.add(top.val); As we go down the tree to the lft, check the previously visited node. If the current node is the left or right child stack.pop();
stack.pop(); of the previous node, then keep going down the tree, and add left/right node to stack when applicable. When lst.add(curr.val);
if(top.right!=null){ there is no children for current node, i.e., the current node is a leaf, pop it from the stack. Then the previous node }
stack.push(top.right); become to be under the current node for next loop. You can using an example to walk through the code.
} prev = curr;
} //Definition for binary tree }
} public class TreeNode {
int val; return lst;
return result; TreeNode left; }
} TreeNode right; }
TreeNode(int x) { val = x; }
}
Program Creek 304 | 568 305 | 568 Program Creek 306 | 568
158 Binary Tree Postorder Traversal 159 Binary Tree Level Order Traversal
}
return al;
}
Program Creek 307 | 568 308 | 568 Program Creek 309 | 568
160 Binary Tree Level Order Traversal II
160 Binary Tree Level Order Traversal II return reversedResult; 161 Binary Tree Vertical Order Traversal
}
Given a binary tree, return the bottom-up level order traversal of its nodes’ values. Given a binary tree, return the vertical order traversal of its nodes’ values. (ie, from top to bottom, column by
For example, given binary tree 3,9,20,#,#,15,7, column).
3
/ \ 161.1 Java Solution
9 20
/ \ For each node, its left child’s degree is -1 and is right child’s degree is +1. We can do a level order traversal and
15 7
save the degree information.
return its level order traversal as [[15,7], [9,20],[3]] public List<List<Integer>> verticalOrder(TreeNode root) {
TreeMap<Integer, ArrayList<Integer>> map = new TreeMap<>();
helper(root, map);
160.1 Java Solution List<List<Integer>> result = new ArrayList<>();
result.addAll(map.values());
return result;
public List<ArrayList<Integer>> levelOrderBottom(TreeNode root) { }
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
private void helper(TreeNode t, TreeMap<Integer, ArrayList<Integer>> map) {
if(root == null){ if (t == null) {
return result; return;
} }
Time complexity is O(n*log(n)) and space complexity is O(n). n is the number of nodes on the tree.
r=r.left; }
}
return max;
} }
nodeQueue.offer(head.right);
sizeQueue.offer(rightSize);
}
Program Creek 316 | 568 317 | 568 Program Creek 318 | 568
165 Validate Binary Search Tree
return true;
}
165 Validate Binary Search Tree 166 Flatten Binary Tree to Linked List
165.2 Java Solution 2 - Iterative
Given a binary tree, determine if it is a valid binary search tree (BST). Given a binary tree, flatten it to a linked list in-place.
Assume a BST is defined as follows: For example, Given
public class Solution {
• The left subtree of a node contains only nodes with keys less than the node’s key. public boolean isValidBST(TreeNode root) { 1
if(root == null) / \
• The right subtree of a node contains only nodes with keys greater than the node’s key. 2 5
return true;
• Both the left and right subtrees must also be binary search trees. / \ \
LinkedList<BNode> queue = new LinkedList<BNode>(); 3 4 6
queue.add(new BNode(root, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
165.1 Java Solution 1 - Recursive while(!queue.isEmpty()){ The flattened tree should look like:
BNode b = queue.poll();
All values on the left sub tree must be less than parent and parent’s parent, and all values on the right sub tree if(b.n.val <= b.left || b.n.val >=b.right){ 1
must be greater than parent and parent’s parent. So we just check the boundaries for each node. return false; \
} 2
public boolean isValidBST(TreeNode root) { if(b.n.left!=null){ \
return isValidBST(root, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY); queue.offer(new BNode(b.n.left, b.left, b.n.val)); 3
} } \
if(b.n.right!=null){ 4
public boolean isValidBST(TreeNode p, double min, double max){ queue.offer(new BNode(b.n.right, b.n.val, b.right)); \
if(p==null) } 5
return true; } \
return true; 6
if(p.val <= min || p.val >= max) }
return false; }
//define a BNode class with TreeNode and it’s boundaries
return isValidBST(p.left, min, p.val) && isValidBST(p.right, p.val, max); class BNode{ 166.1 Java Solution
} TreeNode n;
double left; Go down the tree to the left, when the right child is not null, push the right child to the stack.
This solution also goes to the left subtree first. If the violation occurs close to the root but on the right subtree, double right;
the method still cost time O(n) and space O(h). public BNode(TreeNode n, double left, double right){ /**
The following solution can handle violations close to root node faster. this.n = n; * Definition for binary tree
this.left = left; * public class TreeNode {
public boolean isValidBST(TreeNode root) { this.right = right; * int val;
return helper(root, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY); } * TreeNode left;
} } * TreeNode right;
* TreeNode(int x) { val = x; }
public boolean helper(TreeNode root, double min, double max){ Time and space are both O(n). * }
if(root==null){ */
return true; public class Solution {
public void flatten(TreeNode root) {
} 165.3 Java Solution 3 - In-order traversal Stack<TreeNode> stack = new Stack<TreeNode>();
if(root.val<=min||root.val>=max){ TreeNode p = root;
Since inorder traversal of BST is ascending, so we can check the sequence. Time is O(n) and space is O(h). h is
return false;
the height of the stack which is the tree’s height. while(p != null || !stack.empty()){
}
Add all node to a queue and store sum value of each node to another queue. When it is a leaf node, check the return hasPathSum(root.left, sum - root.val)
stored sum value. || hasPathSum(root.right, sum - root.val);
For the tree above, the queue would be: 5 - 4 - 8 - 11 - 13 - 4 - 7 - 2 - 1. It will check node 13, 7, 2 and 1. This is }
nodes.add(root);
values.add(root.val);
while(!nodes.isEmpty()){
TreeNode curr = nodes.poll();
int sumValue = values.poll();
if(curr.left != null){
Program Creek 322 | 568 323 | 568 Program Creek 324 | 568
168 Path Sum II
Given a binary tree and a sum, find all root-to-leaf paths where each path’s sum equals the given sum.
dfs(t.right, sum-t.right.val, result, l); Postorder Traversal
l.remove(l.size()-1);
For example, given the below binary tree and sum = 22, }
} Given inorder and postorder traversal of a tree, construct the binary tree.
5
/ \
4 8
169.1 Analysis
/ / \
11 13 4
This problem can be illustrated by using a simple example.
/ \ / \
7 2 5 1 in-order: 4 2 5 (1) 6 7 3 8
post-order: 4 5 2 6 7 8 3 (1)
the method returns the following:
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.
[5,4,11,2],
[5,8,4,5]
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.
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.
int k = 0;
for (int i = 0; i < inorder.length; i++) { //find parent element index from inorder
if (inorder[i] == rootValue) { int k=0;
k = i; for(int i=0; i<inorder.length; i++){
break; if(val == inorder[i]){
} 170 Construct Binary Tree from Preorder and k=i;
} break;
Inorder Traversal }
root.left = buildTree(inorder, inStart, k - 1, postorder, postStart, }
postStart + k - (inStart + 1));
// Becuase k is not the length, it it need to -(inStart+1) to get the length Given preorder and inorder traversal of a tree, construct the binary tree. p.left = construct(preorder, preStart+1, preStart+(k-inStart), inorder, inStart, k-1);
root.right = buildTree(inorder, k + 1, inEnd, postorder, postStart + k- inStart, postEnd - 1); p.right= construct(preorder, preStart+(k-inStart)+1, preEnd, inorder, k+1 , inEnd);
// postStart+k-inStart = postStart+k-(inStart+1) +1
170.1 Analysis return p;
return root; }
} 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;
}
Program Creek 328 | 568 329 | 568 Program Creek 330 | 568
172 Convert Sorted List to Binary Search Tree
int len = 0;
ListNode p = head;
while (p != null) {
len++;
171 Convert Sorted Array to Binary Search Tree 172 Convert Sorted List to Binary Search Tree p = p.next;
}
return len;
Given an array where elements are sorted in ascending order, convert it to a height balanced BST. Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST. }
h = head;
int len = getLength(head);
return sortedListToBST(0, len - 1);
}
}
}
return 0;
}
173 Minimum Depth of Binary Tree } 174 Binary Tree Maximum Path Sum
Given a binary tree, find its minimum depth. Given a binary tree, find the maximum path sum. The path may start and end at any node in the tree. For
The minimum depth is the number of nodes along the shortest path from the root node down to the nearest example, given the below binary tree
leaf node.
1
/ \
173.1 Thoughts 2 3
LinkedList is a queue in Java. The add() and remove() methods are used to manipulate the queue. the result is 6.
if(curr.left != null){
nodes.add(curr.left);
counts.add(count+1);
}
if(curr.right != null){
nodes.add(curr.right);
counts.add(count+1);
}
}
175.1 Analysis 1
/ \
This is a typical tree problem that can be solve by using recursion. 2 2
/ \ / \
3 4 4 3
175.2 Java Solution
But the following is not:
// Definition for binary tree 1
class TreeNode { / \
int val; 2 2
TreeNode left; \ \
TreeNode right; 3 3
TreeNode(int x) {
val = x;
} 176.2 Java Solution - Recursion
}
This problem can be solve by using a simple recursion. The key is finding the conditions that return false, such
public class Solution { as value is not equal, only one node(left or right) has value.
public boolean isBalanced(TreeNode root) {
if (root == null) public boolean isSymmetric(TreeNode root) {
return true; if (root == null)
return true;
if (getHeight(root) == -1) return isSymmetric(root.left, root.right);
return false; }
}
}
return result;
}
Similarly, we can also use two queues which makes the code slightly more readable.
179 Lowest Common Ancestor of a Binary Search 180 Lowest Common Ancestor of a Binary Tree
public List<Integer> rightSideView(TreeNode root) {
LinkedList<TreeNode> q1 = new LinkedList<>(); Tree Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.
LinkedList<Integer> q2 = new LinkedList<>();
ArrayList<Integer> result = new ArrayList<>(); Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST.
if (root == null) { 180.1 Java Solution 1
return result;
} 179.1 Analysis public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root==null)
q1.offer(root); This problem can be solved by using BST property, i.e., left <parent <right for each node. There are 3 cases to
return null;
q2.offer(1); handle.
int prev = 0;
if(root==p || root==q)
return root;
while (!q1.isEmpty()) { 179.2 Java Solution 1 - Recursive
TreeNode h = q1.poll();
TreeNode l = lowestCommonAncestor(root.left, p, q);
int level = q2.poll();
TreeNode r = lowestCommonAncestor(root.right, p, q);
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (level != prev) { TreeNode m = root;
if(l!=null&&r!=null){
result.add(h.val);
return root;
} if(m.val > p.val && m.val < q.val){
}else if(l==null&&r==null){
return m;
return null;
if (h.right != null) { }else if(m.val>p.val && m.val > q.val){
}else{
q1.offer(h.right); return lowestCommonAncestor(root.left, p, q);
return l==null?r:l;
q2.offer(level + 1); }else if(m.val<p.val && m.val < q.val){
}
} return lowestCommonAncestor(root.right, p, q);
}
}
if (h.left != null) {
q1.offer(h.left); return root; To calculate time complexity, we know that f(n)=2*f(n-1)=2*2*f(n-2)=2ˆ(logn), so time=O(n).
q2.offer(level + 1); }
}
180.2 Java Solution 2
prev = level;
} 179.3 Java Solution 2 - Iterative class Solution {
return result; public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
} public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { CounterNode n = helper(root, p, q);
TreeNode t = root; return n.node;
}
while(t!=null){
if(p.val >t.val && q.val >t.val){ public CounterNode helper(TreeNode root, TreeNode p, TreeNode q){
t = t.right; if(root==null){
}else if (p.val<t.val && q.val<t.val){ return new CounterNode(null, 0);
t = t.left; }
}else{
return t; CounterNode left = helper(root.left, p, q);
} if(left.count==2){
} return left;
}
return null;
} CounterNode right = helper(root.right, p, q);
if(right.count==2){
return right;
helper(root, map);
int maxCount = 0;
for(int i: map.keySet()){
if(map.get(i)>maxCount){
maxCount=map.get(i);
}
}
return result;
}
Program Creek 346 | 568 347 | 568 Program Creek 348 | 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);
182 Verify Preorder Serialization of a Binary Tree stack.remove(stack.size()-1); 183 Populating Next Right Pointers in Each Node
stack.remove(stack.size()-1);
One way to serialize a binary tree is to use pre-order traversal. When we encounter a non-null node, we record stack.add("#"); Given the following perfect binary tree,
the node’s value. If it is a null node, we record using a sentinel value such as #. }
1
9 / \
}
/ \ 2 3
3 2 / \ / \
if(stack.size()==1 && stack.get(0).equals("#"))
/ \ / \ 4 5 6 7
return true;
4 1 # 6 else
/ \ / \ / \ return false;
After calling your function, the tree should look like:
# # # # # # }
1 -> NULL
For example, the above binary tree can be serialized to the string "9,3,4,#,#,1,#,#,2,#,6,#,#", where # represents a / \
If only stack operations are allowed, the solution can be written in the following way: 2 -> 3 -> NULL
null node.
/ \ / \
Given a string of comma separated values, verify whether it is a correct preorder traversal serialization of a public boolean isValidSerialization(String preorder) {
4->5->6->7 -> NULL
binary tree. Find an algorithm without reconstructing the tree. String[] arr = preorder.split(",");
if(depthQueue.isEmpty()){
topNode.next = null;
}else if(depthQueue.peek()>depth){
topNode.next = null;
}else{
topNode.next = nodeQueue.peek();
public boolean isValidSerialization(String preorder) { }
LinkedList<String> stack = new LinkedList<String>();
String[] arr = preorder.split(","); if(topNode.left!=null){
nodeQueue.offer(topNode.left);
for(int i=0; i<arr.length; i++){ depthQueue.offer(depth+1);
stack.add(arr[i]); }
while(stack.size()>=3 if(topNode.right!=null){
nodeQueue.offer(topNode.right);
depthQueue.offer(depth+1); lastCurrent = lastCurrent.next;
} }
}
} //update last head
lastHead = currentHead; 184 Populating Next Right Pointers in Each Node
currentHead = null;
} II
183.2 Java Solution 2
}
This solution is easier to understand. You can use the example tree above to walk through the algorithm. The Follow up for problem "Populating Next Right Pointers in Each Node".
basic idea is have 4 pointers to move towards right on two levels (see comments in the code). What if the given tree could be any binary tree? Would your previous solution still work?
184.1 Analysis
Similar to Populating Next Right Pointers in Each Node, we have 4 pointers at 2 levels of the tree.
Program Creek 352 | 568 Program Creek 353 | 568 354 | 568
184 Populating Next Right Pointers in Each Node II 185 Unique Binary Search Trees
count[0] = 1;
count[1] = 1;
Program Creek 355 | 568 356 | 568 Program Creek 357 | 568
186 Unique Binary Search Trees II
186 Unique Binary Search Trees II 187 Sum Root to Leaf Numbers
Given n, generate all structurally unique BST’s (binary search trees) that store values 1...n. Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number. Find the
For example, Given n = 3, your program should return all 5 unique BST’s shown below. total sum of all root-to-leaf numbers.
For example,
1 3 3 2 1
\ / / / \ \ 1
3 2 1 1 3 2 / \
/ / \ \ 2 3
2 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.
186.1 Analysis
187.1 Java Solution - Recursive
Check out Unique Binary Search Trees I.
This problem can be solved by recursively forming left and right subtrees. The different combinations of left This problem can be solved by a typical DFS approach.
and right subtrees form the set of all unique binary search trees.
public int sumNumbers(TreeNode root) {
int result = 0;
186.2 Java Solution if(root==null)
return result;
Program Creek 361 | 568 362 | 568 Program Creek 363 | 568
188 Count Complete Tree Nodes 189 Closest Binary Search Tree Value
} }
root = root.right;
if(level >=height){ }else if(target<root.val){
return false;
} double diff = Math.abs(root.val-target);
189 Closest Binary Search Tree Value if(diff<min){
if(level == height-1){ min = Math.min(min, diff);
if(t.right == null){ result = root.val;
miss[0]++; Given a non-empty binary search tree and a target value, find the value in the BST that is closest to the target. }
} root = root.left;
if(t.left == null){ }else{
miss[0]++; 189.1 Java Solution 1 - Recursion return root.val;
} }
Recursively traverse down the root. When target is less than root, go left; when target is greater than root, go }
if(t.left!=null){ right.
return false; return result;
} public class Solution { }
} int goal;
double min = Double.MAX_VALUE;
boolean r = helper(t.right, level, height, miss);
if(r){ public int closestValue(TreeNode root, double target) {
boolean l = helper(t.left, level, height, miss); helper(root, target);
return l; return goal;
} }
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){
Program Creek 364 | 568 365 | 568 Program Creek 366 | 568
190 Binary Tree Paths
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);
}
}
inorder(root.left); queue.add(root);
while(!queue.isEmpty()){
if(pre==null){ TreeNode t = queue.poll();
pre=root; if(t!=null){
}else{ sb.append(String.valueOf(t.val) + ",");
if(root.val<pre.val){ queue.add(t.left);
if(first==null){ queue.add(t.right);
first=pre; }else{
} sb.append("#,");
}
second=root; }
}
pre=root; sb.deleteCharAt(sb.length()-1);
} System.out.println(sb.toString());
return sb.toString();
inorder(root.right); }
}
// Decodes your encoded data to tree.
public void recoverTree(TreeNode root) { public TreeNode deserialize(String data) {
if(root==null) if(data==null || data.length()==0)
return; return null;
} int i=1;
} while(!queue.isEmpty()){
TreeNode t = queue.poll();
if(data == null)
if(t==null) return null;
continue;
int[] t = {0};
if(!arr[i].equals("#")){ String[] arr = data.split(",");
t.left = new TreeNode(Integer.parseInt(arr[i])); 195 Inorder Successor in BST
queue.offer(t.left); return helper(arr, t);
}
}else{ Given a binary search tree and a node in it, find the in-order successor of that node in the BST.
t.left = null; public TreeNode helper(String[] arr, int[] t){
// Definition for a binary tree node.
queue.offer(null); if(arr[t[0]].equals("#")){
public class TreeNode {
} return null;
int val;
i++; }
TreeNode left;
TreeNode right;
if(!arr[i].equals("#")){ TreeNode root = new TreeNode(Integer.parseInt(arr[t[0]]));
TreeNode(int x) { val = x; }
t.right = new TreeNode(Integer.parseInt(arr[i]));
}
queue.offer(t.right); t[0]=t[0]+1;
root.left = helper(arr, t);
}else{ t[0]=t[0]+1;
t.right = null; root.right = helper(arr, t);
queue.offer(null); 195.1 Java Solution
} return root;
i++; } The node does not have a pointer pointing to its parent. This is different from Inorder Successor in BST II.
}
public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
if(root==null)
return root;
return null;
}
while(!stack.isEmpty()){ if(c.right==null)
TreeNode h = stack.pop(); return next;
if(h!=null){
sb.append(h.val+","); c = c.right;
stack.push(h.right); while(c.left!=null)
stack.push(h.left); c = c.left;
}else{
sb.append("#,"); return c;
} }
}
When the tree is balanced, time complexity is O(log(n)) and space is O(1). The worst case time complexity is
return sb.toString().substring(0, sb.length()-1); O(n).
}
Program Creek 373 | 568 Program Creek 374 | 568 375 | 568
196 Inorder Successor in BST II
//case 1: right child is not null -> go down to get the next int min = Integer.MAX_VALUE;
Node p = x.right; int max = Integer.MIN_VALUE;
while(p!=null){ HashMap<Integer, HashSet<TreeNode>> reversed = new HashMap<>();
result = p;
p = p.left; for(Map.Entry<TreeNode, Integer> entry: map.entrySet()){
} If the tree is balanced, the time complexity is the height of the tree - O(log(n)). In the worst cast, the time is min = Math.min(min, entry.getValue());
O(n). Space complexity is constant. max = Math.max(max, entry.getValue());
if(result != null){
return result; HashSet<TreeNode> set = reversed.getOrDefault(entry.getValue(), new HashSet<TreeNode>());
} set.add(entry.getKey());
reversed.put(entry.getValue(), set);
//case 2: right child is null -> go up to the parent, }
//until the node is a left child, return the parent
p = x;
List<List<Integer>> result = new ArrayList<List<Integer>>();
while(p!=null){ for(int i=min; i<=max; i++){
if(p.parent!=null && p.parent.left==p){ HashSet<TreeNode> set = reversed.get(i);
return p.parent; ArrayList<Integer> l = new ArrayList<>();
} for(TreeNode td: set){
p = p.parent; l.add(td.val);
} }
result.add(l);
return null; }
}
return result;
}
if(root==null){ }
return 0; }
}
Wrapper l = helper(node.left);
list.get(curr).add(root.val);
Wrapper r = helper(node.right);
return curr;
//current subtree’s boundaries
}
curr.lower = Math.min(node.val, l.lower);
curr.upper = Math.max(node.val, r.upper);
return curr;
Program Creek 379 | 568 380 | 568 Program Creek 381 | 568
199 Implement Trie (Prefix Tree) 199 Implement Trie (Prefix Tree)
382 | 568 Program Creek 383 | 568 Program Creek 384 | 568
199 Implement Trie (Prefix Tree) 200 Add and Search Word Data structure design
return p; public boolean dfsSearch(HashMap<Character, TrieNode> children, String word, int start) {
} 200.1 Java Solution 1 if(start == word.length()){
} if(children.size()==0)
This problem is similar with Implement Trie. The solution 1 below uses the same definition of a trie node. To return true;
If the same words can be inserted more than once, what do you need to change to make it work? handle the "." case for this problem, we need to search all possible paths, instead of one path. else
TrieNode return false;
}
class TrieNode{
char c; char c = word.charAt(start);
HashMap<Character, TrieNode> children = new HashMap<Character, TrieNode>();
boolean isLeaf; if(children.containsKey(c)){
if(start == word.length()-1 && children.get(c).isLeaf){
public TrieNode() {} return true;
}
public TrieNode(char c){
this.c = c; return dfsSearch(children.get(c).children, word, start+1);
} }else if(c == ’.’){
} boolean result = false;
for(Map.Entry<Character, TrieNode> child: children.entrySet()){
WordDictionary if(start == word.length()-1 && child.getValue().isLeaf){
return true;
public class WordDictionary { }
private TrieNode root;
//if any path is true, set result to be true;
public WordDictionary(){ if(dfsSearch(child.getValue().children, word, start+1)){
root = new TrieNode(); result = true;
} }
}
// Adds a word into the data structure.
public void addWord(String word) { return result;
HashMap<Character, TrieNode> children = root.children; }else{
return false;
for(int i=0; i<word.length(); i++){ }
char c = word.charAt(i); }
}
TrieNode t = null;
if(children.containsKey(c)){
t = children.get(c);
}else{ 200.2 Java Solution 2 - Using Array Instead of HashMap
t = new TrieNode(c);
children.put(c,t);
} class TrieNode{
Program Creek 385 | 568 386 | 568 Program Creek 387 | 568
200 Add and Search Word Data structure design 200 Add and Search Word Data structure design
p.isLeaf=true;
}
Program Creek 388 | 568 Program Creek 389 | 568 390 | 568
201 Range Sum Query Mutable 201 Range Sum Query Mutable 201 Range Sum Query Mutable
} }
if(i==j){ return sum;
public class NumArray { return new TreeNode(i, j, nums[i]); }
TreeNode root = null; } }
Program Creek 391 | 568 Program Creek 392 | 568 Program Creek 393 | 568
202 The Skyline Problem
return a.isStart ? -1 : 1;
202 The Skyline Problem } 203 Implement Stack using Queues
});
// process edges Implement the following operations of a stack using queues. push(x) – Push element x onto stack. pop() –
202.1 Analysis
PriorityQueue<Integer> heightHeap = new PriorityQueue<Integer>(10, Collections.reverseOrder()); Removes the element on top of the stack. top() – Get the top element. empty() – Return whether the stack is
This problem is essentially a problem of processing 2*n edges. Each edge has a x-axis value and a height value. empty.
The key part is how to use the height heap to process each edge. for (Edge edge : edges) { Note: only standard queue operations are allowed, i.e., poll(), offer(), peek(), size() and isEmpty() in Java.
if (edge.isStart) {
if (heightHeap.isEmpty() || edge.height > heightHeap.peek()) {
202.2 Java Solution result.add(new int[] { edge.x, edge.height }); 203.1 Analysis
}
heightHeap.add(edge.height); This problem can be solved by using two queues.
class Edge { } else {
int x; heightHeap.remove(edge.height);
int height; 203.2 Java Solution
boolean isStart; if(heightHeap.isEmpty()){
result.add(new int[] {edge.x, 0});
public Edge(int x, int height, boolean isStart) { }else if(edge.height > heightHeap.peek()){ class MyStack {
this.x = x; result.add(new int[]{edge.x, heightHeap.peek()}); LinkedList<Integer> queue1 = new LinkedList<Integer>();
this.height = height; } LinkedList<Integer> queue2 = new LinkedList<Integer>();
this.isStart = isStart; }
} } // Push element x onto stack.
} public void push(int x) {
return result; if(empty()){
} queue1.offer(x);
public List<int[]> getSkyline(int[][] buildings) { }else{
List<int[]> result = new ArrayList<int[]>(); if(queue1.size()>0){
queue2.offer(x);
if (buildings == null || buildings.length == 0 int size = queue1.size();
|| buildings[0].length == 0) { while(size>0){
return result; queue2.offer(queue1.poll());
} size--;
}
List<Edge> edges = new ArrayList<Edge>(); }else if(queue2.size()>0){
queue1.offer(x);
// add all left/right edges int size = queue2.size();
for (int[] building : buildings) { while(size>0){
Edge startEdge = new Edge(building[0], building[2], true); queue1.offer(queue2.poll());
edges.add(startEdge); size--;
Edge endEdge = new Edge(building[1], building[2], false); }
edges.add(endEdge); }
} }
}
// sort edges
Collections.sort(edges, new Comparator<Edge>() { // Removes the element on top of the stack.
public int compare(Edge a, Edge b) { public void pop() {
if (a.x != b.x) if(queue1.size()>0){
return Integer.compare(a.x, b.x); queue1.poll();
}else if(queue2.size()>0){
if (a.isStart && b.isStart) { queue2.poll();
return Integer.compare(b.height, a.height); }
} }
if(tail == -1){
tail = head;
}
return true;
}
boolean pop() {
if (size == 0) {
return false;
}
Program Creek 400 | 568 401 | 568 Program Creek 402 | 568
207 Evaluate Reverse Polish Notation 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;
The following is the code. However, this code contains compilation errors in leetcode. Why? String operators = "+-*/";
403 | 568 Program Creek 404 | 568 Program Creek 405 | 568
208 Valid Parentheses 209 Longest Valid Parentheses 210 Min Stack
Given a string containing just the characters ’(’, ’)’, ’’, ’’, ’[’ and ’]’, determine if the input string is valid. The brackets Given a string containing just the characters ’(’ and ’)’, find the length of the longest valid (well-formed) paren- Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.
must close in the correct order, "()" and "()[]" are all valid but "(]" and "([)]" are not. theses substring. push(x) – Push element x onto stack. pop() – Removes the element on top of the stack. top() – Get the top
For "(()", the longest valid parentheses substring is "()", which has length = 2. Another example is ")()())", where element. getMin() – Retrieve the minimum element in the stack.
the longest valid parentheses substring is "()()", which has length = 4.
208.1 Analysis
210.1 Java Solution
A typical problem which can be solved by using a stack data structure. 209.1 Java Solution
To make constant time of getMin(), we need to keep track of the minimum element for each element in the stack.
A stack can be used to track and reduce pairs. Since the problem asks for length, we can put the index into the Define an element class that holds element value, min value, and pointer to elements below it.
208.2 Java Solution stack along with the character. For coding simplicity purpose, we can use 0 to respresnt ( and 1 to represent ).
class Elem{
This problem is similar with Valid Parentheses, which can also be solved by using a stack.
public int value;
public static boolean isValid(String s) { public int min;
public int longestValidParentheses(String s) {
HashMap<Character, Character> map = new HashMap<Character, Character>(); public Elem next;
Stack<int[]> stack = new Stack<>();
map.put(’(’, ’)’);
int result = 0;
map.put(’[’, ’]’); public Elem(int value, int min){
map.put(’{’, ’}’); this.value = value;
for(int i=0; i<s.length(); i++){
char c = s.charAt(i); this.min = min;
Stack<Character> stack = new Stack<Character>(); }
if(c==’)’){
if(!stack.isEmpty() && stack.peek()[0]==0){ }
for (int i = 0; i < s.length(); i++) {
stack.pop();
char curr = s.charAt(i); public class MinStack {
result = Math.max(result, i-(stack.isEmpty()?-1:stack.peek()[1]));
}else{ public Elem top;
if (map.keySet().contains(curr)) {
stack.push(new int[]{1, i});
stack.push(curr); /** initialize your data structure here. */
}
} else if (map.values().contains(curr)) { public MinStack() {
}else{
if (!stack.empty() && map.get(stack.peek()) == curr) {
stack.push(new int[]{0, i});
stack.pop(); }
}
} else {
}
return false; public void push(int x) {
} if(top == null){
return result;
} top = new Elem(x, x);
}
} }else{
Elem e = new Elem(x, Math.min(x,top.min));
return stack.empty(); e.next = top;
} top = e;
}
if(top == null)
return -1;
return top.value;
}
public int getMin() { 211 Max Chunks To Make Sorted 212 Maximal Rectangle
if(top == null)
return -1;
return top.min; Given an array arr that is a permutation of [0, 1, ..., arr.length - 1], we split the array into some number of "chunks" Given a 2D binary matrix filled with 0’s and 1’s, find the largest rectangle containing all ones and return its area.
} (partitions), and individually sort each chunk. After concatenating them, the result equals the sorted array.
} What is the most number of chunks we could have made?
For example, given [2,0,1], the method returns 0, as there can only be one chunk. 212.1 Analysis
This problem can be converted to the "Largest Rectangle in Histogram" problem.
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 212.2 Java Solution
max number. Each chunk is essentially an interval and the interval can not overlap.
public int maximalRectangle(char[][] matrix) {
int m = matrix.length;
211.2 Java Solution int n = m == 0 ? 0 : matrix[0].length;
int[][] height = new int[m][n + 1];
public int maxChunksToSorted(int[] arr) {
int maxArea = 0;
if(arr==null||arr.length==0){
for (int i = 0; i < m; i++) {
return 0;
for (int j = 0; j < n; j++) {
}
if (matrix[i][j] == ’0’) {
height[i][j] = 0;
// use [min,max] for each chunk
} else {
Stack<int[]> stack = new Stack<int[]>();
height[i][j] = i == 0 ? 1 : height[i - 1][j] + 1;
}
for(int i=0; i<arr.length; i++){
}
int min=arr[i];
}
int max=arr[i];
break;
213.1 Given a nested list of integers represented as a string, case ’,’:
if(sb.length()>0){ //hande case "123," not "[456],"
implement a parser to deserialize it. Each element is either an stack.peek().add(new NestedInteger(Integer.parseInt(sb.toString())));
sb=sb.delete(0, sb.length());
integer, or a list – whose elements may also be integers or other }
lists.
break;
Note: You may assume that the string is well-formed:
default: //digits
• String is non-empty. sb.append(c);
• String does not contain white spaces. }
}
• String contains only digits and "[],"
//handle case "123"
For example,
if(sb.length()>0){
Given s = "[123,[456,[789]]]", return new NestedInteger(Integer.parseInt(sb.toString()));
}
Return a NestedInteger object containing a nested list with 2 elements:
return null;
1. An integer containing value 123. }
2. A nested list containing two elements:
i. An integer containing value 456.
ii. A nested list with one element:
a. An integer containing value 789.
case ’]’:
if(sb.length()>0){ //123, not [456],
stack.peek().add(new NestedInteger(Integer.parseInt(sb.toString())));
sb=sb.delete(0, sb.length());
}
Program Creek 412 | 568 413 | 568 Program Creek 414 | 568
214 Flatten Nested List Iterator
while(!queue.isEmpty()){
NestedInteger top = queue.poll();
214.2 Java Solution 2 int dep = depth.poll();
if(top.isInteger()){
public class NestedIterator implements Iterator<Integer> { sum += dep*top.getInteger();
}else{ }
for(NestedInteger ni: top.getList()){
queue.offer(ni); // calcualte sum
depth.offer(dep+1); int result=0;
} for(int i=maxLayer; i>=1; i--){
} 216 Nested List Weight Sum II if(map.get(i)!=null){
} for(int v: map.get(i)){
result += v*(maxLayer-i+1);
return sum; Given a nested list of integers, return the sum of all integers in the list weighted by their depth. }
} Each element is either an integer, or a list – whose elements may also be integers or other lists. }
Different from the previous question where weight is increasing from root to leaf, now the weight is defined }
from bottom up. i.e., the leaf level integers have weight 1, and the root level integers have the largest weight.
Example 1: Given the list [[1,1],2,[1,1]], return 8. (four 1’s at depth 1, one 2 at depth 2) return result;
Example 2: Given the list [1,[4,[6]]], return 17. (one 1 at depth 3, one 4 at depth 2, and one 6 at depth 1; 1*3 + }
4*2 + 6*1 = 17)
//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);
}
}
Program Creek 418 | 568 419 | 568 Program Creek 420 | 568
217 Decode String
stack.push(new Node(1));
String t = "";
217 Decode String while (i < s.length()) { 218 Evaluate math expression with plus, minus
char c = s.charAt(i);
The key to solve this problem is convert the string to a structured data structure and recursively form the return }
public Node(boolean isPositive, Integer value) {
string.
} else { this.isPositive = isPositive;
class Node{ stack.peek().list.add(new Node(c)); this.value = value;
int num; } this.list = new ArrayList<>();
ArrayList<Node> list; }
char symbol; i++;
boolean isList; } public int evaluate() {
int sum = 0;
public Node(char s){ return getString(stack.peek()); for (Node t : list) {
symbol=s; } if (t.isPositive) {
} sum = sum + t.value;
public String getString(Node node){ } else {
public Node(int n){ String s=""; sum = sum - t.value;
list = new ArrayList<Node>(); if(node.isList){ }
isList=true; for(int i=0; i<node.num; i++){ }
num=n; for(Node t: node.list) return sum;
} s+= getString(t); }
} }
public String toString(){ }else{
String s = ""; s+=node.symbol; public static int evaluate(String s) {
if(isList){ } Stack<Node> stack = new Stack<>();
s += num + ":" + list.toString(); stack.push(new Node(true, 0));
}else{ return s;
s += symbol; } Boolean isPositive = true;
} } StringBuilder sb = null;
return s;
} for (int i = 0; i < s.length(); i++) {
} char c = s.charAt(i);
Node top = stack.peek();
public class Solution {
public String decodeString(String s) { if (c >= ’0’ && c <= ’9’) {
int i = 0; if (sb == null) {
//sort array
public static void main(String[] args) { Arrays.sort(nums);
System.out.println(evaluate("(1-20)+3")); //-16
System.out.println(evaluate("1-(20+1-(2+3))")); //-15 int j=nums.length-1;
} if(nums[j]>share){
} return false;
}
while(j>=0 && nums[j]==share){
j--;
k--;
}
Program Creek 424 | 568 425 | 568 Program Creek 426 | 568
220 Permutations 220 Permutations
return result;
220 Permutations }
For example,
220.2 Java Solution 2 - Recursion
[1,2,3] have the following permutations:
We can also recursively solve this problem. Swap each element with each element after it.
[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], and [3,2,1].
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
helper(0, nums, result);
220.1 Java Solution 1 - Iteration return result;
}
We can get all permutations by the following steps:
private void helper(int start, int[] nums, List<List<Integer>> result){
[1]
if(start==nums.length-1){
[2, 1]
ArrayList<Integer> list = new ArrayList<>();
[1, 2]
for(int num: nums){ Since C(n)=1+C(n-1), if we expand it, we can get time complexity is O(N!).
[3, 2, 1]
list.add(num);
[2, 3, 1]
}
[2, 1, 3]
result.add(list);
[3, 1, 2]
return;
[1, 3, 2]
}
[1, 2, 3]
//System.out.println(temp);
427 | 568 Program Creek 428 | 568 Program Creek 429 | 568
221 Permutations II
Given a collection of numbers that might contain duplicates, return all possible unique permutations. for (int i = 0; i < num.length; i++) { The set [1,2,3,. . . ,n] contains a total of n! unique permutations.
Set<ArrayList<Integer>> currentSet = new HashSet<ArrayList<Integer>>(); By listing and labeling all of the permutations in order, We get the following sequence (ie, for n = 3):
For example, [1,1,2] have the following unique permutations: for (List<Integer> l : returnList) {
[1,1,2], [1,2,1], and [2,1,1]. for (int j = 0; j < l.size() + 1; j++) { "123"
l.add(j, num[i]); "132"
ArrayList<Integer> T = new ArrayList<Integer>(l); "213"
l.remove(j); "231"
221.1 Java Solution 1 currentSet.add(T); "312"
} "321"
Based on Permutation, we can add a set to track if an element is duplicate and no need to swap. }
returnList = new ArrayList<ArrayList<Integer>>(currentSet); Given n and k, return the kth permutation sequence. (Note: Given n will be between 1 and 9 inclusive.)
public List<List<Integer>> permuteUnique(int[] nums) { }
List<List<Integer>> result = new ArrayList<>();
helper(0, nums, result); return returnList; 222.1 Java Solution 1
return result; }
}
public class Solution {
Thanks to Milan for such a simple solution!
private void helper(int start, int[] nums, List<List<Integer>> result){ public String getPermutation(int n, int k) {
if(start==nums.length-1){
ArrayList<Integer> list = new ArrayList<>(); // initialize all numbers
for(int num: nums){ ArrayList<Integer> numberList = new ArrayList<Integer>();
list.add(num); for (int i = 1; i <= n; i++) {
} numberList.add(i);
result.add(list); }
return;
} // change k to be index
k--;
HashSet<Integer> set = new HashSet<>();
// set factorial of n
for(int i=start; i<nums.length; i++){ int mod = 1;
if(set.contains(nums[i])){ for (int i = 1; i <= n; i++) {
continue; mod = mod * i;
} }
set.add(nums[i]);
String result = "";
swap(nums, i, start);
helper(start+1, nums, result); // find sequence
swap(nums, i, start); for (int i = 0; i < n; i++) {
} mod = mod / (n - i);
} // find the right number(curIndex) of
int curIndex = k / mod;
private void swap(int[] nums, int i, int j){ // update k
int temp = nums[i]; k = k % mod;
nums[i] = nums[j];
nums[j] = temp; // get number according to curIndex
} result += numberList.get(curIndex);
// remove from list
numberList.remove(curIndex);
}
return result.toString();
}
}
output[s - 1] = true;
buf.append(Integer.toString(s));
}
return buf.toString();
class Solution {
}
int count = 0;
}
Program Creek 433 | 568 434 | 568 Program Creek 435 | 568
223 Number of Squareful Arrays 224 Generate Parentheses
if(start==A.length-1){ diff.add(0);
count++;
return; for (int i = 0; i < 2 * n; i++) {
} ArrayList<String> temp1 = new ArrayList<String>();
ArrayList<Integer> temp2 = new ArrayList<Integer>();
HashSet<Integer> set = new HashSet<>(); 224 Generate Parentheses
for(int i=start; i<A.length; i++){ for (int j = 0; j < result.size(); j++) {
//use set to track if the same element is used String s = result.get(j);
if(set.contains(A[i])){ Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses. int k = diff.get(j);
continue; For example, given n = 3, a solution set is:
} if (i < 2 * n - 1) {
set.add(A[i]); "((()))", "(()())", "(())()", "()(())", "()()()" temp1.add(s + "(");
temp2.add(k + 1);
swap(A, i, start); }
helper(A, start+1);
swap(A, i, start); 224.1 Java Solution 1 - DFS if (k > 0 && i < 2 * n - 1 || k == 1 && i == 2 * n - 1) {
} temp1.add(s + ")");
} This solution is simple and clear. In the dfs() method, left stands for the remaining number of (, right stands for temp2.add(k - 1);
the remaining number of ). }
void swap(int[] A, int i, int j){ }
int t = A[i]; public List<String> generateParenthesis(int n) {
A[i] = A[j]; ArrayList<String> result = new ArrayList<String>(); result = new ArrayList<String>(temp1);
A[j] = t; dfs(result, "", n, n); diff = new ArrayList<Integer>(temp2);
} return result; }
}
boolean isSquareful(int a, int b){ /* return result;
double root = Math.sqrt(a+b); left and right represents the remaining number of ( and ) that need to be added. }
return (root-Math.floor(root))==0; When left > right, there are more ")" placed than "(". Such cases are wrong and the method stops.
} */
} public void dfs(ArrayList<String> result, String s, int left, int right){
if(left > right)
return;
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("");
Program Creek 436 | 568 437 | 568 Program Creek 438 | 568
225 Combination Sum
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];
}
}
}
private void helper(int[] candidates, int start, int target, int sum,
} return true;
} }
} i++;
}
return false;
230 Regular Expression Matching }
230.3 Java Solution 2 (More Readable) }
Implement regular expression matching with support for ’.’ and ’*’.
’.’ Matches any single character. ’*’ Matches zero or more of the preceding element. public boolean isMatch(String s, String p) {
The matching should cover the entire input string (not partial). // base case
The function prototype should be: bool isMatch(const char *s, const char *p) if (p.length() == 0) {
Some examples: isMatch("aa","a") return false isMatch("aa","aa") return true isMatch("aaa","aa") return false return s.length() == 0;
}
isMatch("aa", "a*") return true isMatch("aa", ".*") return true isMatch("ab", ".*") return true isMatch("aab", "c*a*b")
return true
// special case
if (p.length() == 1) {
The following Java solution is accepted. // case 1: when the second char of p is not ’*’
if (p.charAt(1) != ’*’) {
public class Solution { if (s.length() < 1) {
public boolean isMatch(String s, String p) { return false;
}
if(p.length() == 0) if ((p.charAt(0) != s.charAt(0)) && (p.charAt(0) != ’.’)) {
return s.length() == 0; return false;
} else {
//p’s length 1 is special case return isMatch(s.substring(1), p.substring(1));
if(p.length() == 1 || p.charAt(1) != ’*’){ }
if(s.length() < 1 || (p.charAt(0) != ’.’ && s.charAt(0) != p.charAt(0))) }
return false;
return isMatch(s.substring(1), p.substring(1)); // case 2: when the second char of p is ’*’, complex case.
else {
}else{ //case 2.1: a char & ’*’ can stand for 0 element
int len = s.length(); if (isMatch(s, p.substring(2))) {
return true;
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))) //case 2.2: a char & ’*’ can stand for 1 or more preceding element,
return true; //so try every sub string
i++; int i = 0;
} while (i<s.length() && (s.charAt(i)==p.charAt(0) || p.charAt(0)==’.’)){
return false; if (isMatch(s.substring(i + 1), p.substring(2))) {
445 | 568 Program Creek 446 | 568 Program Creek 447 | 568
231 Expressive Words
m++;
}
while (n < s2.length() && s2.charAt(n) == s2.charAt(n - 1)) {
n++;
}
231 Expressive Words if (n - j > m - i) { 232 Get Target Number Using Number List and
return false;
Sometimes people repeat letters to represent extra feeling, such as "hello" ->"heeellooo", "hi" ->"hiiii". In these
} Arithmetic Operations
strings like "heeellooo", we have groups of adjacent letters that are all the same: "h", "eee", "ll", "ooo". res = isMatch(s1, m, s2, n);
For some given string S, a query word is stretchy if it can be made to be equal to S by any number of applica- } Given a list of numbers and a target number, write a program to determine whether the target number can be
tions of the following extension operation: choose a group consisting of characters c, and add some number of calculated by applying "+-*/" operations to the number list? You can assume () is automatically added when
characters c to the group so that the size of the group is 3 or more. res = res | isMatch(s1, i + 1, s2, j + 1); necessary.
For example, starting with "hello", we could do an extension on the group "o" to get "hellooo", but we cannot For example, given 1,2,3,4 and 21, return true. Because (1+2)*(3+4)=21
get "helloo" since the group "oo" has size less than 3. Also, we could do another extension like "ll" ->"lllll" to return res;
}
get "helllllooo". If S = "helllllooo", then the query word "hello" would be stretchy because of these two extension
operations: query = "hello" ->"hellooo" ->"helllllooo" = S. 232.1 Analysis
Given a list of query words, return the number of words that are stretchy.
Example: Input: S = "heeellooo" words = ["hello", "hi", "helo"] Output: 1 Explanation: We can extend "e" and This is a partition problem which can be solved by using depth first search.
"o" in the word "hello" to get "heeellooo". We can’t extend "helo" to get "heeellooo" because the group "ll" is not
size 3 or more.
232.2 Java Solution
231.1 Java Solution public static boolean isReachable(ArrayList<Integer> list, int target) {
if (list == null || list.size() == 0)
This problem is similar to regular expression matching. return false;
if (s1.charAt(i) != s2.charAt(j)) {
if (left > right) {
return false;
return result;
}
} else if (left == right) {
result.add(list.get(left));
boolean res = false;
return result;
}
if (i + 2 < s1.length()
&& s1.charAt(i + 1) == s2.charAt(j)
for (int i = left; i < right; i++) {
&& s1.charAt(i + 2) == s2.charAt(j)) {
int m = i + 2;
ArrayList<Integer> result1 = getResults(list, left, i, target);
int n = j + 1;
ArrayList<Integer> result2 = getResults(list, i + 1, right, target);
while (m < s1.length() && s1.charAt(m) == s2.charAt(j)) {
//if there is a flip which makes the other player lose, the first play wins
if(!win){
return true;
}
}
}
return false;
}
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):
}else{
dfs(left.substring(1), right+String.valueOf(left.charAt(0)), countLeft, maxLeft);
}
}
237 Scramble String 238 Remove Invalid Parentheses }
Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1. 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 ).
237.1 Java Solution Examples: "()())()" ->["()()()", "(())()"] "(a)())()" ->["(a)()()", "(a())()"] ")(" ->[""]
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);
}
} else {
if ((result = scanFromCenter(s, i - 1, i - 1)) != null)
return result;
}
}
239 Shortest Palindrome 240 Lexicographical Numbers
return result;
}
Given a string S, you are allowed to convert it to a palindrome by adding characters in front of it. Find and return Given an integer n, return 1 - n in lexicographical order.
the shortest palindrome you can find by performing this transformation. private String scanFromCenter(String s, int l, int r) { For example, given 13, return: [1,10,11,12,13,2,3,4,5,6,7,8,9].
For example, given "aacecaaa", return "aaacecaaa"; given "abcd", return "dcbabcd". int i = 1; Please optimize your algorithm to use less time and space. The input size may be as large as 5,000,000.
We can solve this problem by using one of the methods which is used to solve the longest palindrome substring if(i==0){
problem. for(char c=’1’; c<=’9’; c++){
Specifically, we can start from the center and scan two sides. If read the left boundary, then the shortest num[i]=c;
helper(num, i+1, max, result);
palindrome is identified.
}
public String shortestPalindrome(String s) { }else{
if (s == null || s.length() <= 1) num[i]=’a’;
return s; helper(num, num.length, max, result);
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; 241 Combinations 242 Letter Combinations of a Phone Number
}
return result;
} Given two integers n and k, return all possible combinations of k numbers out of 1 ... n. Given a digit string, return all possible letter combinations that the number could represent. (Check out your
For example, if n = 4 and k = 2, a solution is: cellphone to see the mappings) Input:Digit string "23", Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
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.
List<String> l = new ArrayList<>(); This is a typical search problem and it can be solved by using DFS.
if (digits == null || digits.length() == 0) {
return l; public List<String> restoreIpAddresses(String s) {
} ArrayList<ArrayList<String>> result = new ArrayList<ArrayList<String>>();
ArrayList<String> t = new ArrayList<String>();
l.add(""); dfs(result, s, 0, t);
return l; public void dfs(ArrayList<ArrayList<String>> result, String s, int start, ArrayList<String> t){
} //if already get 4 numbers, but s is not consumed, return
if(t.size()>=4 && start!=s.length())
return;
Program Creek 466 | 568 467 | 568 Program Creek 468 | 568
245 Subsets
single.add(S[i]);
temp.add(single);
result.addAll(temp);
}
244 Factor Combinations 245 Subsets
//add empty set
result.add(new ArrayList<Integer>());
Numbers can be regarded as product of its factors. For example, 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 return result;
8 = 2 x 2 x 2;
subsets. }
= 2 x 4.
For example, given S = [1,2,3], the method returns:
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. [3],
[1],
[2],
244.1 Java Solution [1,2,3],
[1,3],
[2,3],
public List<List<Integer>> getFactors(int n) { [1,2],
List<List<Integer>> result = new ArrayList<List<Integer>>(); []
List<Integer> list = new ArrayList<Integer>(); ]
helper(2, 1, n, result, list);
return result;
}
245.1 Thoughts
public void helper(int start, int product, int n, List<List<Integer>> result, List<Integer> curr){
if(start>n || product > n )
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
return ;
subset of Sn-1 and each element in Sn-1 + one more element. Therefore, a Java solution can be quickly formalized.
if(product==n) {
ArrayList<Integer> t = new ArrayList<Integer>(curr);
result.add(t);
245.2 Java Solution
return;
}
public ArrayList<ArrayList<Integer>> subsets(int[] S) {
if (S == null)
for(int i=start; i<n; i++){
return null;
if(i*product>n)
break;
Arrays.sort(S);
if(n%i==0){
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
curr.add(i);
helper(i, i*product, n, result, curr);
for (int i = 0; i < S.length; i++) {
curr.remove(curr.size()-1);
ArrayList<ArrayList<Integer>> temp = new ArrayList<ArrayList<Integer>>();
}
}
//get sets that are already in result
}
for (ArrayList<Integer> a : result) {
temp.add(new ArrayList<Integer>(a));
}
246.1 Thoughts
Comparing this problem with Subsets can help better understand the problem.
Let dp[i] to be the minimum number of coins required to get the amount i.
Arrays.sort(num);
dp[i] = 1, if i==coin
otherwise, dp[i]=min(dp[i-coin]+1, dp[i]) if dp[i-coin] is reachable.
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
We initially set dp[i] to be MAX_VALUE.
ArrayList<ArrayList<Integer>> prev = new ArrayList<ArrayList<Integer>>();
continue; }
} }
dp[i]=Math.min(dp[i-coin]+1, dp[i]); }
}
} if(dp[amount]==Integer.MAX_VALUE){
} return -1; 248 Palindrome Partitioning
}
if(dp[amount]==Integer.MAX_VALUE){
return -1; return dp[amount]; 248.1 Problem
} }
Given a string s, partition s such that every substring of the partition is a palindrome.
return dp[amount]; Time and space are the same as Solution 1. Return all possible palindrome partitioning of s.
}
For example, given s = "aab", Return
Time complexity is O(amount * num_of_coins) and space complexity is O(amount). 247.3 Java Solution 3 - Breath First Search (BFS) [
["aa","b"],
Dynamic programming problems can often be solved by using BFS. ["a","a","b"]
247.2 Java Solution 2 - Dynamic Programming (Looking Forward) We can view this problem as going to a target position with steps that are allows in the array coins. We maintain ]
two queues: one of the amount so far and the other for the minimal steps. The time is too much because of the
contains method take n and total time is O(n3̂).
Program Creek 475 | 568 Program Creek 476 | 568 477 | 568
248 Palindrome Partitioning
return result;
}
for (int i = 0; i < num.length; i++) { After robbing those houses on that street, the thief has found himself a new place for his thievery so that he will The houses form a binary tree. If the root is robbed, its left and right can not be robbed.
if (i % 2 == 0) { not get too much attention. This time, all houses at this place are arranged in a circle. That means the first house
even += num[i]; is the neighbor of the last one. Meanwhile, the security system for these houses remain the same as for those in
even = even > odd ? even : odd; the previous street. 252.1 Analysis
} else {
Given a list of non-negative integers representing the amount of money of each house, determine the maximum
odd += num[i]; Traverse down the tree recursively. We can use an array to keep 2 values: the maximum money when a root is
amount of money you can rob tonight without alerting the police.
odd = even > odd ? even : odd; selected and the maximum value when a root if NOT selected.
}
}
251.1 Analysis
252.2 Java Solution
return even > odd ? even : odd;
}
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 public int rob(TreeNode root) {
scan the array twice and get the larger value. if(root == null)
return 0;
250.3 Java Solution 3 - Dynamic Programming with Memorization
251.2 Java Solution int[] result = helper(root);
return Math.max(result[0], result[1]);
public int rob(int[] nums) { }
if(nums.length==0){ public int rob(int[] nums) {
return 0; if(nums==null || nums.length==0)
public int[] helper(TreeNode root){
} return 0;
if(root == null){
int[] result = {0, 0};
int[] mem = new int[nums.length+1]; if(nums.length==1)
return result;
Arrays.fill(mem, -1); return nums[0];
}
return true;
}
return false;
}
253 Jump Game 254 Jump Game II
Given an array of non-negative integers, you are initially positioned at the first index of the array. Each element 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 in the array represents your maximum jump length at that position.
index. For example: A = [2,3,1,1,4], return true. A = [3,2,1,0,4], return false. Your goal is to reach the last index in the minimum number of jumps.
For example, given array A = [2,3,1,1,4], the minimum number of jumps to reach the last index is 2. (Jump 1
step from index 0 to 1, then 3 steps to the last index.)
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 254.1 Analysis
current position can not reach next position (return false) , and 2) when the maximum index can reach the end
(return true). This is an extension of Jump Game.
The largest index that can be reached is: i + A[i]. The solution is similar, but we also track the maximum steps of last jump.
int lastReach = 0;
int reach = 0;
int step = 0;
//update max
if(i + A[i] > max){
max = i + A[i];
}
for(int i=1; i<prices.length; i++){ public int maxProfit(int[] prices) { The maximum profit = 13
result = Math.max(result, prices[i]-min); int profit = 0;
min = Math.min(min, prices[i]); for(int i=1; i<prices.length; i++){
} int diff = prices[i]-prices[i-1]; 257.2 Java Solution
if(diff > 0){
return result; profit += diff;
} } public int maxProfit(int[] prices) {
} if (prices == null || prices.length < 2) {
return profit; return 0;
} }
int profit = 0;
for (int i = 0; i < prices.length; i++) {
profit = Math.max(profit, left[i] + right[i]);
We track two arrays - local and global. The local array tracks maximum profit of j transactions & the last
transaction is on ith day. The global array tracks the maximum profit of j transactions until ith day.
Program Creek 490 | 568 491 | 568 Program Creek 492 | 568
259 Dungeon Game 260 Decode Ways 261 Perfect Squares
Example: A message containing letters from A-Z is being encoded to numbers using the following mapping: Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which
’A’ ->1 ’B’ ->2 ... ’Z’ ->26 sum to n.
-2 (K) -3 3
Given an encoded message containing digits, determine the total number of ways to decode it. For example, given n = 12, return 3 because 12 = 4 + 4 + 4; given n = 13, return 2 because 13 = 4 + 9.
-5 -10 1
10 30 -5 (P)
t[0] = true; //set first to be true, why? 262.4 The More Interesting Problem
//Because we need initial state
The dynamic solution can tell us whether the string can be broken to words, but can not tell us what words the
for(int i=0; i<s.length(); i++){ string is broken to. So how to get those words?
//should continue from match position Check out Word Break II.
262 Word Break if(!t[i])
continue;
Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one for(String a: dict){
or more dictionary words. For example, given s = "leetcode", dict = ["leet", "code"]. Return true because "leetcode" int len = a.length();
can be segmented as "leet code". int end = i + len;
if(end > s.length())
continue;
262.1 Naive Approach
if(t[end]) continue;
This problem can be solve by using a naive approach, which is trivial. A discussion can always start from that
though. if(s.substring(i, end).equals(a)){
t[end] = true;
public class Solution { }
public boolean wordBreak(String s, Set<String> dict) { }
return wordBreakHelper(s, dict, 0); }
}
return t[s.length()];
public boolean wordBreakHelper(String s, Set<String> dict, int start){ }
if(start == s.length()) }
return true;
Time: O(string length * dict size).
for(String a: dict){
int len = a.length();
int end = start+len; 262.3 Java Solution 3 - Simple and Efficient
//end index should be <= string length In Solution 2, if the size of the dictionary is very large, the time is bad. Instead we can solve the problem in O(n2̂)
if(end > s.length())
time (n is the length of the string).
continue;
public boolean wordBreak(String s, Set<String> wordDict) {
if(s.substring(start, start+len).equals(a)) int[] pos = new int[s.length()+1];
if(wordBreakHelper(s, dict, start+len))
return true; Arrays.fill(pos, -1);
}
pos[0]=0;
return false;
} for(int i=0; i<s.length(); i++){
} if(pos[i]!=-1){
for(int j=i+1; j<=s.length(); j++){
Time is O(n2̂) and exceeds the time limit. String sub = s.substring(i, j);
if(wordDict.contains(sub)){
pos[j]=i;
262.2 Dynamic Programming }
}
The key to solve this problem by using dynamic programming approach: }
}
• Define an array t[] such that t[i]==true =>0-(i-1) can be segmented using dictionary
• Initial state t[0] == true return pos[s.length()]!=-1;
}
496 | 568 Program Creek 497 | 568 Program Creek 498 | 568
263 Word Break II 263 Word Break II
499 | 568 Program Creek 500 | 568 Program Creek 501 | 568
265 Maximal Square
return result*result;
}
while(start<S.length()){
public int maximalSquare(char[][] matrix) {
int j=0;
if(matrix==null||matrix.length==0){
return 0;
for(int i=start; i<S.length(); i++){
}
if(S.charAt(i)==T.charAt(j)&&j==0){
start=i;
int result=0;
}
int[][] dp = new int[matrix.length][matrix[0].length];
if(S.charAt(i)==T.charAt(j)){
for(int i=0; i<matrix.length; i++){
j++;
dp[i][0]=matrix[i][0]-’0’;
}
result=Math.max(result, dp[i][0]);
}
if(j==T.length()){
if(result.equals("")||(i-start+1)<result.length()){
for(int j=0; j<matrix[0].length; j++){
result = S.substring(start, i+1);
dp[0][j]=matrix[0][j]-’0’;
}
result=Math.max(result, dp[0][j]);
start=start+1;
}
break;
}
for(int i=1; i<matrix.length; i++){
for(int j=1; j<matrix[0].length; j++){
if(i==S.length()-1){
if(matrix[i][j]==’1’){
return result;
int min = Math.min(dp[i-1][j], dp[i][j-1]);
}
min = Math.min(min, dp[i-1][j-1]);
}
dp[i][j]=min+1;
}
if(i<grid.length-1){ if(i<m-1){
return grid[i][j] + dfs(i+1, j, grid); return dfs(i+1,j,m,n);
} }
if(j<grid[0].length-1){ if(j<n-1){
return grid[i][j] + dfs(i, j+1, grid); return dfs(i,j+1,m,n);
} }
return 0; return 0;
} }
266.2 Java Solution 2: Dynamic Programming 267.2 Java Solution 2 - Dynamic Programming
Program Creek 508 | 568 509 | 568 Program Creek 510 | 568
269 Paint House
return result;
}
return dp[len1][len2];
}
• if x != y, and we insert y for word1, then dp[i][j] = dp[i][j-1] + 1 public int minDistance(String word1, String word2) {
int m=word1.length();
• if x != y, and we delete x for word1, then dp[i][j] = dp[i-1][j] + 1
int n=word2.length();
• if x != y, and we replace x with y for word1, then dp[i][j] = dp[i-1][j-1] + 1 int[][] mem = new int[m][n];
• When x!=y, dp[i][j] is the min of the three situations. for(int[] arr: mem){
Program Creek 514 | 568 515 | 568 Program Creek 516 | 568
271 Edit Distance in Java 272 Distinct Subsequences Total
return table[S.length()][T.length()];
}
Program Creek 517 | 568 518 | 568 Program Creek 519 | 568
273 Longest Palindromic Substring
From the table, we can clearly see that the longest string is in cell table[1][5].
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].
The dp table looks like the following given a="abc" and b="abcd".
Program Creek 523 | 568 524 | 568 Program Creek 525 | 568
276 LRU Cache 276 LRU Cache
Node t = map.get(key);
The key to solve this problem is using a double linked list which enables us to quickly move nodes.
remove(t);
setHead(t);
return t.value;
}
remove(t);
setHead(t);
}else{
if(map.size()>=cap){
map.remove(tail.key);
remove(tail);
}
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).
Node t = new Node(key, value);
setHead(t);
map.put(key, t);
276.2 Java Solution }
}
Define a double linked list.
//remove a node
class Node{
private void remove(Node t){
int key;
if(t.prev!=null){
int value;
t.prev.next = t.next;
Node prev;
}else{
Node next;
head = t.next;
}
public Node(int key, int value){
this.key=key;
if(t.next!=null){
this.value=value;
t.next.prev = t.prev;
}
}else{
}
tail = t.prev;
}
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 Program Creek 527 | 568 Program Creek 528 | 568
277 Insert Delete GetRandom O(1)
Design a data structure that supports all following operations in O(1) time.
allowed
if(valueMap.size()==1){
insert(val): Inserts an item val to the set if not already present. remove(val): Removes an item val from the set if return idxMap.get(0);
present. getRandom: Returns a random element from current set of elements. Each element must have the same } Design a data structure that supports all following operations in average O(1) time.
probability of being returned. Note: Duplicate elements are allowed.
Random r = new Random();
int idx = r.nextInt(valueMap.size()); insert(val): Inserts an item val to the collection.
277.1 Java Solution remove(val): Removes an item val from the collection if present.
return idxMap.get(idx); getRandom(): Returns a random element from current collection of elements.
We can use two hashmaps to solve this problem. One uses value as keys and the other uses index as the keys. } The probability of each element being returned is linearly related to the number of same value the
} collection contains.
class RandomizedSet {
HashMap<Integer, Integer> valueMap;
HashMap<Integer, Integer> idxMap;
278.1 Java Solution
/** Initialize your data structure here. */
public RandomizedSet() { This problem is similar to Insert Delete GetRandom O(1). We can use two maps. One tracks the index of the
valueMap = new HashMap<>(); element, so that we can quickly insert and remove. The other maps tracks the order of each inserted element, so
idxMap = new HashMap<>(); that we can randomly access any element in time O(1).
}
public class RandomizedCollection {
/** Inserts a value to the set. Returns true if the set did not already contain the specified HashMap<Integer, HashSet<Integer>> map1;
element. */ HashMap<Integer, Integer> map2;
public boolean insert(int val) { Random r;
if(valueMap.containsKey(val)){
return false; /** Initialize your data structure here. */
} public RandomizedCollection() {
map1 = new HashMap<Integer, HashSet<Integer>>();
valueMap.put(val, valueMap.size()); map2 = new HashMap<Integer, Integer>();
idxMap.put(idxMap.size(), val); r = new Random();
}
return true;
} /** Inserts a value to the collection. Returns true if the collection did not already contain the
specified element. */
/** Removes a value from the set. Returns true if the set contained the specified element. */ public boolean insert(int val) {
public boolean remove(int val) { //add to map2
if(valueMap.containsKey(val)){ int size2 = map2.size();
int idx = valueMap.get(val); map2.put(size2+1, val);
valueMap.remove(val);
idxMap.remove(idx); if(map1.containsKey(val)){
map1.get(val).add(size2+1);
Integer tailElem = idxMap.get(idxMap.size()); return false;
if(tailElem!=null){ }else{
idxMap.put(idx,tailElem); HashSet<Integer> set = new HashSet<Integer>();
valueMap.put(tailElem, idx); set.add(size2+1);
} map1.put(val, set);
return true;
return true; }
} }
return false;
/** Removes a value from the collection. Returns true if the collection contained the specified
element. */ if(n.next!=null){
public boolean remove(int val) { n.next.set.add(val); // next + 1
if(map1.containsKey(val)){ map.put(val, n.next);
HashSet<Integer> set = map1.get(val); }else{
int toRemove = set.iterator().next(); 279 Design a Data Structure with Insert, Delete Node t = new Node(n.value+1);
t.set.add(val);
and GetMostFrequent of O(1) n.next = t;
//remove from set of map1 t.prev = n;
set.remove(toRemove); map.put(val, t);
Design a data structure that allows O(1) time complexity to insert, delete and get most frequent element. }
if(set.size()==0){
map1.remove(val); //update head
} 279.1 Analysis if(head.next!=null)
head = head.next;
if(toRemove == map2.size()){ At first, a hash map seems to be good for insertion and deletion. But how to make getMostFrequent O(1)? Regular }else{
map2.remove(toRemove); sorting algorithm takes nlogn, so we can not use that. As a result we can use a linked list to track the maximum if(tail==null||head==null){
return true; frequency. Node n = new Node(1);
} n.set.add(val);
map.put(val, n);
int size2 = map2.size();
279.2 Java Solution
int key = map2.get(size2); head = n;
tail = n;
HashSet<Integer> setChange = map1.get(key); import java.util.*; return;
setChange.remove(size2); }
setChange.add(toRemove); class Node {
int value; if(tail.value>1){
Node prev; Node n = new Node(1);
Node next; n.set.add(val);
map2.remove(size2); HashSet<Integer> set; map.put(val, n);
map2.remove(toRemove); tail.prev = n;
public Node(int v){ n.next = tail;
map2.put(toRemove, key); value = v; tail = n;
set = new HashSet<Integer>(); }else{
return true; } tail.set.add(val);
} map.put(val, tail);
public String toString(){ }
return false; return value + ":" + set.toString();
} } }
}
/** Get a random element from the collection. */
public int getRandom() { public class FrequentCollection { }
if(map1.size()==0)
return -1; HashMap<Integer, Node> map; /**
Node head, tail; * Removes a value from the collection.
if(map2.size()==1){ */
return map2.get(1); /** Initialize your data structure here. */ public void remove(int val) {
} public FrequentCollection() { Node n = map.get(val);
map = new HashMap<Integer, Node>(); n.set.remove(val);
return map2.get(r.nextInt(map2.size())+1); // nextInt() returns a random number in [0, n). }
} if(n.value==1){
} /** map.remove(val);
* Inserts a value to the collection. }else{
*/ n.prev.set.add(val);
public void insert(int val) { map.put(val, n.prev);
if(map.containsKey(val)){ }
Node n = map.get(val);
n.set.remove(val);
Program Creek 532 | 568 533 | 568 Program Creek 534 | 568
279 Design a Data Structure with Insert, Delete and GetMostFrequent of O(1)
set.remove(followeeId);
Program Creek 538 | 568 Program Creek 539 | 568 540 | 568
284 Twitter Codility Problem Max Binary Gap
}
pre = curr;
}
return len;
283 Single Number II 284 Twitter Codility Problem Max Binary Gap }
Time is O(log(n)).
Problem: Get maximum binary Gap.
283.1 Problem
For example, 9’s binary form is 1001, the gap is 2.
Given an array of integers, every element appears three times except for one. Find that single one.
284.1 Java Solution 1
283.2 Java Solution
An integer x & 1 will get the last digit of the integer.
This problem is similar to Single Number. public static int getGap(int N) {
int max = 0;
public int singleNumber(int[] A) {
int count = -1;
int ones = 0, twos = 0, threes = 0;
int r = 0;
for (int i = 0; i < A.length; i++) {
twos |= ones & A[i];
while (N > 0) {
ones ^= A[i];
// get right most bit & shift right
threes = ones & twos;
r = N & 1;
ones &= ~threes;
N = N >> 1;
twos &= ~threes;
}
if (0 == r && count >= 0) {
return ones;
count++;
}
}
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);
return n;
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;
while(!queue.isEmpty()){
return count==0;
int top = queue.remove();
}
for(int i=0; i<len; i++){
// if a course’s prerequisite can be satisfied by a course in queue
if(prerequisites[i][1]==top){ visit[i]=-1;
pCounter[prerequisites[i][0]]--; if(map.containsKey(i)){
if(pCounter[prerequisites[i][0]]==0){ for(int j: map.get(i)){
numNoPre++; if(!canFinishDFS(map, visit, j))
queue.add(prerequisites[i][0]); return false;
} } 295 Course Schedule II
} }
}
} visit[i]=1; This is an extension of Course Schedule. This time a valid sequence of courses is required as output.
Topological Sort Video from Coursera. If we use the BFS solution of Course Schedule, a valid sequence can easily be recorded.
Program Creek 556 | 568 Program Creek 557 | 568 558 | 568
295 Course Schedule II 296 Minimum Height Trees
if(leaves.size()==0){
for(int i=0; i<len; i++){ return result;
if(prerequisites[i][1]==c){ }
pCounter[prerequisites[i][0]]--;
if(pCounter[prerequisites[i][0]]==0){ while(n>2){
queue.add(prerequisites[i][0]); 296 Minimum Height Trees n = n-leaves.size();
numNoPre++;
} LinkedList<Integer> newLeaves = new LinkedList<Integer>();
} For a undirected graph with tree characteristics, we can choose any node as the root. The result graph is then
a rooted tree. Among all possible rooted trees, those with minimum height are called minimum height trees for(int l: leaves){
} (MHTs). Given such a graph, write a function to find all the MHTs and return a list of their root labels. int neighbor = graph.get(l).iterator().next();
} The graph contains n nodes which are labeled from 0 to n - 1. You will be given the number n and a list of graph.get(neighbor).remove(l);
undirected edges (each edge is a pair of labels). if(graph.get(neighbor).size()==1){
//return result You can assume that no duplicate edges will appear in edges. Since all edges are undirected, [0, 1] is the same newLeaves.add(neighbor);
if(numNoPre==numCourses){ as [1, 0] and thus will not appear together in edges. }
return result; }
Example 1:
}else{
return new int[0]; Given n = 4, edges = [[1, 0], [1, 2], [1, 3]] leaves = newLeaves;
} }
} 0
| return leaves;
1 }
/ \
2 3
return [1]
Program Creek 559 | 568 560 | 568 Program Creek 561 | 568
297 Graph Valid Tree
return true;
}
list.get(a).add(b);
public boolean validTree(int n, int[][] edges) { list.get(b).add(a);
HashMap<Integer, ArrayList<Integer>> map = new HashMap<Integer, ArrayList<Integer>>(); }
for(int i=0; i<n; i++){
ArrayList<Integer> list = new ArrayList<Integer>(); //use queue to traverse the graph
map.put(i, list); HashSet<Integer> visited = new HashSet<>();
} LinkedList<Integer> q = new LinkedList<>();
q.offer(0);
for(int[] edge: edges){
map.get(edge[0]).add(edge[1]); while(!q.isEmpty()){
map.get(edge[1]).add(edge[0]); int head = q.poll();
}
if(visited.contains(head)){
boolean[] visited = new boolean[n]; return false;
}
if(!helper(0, -1, map, visited))
return false; visited.add(head);
for(int i: map.get(curr)){
if(i!=parent && !helper(i, curr, map, visited)){ /**
return false; * Definition for undirected graph.
} * class UndirectedGraphNode {
} * int label;
queue.offer(node);
while(!queue.isEmpty()){
UndirectedGraphNode top = queue.poll();
map.put(top, new UndirectedGraphNode(top.label));
for(UndirectedGraphNode n: top.neighbors){
Program Creek 565 | 568 Program Creek 566 | 568 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