04/05/2022
Longest Common Prefix
https://leetcode.com/problems/longest-common-prefix/
Solutions:
horizontal scanning(from left to right)
vertical scanning(compare the ith char on all the elements each time)
divide and conquer
Binary search
Follow up
LCP called multiple times frequently
use a trie
node path must only have one child element
stop at the “isWord” node
must match the character
Letter Combinations of a phone number
https://leetcode.com/problems/letter-combinations-of-a-phone-number/
Solutions:
Remove Nth Node From End of List
https://leetcode.com/problems/remove-nth-node-from-end-of-list/
Solutions
two pass, one to find the length, the other to find the first Node.
Generate Parentheses
https://leetcode.com/problems/generate-parentheses/
DFS(permutation: only allow certain paths when conditions met)
Closure Number: (To be reviewed)
swap nodes in pairs
https://leetcode.com/problems/swap-nodes-in-pairs/
set up loop invariant and keep them. prev, first, second.
remove element
https://leetcode.com/problems/remove-element/
Solutions
two pointer, slow fast pointer. copy over all the not equal elements
two pointer, opposite direction, reduce right pointer by one when equal.
implement strstr
https://leetcode.com/problems/implement-strstr/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public int strStr (String haystack, String needle) { int index = 0 ; char [] hays = haystack.toCharArray(); char [] needles = needle.toCharArray(); int i = 0 ; for (; i < hays.length; i++) { int j = 0 ; while (j < needles.length && i+j < hays.length && hays[i+j] == needles[j]) { j++; } if (j == needles.length) { return i; } } return -1 ; }
Find First and Last Position of Element in Sorted Array
https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/
solutions
binary search two ends. stop at two elements, because we might get into a dead loop.
Count and Say
https://leetcode.com/problems/count-and-say/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public String countAndSay (int n) { if (n == 1 ) { return "1" ; } String prev = "11" ; for (int i = 1 ; i < n - 1 ; i++) { prev = convert(prev); } return prev; } private String convert (String prev) { StringBuilder sb = new StringBuilder (); char [] chars = prev.toCharArray(); for (int i = 0 ; i < chars.length; i++) { char c = chars[i]; int count = 1 ; while (i+1 < chars.length && chars[i+1 ] == c) { count++; i++; } sb.append(count); sb.append(c); } return sb.toString(); }
Combination Sum
https://leetcode.com/problems/combination-sum/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class Solution { List<List<Integer>> res = new ArrayList <List<Integer>>(); public List<List<Integer>> combinationSum (int [] candidates, int target) { combine(candidates, 0 , target, new ArrayList <Integer>()); return res; } private void combine (int [] candidates, int level, int target, List<Integer> list) { if (target == 0 ) { res.add(list); return ; } if (level == candidates.length) { return ; } int count = 0 ; while (count * candidates[level] <= target) { List<Integer> copy = new ArrayList <Integer>(list); for (int i = 0 ; i < count; i++) { copy.add(candidates[level]); } combine(candidates, level + 1 , target - count * candidates[level], copy); count++; } } }
Jump game II
https://leetcode.com/problems/jump-game-ii/
Solutions
04/06/2022
Permutations
https://leetcode.com/problems/permutations/
Solutions
key point: fill each spot with available elements
dps
swap swap
Combination Sum II
https://leetcode.com/problems/combination-sum-ii/
Solutions
think of each element can only show up on a level repeated times
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 List<List<Integer>> res = new ArrayList <List<Integer>>(); public List<List<Integer>> combinationSum2 (int [] candidates, int target) { int sum = Arrays.stream(candidates).sum(); if (target > sum) { return res; } Arrays.sort(candidates); dps(candidates, target, 0 , new ArrayList <Integer>()); return res; } private void dps (int [] candidates, int target, int idx, List<Integer> list) { if (target == 0 ) { res.add(list); return ; } if (idx >= candidates.length) { return ; } int nextUnique = idx + 1 ; int count = 1 ; while (nextUnique < candidates.length && candidates[nextUnique] == candidates[idx]) { nextUnique++; count++; } for (int i = 0 ; i <= count; i++) { int rem = target - i * candidates[idx]; if (rem < 0 ) return ; List<Integer> copy = new ArrayList <Integer>(list); for (int j = 0 ; j < i; j++) { copy.add(candidates[idx]); } dps(candidates, rem, nextUnique, copy); } }
Permutations II (with duplicated elements)
https://leetcode.com/problems/permutations-ii/
Solutions
sort array
use a set to check on each level to see if the element was added already
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 List<List<Integer>> res = new ArrayList <List<Integer>>(); public List<List<Integer>> permuteUnique (int [] nums) { Arrays.sort(nums); permute(nums, 0 ); return res; } private void permute (int [] nums, int idx) { int n = nums.length; if (idx == n) { List<Integer> list = new ArrayList <Integer>(); for (int i = 0 ; i < n; i++) { list.add(nums[i]); } res.add(list); return ; } HashSet<Integer> set = new HashSet (); for (int k = idx; k < n; k++) { if (set.contains(nums[k])) { continue ; } swap(nums, idx, k); permute(nums, idx + 1 ); swap(nums, idx, k); set.add(nums[k]); } } private void swap (int [] nums, int i, int j) { int temp = nums[j]; nums[j] = nums[i]; nums[i] = temp; }
Power(x, n)
https://leetcode.com/problems/powx-n/
Solutions
cut in half each time, dp to remember half.
check negative and odd situation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public double myPow (double x, int n) { if (n < 0 ) { return 1 / helper(x, -n); } return helper(x, n); } public double helper (double x, int n) { if (n == 0 ) { return 1 ; } if (n == 1 ) { return x; } int half = n / 2 ; double halfValue = helper(x, half); int mod = n % 2 ; if (mod != 0 ) { return halfValue * halfValue * x; } return halfValue * halfValue; }
Spiral Matrix
https://leetcode.com/problems/spiral-matrix/
Solutions
separate directions
check boundary
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 public List<Integer> spiralOrder (int [][] matrix) { List<Integer> res = new ArrayList <Integer>(); int row = matrix.length; int col = matrix[0 ].length; int layers = (Math.min(row, col) + 1 ) / 2 ; for (int i = 0 ; i < layers; i++) { int innerRow = row - 2 * i; int innerCol = col - 2 * i; if (innerCol == 1 ) { for (int j = 0 ; j < innerRow; j++) { res.add(matrix[i + j][i]); } return res; } if (innerRow == 1 ) { for (int j = 0 ; j < innerCol; j++) { res.add(matrix[i][i + j]); } return res; } for (int j = 0 ; j < innerCol - 1 ; j++) { res.add(matrix[i][i + j]); } if (col - i - 1 > 0 ) { for (int j = 0 ; j < innerRow - 1 ; j++) { res.add(matrix[i + j][col - i -1 ]); } } if (row - i - 1 > 0 ) { for (int j = 0 ; j < innerCol - 1 ; j++) { res.add(matrix[row - i - 1 ][col - i - 1 - j]); } } if (i < col) { for (int j = 0 ; j < innerRow - 1 ; j++) { res.add(matrix[row - i - 1 - j][i]); } } } return res; }
Jump Game
https://leetcode.com/problems/jump-game/
Solutions
go from left to right
remember last reachable element
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public boolean canJump (int [] nums) { int n = nums.length; if (n <= 1 ) return true ; int last = 0 ; for (int i = 0 ; i < n; i++) { if (i > last) return false ; int next = nums[i] + i; if (next >= n - 1 ) { return true ; } last = Math.max(next, last); } return false ; }
Spiral Matrix II (fill out a matrix spirally )
https://leetcode.com/problems/spiral-matrix-ii/
Solutions
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public int [][] generateMatrix(int n) { int total = n * n; int count = 1 ; int layers = (n + 1 ) / 2 ; int [][] res = new int [n][n]; for (int i = 0 ; i < layers; i++) { int l = n - 2 * i; if (l == 1 ) { res[i][i] = count; } for (int j = 0 ; j < l - 1 ; j++) { res[i][i + j] = count++; } for (int j = 0 ; j < l - 1 ; j++) { res[i + j][n - i - 1 ] = count++; } for (int j = 0 ; j < l - 1 ; j++) { res[n - i - 1 ][n - i - 1 - j] = count++; } for (int j = 0 ; j < l - 1 ; j++) { res[n - i - 1 - j][i] = count++; } } return res; }
unique paths
https://leetcode.com/problems/unique-paths/
Solutions
dp
basic math: choose m - 1 or n - 1 from m - n - 2
unique paths II (with obstacles)
https://leetcode.com/problems/unique-paths-ii/
solutions
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public int uniquePathsWithObstacles (int [][] obstacleGrid) { int m = obstacleGrid.length; int n = obstacleGrid[0 ].length; if (obstacleGrid[0 ][0 ] == 1 || obstacleGrid[m-1 ][n-1 ] == 1 ) return 0 ; int [][] dp = new int [m][n]; dp[0 ][0 ] = 1 ; for (int i = 0 ; i < m; i++) { for (int j = 0 ; j < n; j++) { if (i == 0 && j == 0 ) continue ; if (obstacleGrid[i][j] == 1 ) { dp[i][j] = 0 ; } else { int left = j == 0 ? 0 : dp[i][j-1 ]; int up = i == 0 ? 0 : dp[i - 1 ][j]; dp[i][j] = left + up; } } } return dp[m-1 ][n-1 ]; }
Minimum path sum
https://leetcode.com/problems/minimum-path-sum/
Solutions
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public int minPathSum (int [][] grid) { int m = grid.length; int n = grid[0 ].length; int [][] dp = new int [m][n]; dp[0 ][0 ] = grid[0 ][0 ]; for (int i = 0 ; i < m; i++) { for (int j = 0 ; j < n; j++) { if (i == 0 && j == 0 ) continue ; int left = j == 0 ? Integer.MAX_VALUE : dp[i][j-1 ]; int up = i == 0 ? Integer.MAX_VALUE : dp[i - 1 ][j]; dp[i][j] = Math.min(left, up) + grid[i][j]; } } return dp[m - 1 ][n - 1 ]; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public int minPathSum (int [][] grid) { int m = grid.length; int n = grid[0 ].length; int [] dp = new int [n]; dp[0 ] = grid[0 ][0 ]; for (int i = 0 ; i < m; i++) { for (int j = 0 ; j < n; j++) { if (i == 0 && j == 0 ) continue ; if (j == 0 ) { dp[j] = dp[j] + grid[i][j]; continue ; } int left = j == 0 ? Integer.MAX_VALUE : dp[j - 1 ]; int up = i == 0 ? Integer.MAX_VALUE : dp[j]; dp[j] = Math.min(left, up) + grid[i][j]; } } return dp[n - 1 ]; }
Set Matrix Zeros
https://leetcode.com/problems/set-matrix-zeroes/
solutions
use two sets
use first column and first row as marker
search a 2d matrix
https://leetcode.com/problems/search-a-2d-matrix/
Solutions
get row and col like: mid / n; mid % n;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public boolean searchMatrix (int [][] matrix, int target) { int m = matrix.length; int n = matrix[0 ].length; int l = 0 , r = m * n - 1 ; while (l <= r) { int mid = l + (r - l)/2 ; int row = mid / n; int col = mid % n; if (matrix[row][col] == target) { return true ; } if (matrix[row][col] > target) { r = mid - 1 ; } else { l = mid + 1 ; } } return false ; }
04/07/2022
Sort color
https://leetcode.com/problems/sort-colors/
Solutions
quicksort O(NlogN) (more general)
O(N), one pass solution
loop invariants:
three pointers, left i and right j, and cur
left elements of i are all zeros
right elements of j are all twos
elements between i and j are all ones including i and j (this is not needed)
initialization: start at cur = 0, i = 0, j = nums.length -1;
maintenance:
if nums[cur] = 0, move it to the left of i, so swap with i and then move i to the right, then move cur to the right by one too.
if nums[cur] = 2, move it to the right of j, so swap with j and then move j to the left.
if nums[cur] = 1, ignore i or j, move cur to the right by one.
termination: cur > j
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public void sortColors (int [] nums) { int i = 0 , j = nums.length -1 , cur = 0 ; while (cur <= j) { if (nums[cur] == 2 ) { swap(nums, cur, j); j--; continue ; } if (nums[cur] == 0 ) { swap(nums, cur, i); i++; cur++; continue ; } cur++; } } private void swap (int [] nums, int i, int j) { int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; }
Subsets
https://leetcode.com/problems/subsets/
solutions
backtracking (needs review)
dps, each level with or without the current element
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution { List<List<Integer>> res = new ArrayList <List<Integer>>(); public List<List<Integer>> subsets (int [] nums) { dps(nums, 0 , new ArrayList <Integer>()); return res; } private void dps (int [] nums, int idx, List<Integer> list) { if (idx == nums.length) { res.add(list); return ; } List<Integer> copy = new ArrayList <Integer>(list); dps(nums, idx + 1 , copy); List<Integer> copy2 = new ArrayList <Integer>(list); copy2.add(nums[idx]); dps(nums, idx + 1 , copy2); } }
Word search
https://leetcode.com/problems/word-search/
solutions
mark visited grid ‘#’ and then change it back after dps
pruning before dps would save time:
check if word’s length is longer than total number of elements in grid
check if there’s any element that’s not in the grid
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class Solution { public boolean exist (char [][] board, String word) { int m = board.length; int n = board[0 ].length; if (word.length() > m * n) return false ; HashSet<Character> uniqueChars = new HashSet (); for (int i = 0 ; i < m; i++) { for (int j = 0 ; j < n; j++) { uniqueChars.add(board[i][j]); } } for (int i = 0 ; i < word.length(); i++) { if (!uniqueChars.contains(word.charAt(i))) { return false ; } } for (int i = 0 ; i < m; i++) { for (int j = 0 ; j < n; j++) { if (board[i][j] == word.charAt(0 )) { boolean exist = checkWord(board, i, j, word, 0 ); if (exist) return true ; } } } return false ; } private boolean checkWord (char [][] board, int i, int j, String word, int idx) { if (i < 0 || j < 0 || i >= board.length || j >= board[0 ].length) return false ; if (board[i][j] == word.charAt(idx)){ if (idx == word.length() - 1 ) { return true ; } board[i][j] = '#' ; boolean up = checkWord(board, i - 1 , j, word, idx + 1 ); boolean left = checkWord(board, i, j - 1 , word, idx + 1 ); boolean down = checkWord(board, i + 1 , j, word, idx + 1 ); boolean right = checkWord(board, i, j + 1 , word, idx + 1 ); board[i][j] = word.charAt(idx); return up || left || down || right; } return false ; } }
Remove duplicates from sorted array II
https://leetcode.com/problems/remove-duplicates-from-sorted-array-ii/
Solutions
copy the last two elements of its kind instead of the first two because it might be overriden.
1 2 3 4 5 6 7 8 9 10 11 12 class Solution { public int removeDuplicates (int [] nums) { int i = 0 , j = 0 ; for (; j < nums.length; j++) { if (j + 2 >= nums.length || nums[j] != nums[j + 2 ]) { nums[i] = nums[j]; i++; } } return i; } }
#04/08/2022
search in rotated sorted array
https://leetcode.com/problems/search-in-rotated-sorted-array/
solutions
S1. find the pivot first, then binary search one of them
S2. one binary search, add more conditions to move left or right
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 class Solution { public int search (int [] nums, int target) { int m = nums.length; if (m == 0 ) return -1 ; int first = nums[0 ]; if (target == first) return 0 ; int start = 0 , end = m - 1 ; int last = 0 ; while (start <= end) { int mid = start + (end - start) / 2 ; if (nums[mid] == target) return mid; if (mid + 1 < m && nums[mid] > nums[mid + 1 ]) { last = mid; break ; } if (nums[mid] >= first){ start = mid + 1 ; } else { end = mid - 1 ; } } if (target > first) { return binarySearch(nums, 0 , last == 0 ? m - 1 : last, target); } else { return binarySearch(nums, last + 1 , m - 1 , target); } } private int binarySearch (int [] nums, int l, int r, int target) { while (l <= r) { int mid = l + (r - l) / 2 ; if (nums[mid] == target) return mid; if (nums[mid] > target) { r = mid - 1 ; } else { l = mid + 1 ; } } return -1 ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class Solution { public int search (int [] nums, int target) { int left = 0 ; int right = nums.length-1 ; while (left<=right) { int mid = left + (right-left)/2 ; if (target == nums[mid]) { return mid; } if (nums[mid] <= nums[right]) { if (target>nums[mid]&&target<=nums[right]) { left = mid +1 ; }else { right = mid -1 ; } }else { if (target<nums[mid]&&target>=nums[left]){ right = mid - 1 ; }else { left = mid + 1 ; } } } return -1 ; } }
Search in Rotated Sorted Array II
https://leetcode.com/problems/search-in-rotated-sorted-array-ii/
Solutions
same as the first one except when trying to locate pivot, check which side the pivot it located in by checking to the right or left
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 class Solution { public boolean search (int [] nums, int target) { int m = nums.length; if (m == 0 ) return false ; int first = nums[0 ]; if (target == first) return true ; int start = 0 , end = m - 1 ; int last = 0 ; while (start <= end) { int mid = start + (end - start) / 2 ; if (nums[mid] == target) return true ; if (mid + 1 < m && nums[mid] > nums[mid + 1 ]) { last = mid; break ; } if (nums[mid] == first) { int count = mid + 1 ; while (count < m && nums[count] == nums[mid]) { count++; } if (count == m) { end = mid - 1 ; } else { start = mid + 1 ; } } else if (nums[mid] > first){ start = mid + 1 ; } else { end = mid - 1 ; } } if (target > first) { return binarySearch(nums, 0 , last == 0 ? m - 1 : last, target); } else { return binarySearch(nums, last + 1 , m - 1 , target); } } private boolean binarySearch (int [] nums, int l, int r, int target) { while (l <= r) { int mid = l + (r - l) / 2 ; if (nums[mid] == target) return true ; if (nums[mid] > target) { r = mid - 1 ; } else { l = mid + 1 ; } } return false ; } }
Remove Duplicates from Sorted List
https://leetcode.com/problems/remove-duplicates-from-sorted-list/
Solutions
two pointer, prev and cur
loop invariants:
everything left to prev including prev are all unique
move cur to the right without connecting if it’s the same as prev
Remove Duplicates from Sorted List II
https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii/solution/
Solutions
Sentinel head solution: dummy head, because we are not sure what’s the head, so we check which is head first, then append it to the dummy head.
loop invariants:
everything left to last are correct answer
set last.next to the first element of its kind, and then override it if it’s not the only element of its kind
move “last” if current element is different than the last element
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Solution { public ListNode deleteDuplicates (ListNode head) { if (head == null || head.next == null ) return head; ListNode dummy = new ListNode (0 , head); ListNode last = dummy; ListNode cur = head; while (cur != null ) { if (cur.next != null && cur.val == cur.next.val) { while (cur.next != null && cur.val == cur.next.val) { cur = cur.next; } last.next = cur.next; } else { last = last.next; } cur = cur.next; } return dummy.next; } }
subsets ii
https://leetcode.com/problems/subsets-ii/submissions/
Solutions
skip the dps level for the same elements. so for duplicated levels, add different number of elements there
trick: set count to 1, and loop at least 0 and 1. if ther’s more, loop extra.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution { List<List<Integer>> res = new ArrayList <List<Integer>>(); public List<List<Integer>> subsetsWithDup (int [] nums) { Arrays.sort(nums); dps(nums, 0 , new ArrayList <Integer>()); return res; } private void dps (int [] nums, int idx, List<Integer> list) { int m = nums.length; if (idx == m) { res.add(list); return ; } int count = 1 ; while (idx+count < m && nums[idx] == nums[idx + count]) { count++; } List<Integer> copy = new ArrayList <Integer>(list); for (int i = 0 ; i <= count; i++) { dps(nums, idx + count, copy); copy = new ArrayList <Integer>(copy); copy.add(nums[idx]); } } }
Reverse LinkedList II
https://leetcode.com/problems/reverse-linked-list-ii/
trick part, remember the element before the reversal, and also the element where the reversal stops.
Solutions
use dummy head, because we don’t know the new head ahead of time
record “newHead” and “newTail” and “before”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 class Solution { public ListNode reverseBetween (ListNode head, int left, int right) { ListNode dummy = new ListNode (); dummy.next = head; ListNode before = head; ListNode cur = head; int count = 1 ; while (cur != null ) { if (count == left - 1 ) { before = cur; } else if (count == left) { ListNode newHead = head; ListNode newTail = head; ListNode reverseHead = cur; newTail = cur; ListNode prev = null ; while (count <= right) { if (count == right) { newHead = reverseHead; } ListNode next = reverseHead.next; reverseHead.next = prev; prev = reverseHead; count++; reverseHead = next; } newTail.next = reverseHead; if (left == 1 ) { dummy.next = newHead; } else { before.next = newHead; } return dummy.next; } cur = cur.next; count++; } return dummy.next; } }
Restore IP Address
https://leetcode.com/problems/restore-ip-addresses/
Solutions
backtrack (my prefered dps way)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class Solution { List<String> res = new ArrayList <String>(); public List<String> restoreIpAddresses (String s) { char [] chars = s.toCharArray(); dps(chars, 0 , 1 , "" ); return res; } private void dps (char [] chars, int idx, int count, String s) { int m = chars.length; if (count == 4 ) { if (idx >= m) return ; int lastNumber = 0 ; if (Character.getNumericValue(chars[idx]) == 0 && idx != m-1 ) return ; while (idx < m) { int tempNum = Character.getNumericValue(chars[idx]); lastNumber = lastNumber * 10 + tempNum; idx++; if (lastNumber > 255 ) return ; } res.add(s + lastNumber); return ; } if (idx == m) return ; int num = Character.getNumericValue(chars[idx]); if (num == 0 ) { dps(chars, ++idx, count+1 , s + num + "." ); return ; }; while (idx < m && num <= 255 ) { dps(chars, ++idx, count+1 , s + num + "." ); if (idx >=m) return ; int tempNum = Character.getNumericValue(chars[idx]); num = num * 10 + tempNum; } } }
Flip String to Monotone increasing
https://leetcode.com/problems/flip-string-to-monotone-increasing/
Solutions
s1. check how many 0s before element and how many zeros after element i using prefix sum
s2. very tricky thought process, dp thought process too
if current element is 1
not flip it, stays 1, so flips[i] = flips[i - 1]
flip it to 0, flips = flips[i] = previous ones + 1
get min
if current element is 0
not flipping it, stay 0, flips[i] = flips[i - 1]
flip it to 1, then flips[i] = flips[i - 1] + 1, because previous doesnt’ need to change.
get min
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Solution { public int minFlipsMonoIncr (String s) { int one = 0 ; int flip = 0 ; for (int i=0 ;i<s.length();i++) { if (s.charAt(i)=='1' ) { one++; } else { flip++; } flip = Math.min(one,flip); } return flip; } }
Count Unique Characters of All Substrings of a Given String
https://leetcode.com/problems/count-unique-characters-of-all-substrings-of-a-given-string/
Solutions
Sum of Subarray Ranges
https://leetcode.com/problems/sum-of-subarray-ranges/
Solutions
#04/10/2022
LRU Cache
https://leetcode.com/problems/lru-cache/
Solutions
Node has “prev” and “next” pointer so the removal is easier
Have two dummy node “head” and “tail”, change everything in between so that we don’t have check if it’s the head or tail
separate methods to smaller ones
popHead
appendToEnd
removeNode
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 class LRUCache { class Node { int key = 0 , val = 0 ; Node next, prev; public Node (int key, int val) { this .key = key; this .val = val; } public Node () { this (0 , 0 ); } } HashMap<Integer, Node> map; int capacity = 0 ; Node head, tail; public LRUCache (int capacity) { this .capacity = capacity; this .map = new HashMap (); this .head = new Node (); this .tail = new Node (); head.next = tail; tail.prev = head; } public int get (int key) { if (!map.containsKey(key)) return -1 ; Node node = map.get(key); moveNodeToEnd(node); return node.val; } public void put (int key, int value) { if (map.containsKey(key)) { Node node = map.get(key); node.val = value; moveNodeToEnd(node); return ; } if (map.size() == capacity) removeHead(); Node node = new Node (key, value); map.put(key, node); appendNode(node); } private void moveNodeToEnd (Node node) { removeNode(node); appendNode(node); } private void removeHead () { head = head.next; head.prev = null ; map.remove(head.key); head.key = 0 ; head.val = 0 ; } private void appendNode (Node node) { Node prev = tail.prev; prev.next = node; node.prev = prev; tail.prev = node; node.next = tail; } private void removeNode (Node node) { Node prev = node.prev; Node next = node.next; prev.next = next; next.prev = prev; node.next = null ; node.prev = null ; } }
Count Binary Substrings
https://leetcode.com/problems/count-binary-substrings/
Solutions
count ones and zeros, take min of the two consecutive groups
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution { public int countBinarySubstrings (String s) { if (s.length() == 0 ) return 0 ; int prev = 0 ; int cur = 1 ; int res = 0 ; for (int i = 1 ; i < s.length(); i++) { if (s.charAt(i) == s.charAt(i - 1 )) { cur++; } else { res += Math.min(prev, cur); prev = cur; cur = 1 ; } } return res + Math.min(prev, cur); } }
The kth Factor of n
https://leetcode.com/problems/the-kth-factor-of-n/
Solutions
O(sqrt(N))
S1. remember both halves.
S2. check if the k is in the first half, only save divisors
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Solution { public int kthFactor (int n, int k) { int count = 1 ; List<Integer> secondHalf = new ArrayList (); int i = 1 ; int j = n; do { int mod = n % i; if (mod == 0 ) { if (k == 1 ) { return i; } j = n / i; if (i != j) { secondHalf.add(j); } k--; } i++; } while (i < j); int size = secondHalf.size(); if (k > size) return -1 ; return secondHalf.get(size - k); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Solution { public int kthFactor (int n, int k) { int count = 1 ; List<Integer> firstHalf = new ArrayList (); List<Integer> secondHalf = new ArrayList (); int i = 1 ; int j = n; do { int mod = n % i; if (mod == 0 ) { firstHalf.add(i); j = n / i; if (i != j) { secondHalf.add(j); } } i++; } while (i < j); int size1 = firstHalf.size(); if (k <= size1) return firstHalf.get(k - 1 ); int size2 = secondHalf.size(); if (k > size1 + size2) return -1 ; return secondHalf.get(size2 - (k - size1)); } }
valid palindrome II
https://leetcode.com/problems/valid-palindrome-ii/
Solutions
try both substrings generated by deleting each of the mismatched pair
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Solution { public boolean validPalindrome (String s) { int i = 0 ; int j = s.length() - 1 ; int count = 1 ; while (i < j) { if (s.charAt(i) != s.charAt(j)) { return checkPalindrom(s, i, j-1 ) || checkPalindrom(s, i+1 , j); } i++; j--; } return true ; } private boolean checkPalindrom (String s, int i, int j) { while (i < j) { if (s.charAt(i) != s.charAt(j)) { return false ; } i++; j--; } return true ; } }
Maximum Units on a Truck
https://leetcode.com/problems/maximum-units-on-a-truck/
Solutions
sort the array and pick from the bigger box first.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Solution { public int maximumUnits (int [][] boxTypes, int truckSize) { Arrays.sort(boxTypes, (int [] a, int [] b) -> b[1 ] - a[1 ]); int remaining = truckSize; int total = 0 ; for (int i = 0 ; i < boxTypes.length; i++) { if (remaining <= 0 ) return total; total += Math.min(remaining, boxTypes[i][0 ]) * boxTypes[i][1 ]; remaining -= boxTypes[i][0 ]; } return total; } }
Find Winner on a Tic Tac Toe Game
https://leetcode.com/problems/find-winner-on-a-tic-tac-toe-game/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 class Solution { public String tictactoe (int [][] moves) { int [][] board = new int [3 ][3 ]; for (int i = 0 ; i < moves.length; i++) { int num = 1 ; if (i % 2 == 0 ) { num = -1 ; } board[moves[i][0 ]][moves[i][1 ]] = num; } for (int i = 0 ; i < 3 ; i++) { int num = board[i][0 ]; if (num == 0 ) continue ; boolean win = true ; for (int j = 1 ; j < 3 ; j++) { if (board[i][j] != num) { win = false ; break ; } } if (win) { return num == -1 ? "A" : "B" ; } } for (int i = 0 ; i < 3 ; i++) { int num = board[0 ][i]; if (num == 0 ) continue ; boolean win = true ; for (int j = 1 ; j < 3 ; j++) { if (board[j][i] != num) { win = false ; break ; } } if (win) { return num == -1 ? "A" : "B" ; } } if (board[1 ][1 ] != 0 &&((board[0 ][0 ] == board[1 ][1 ] && board[1 ][1 ] == board[2 ][2 ]) || (board[0 ][2 ] == board[1 ][1 ] && board[1 ][1 ] == board[2 ][0 ]))) { return board[1 ][1 ] == -1 ? "A" : "B" ; } if (moves.length < 9 ) { return "Pending" ; } return "Draw" ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 class Solution { public String tictactoe (int [][] moves) { int n = 3 ; int [] rows = new int [n], cols = new int [n]; int diag = 0 , anti_diag = 0 ; int player = 1 ; for (int [] move : moves){ int row = move[0 ], col = move[1 ]; rows[row] += player; cols[col] += player; if (row == col){ diag += player; } if (row + col == n - 1 ){ anti_diag += player; } if (Math.abs(rows[row]) == n || Math.abs(cols[col]) == n || Math.abs(diag) == n || Math.abs(anti_diag) == n){ return player == 1 ? "A" : "B" ; } player *= -1 ; } return moves.length == n * n ? "Draw" : "Pending" ; } }
Sum of Subarray Minimums
https://leetcode.com/problems/sum-of-subarray-minimums/
Solutions
count the contributions of each element being the smallest element
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution { public int sumSubarrayMins (int [] arr) { int l = arr.length; if (l == 0 ) return 0 ; Stack<Integer> s = new Stack (); long res = 0 ; s.add(0 ); int mod = (int )(Math.pow(10 , 9 ) + 7 ); for (int i = 1 ; i <= l; i++) { while (!s.isEmpty() && arr[s.peek()] > (i == l? 0 : arr[i])) { int j = s.pop(); int k = s.isEmpty() ? -1 :s.peek(); res += (long )arr[j] * (j - k) * (i - j); res = res % mod; } s.push(i); } return (int )res; } }
Minimum Swaps to Group All 1’s Together
https://leetcode.com/problems/minimum-swaps-to-group-all-1s-together/
Solutions
sliding window O(n) time, O(1) space
prefix sum: O(n) time, O(n) space
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution { public int minSwaps (int [] data) { int ones = Arrays.stream(data).sum(); int cnt_one = 0 , max_one = 0 ; int left = 0 , right = 0 ; while (right < data.length) { cnt_one += data[right++]; if (right - left > ones) { cnt_one -= data[left++]; } max_one = Math.max(max_one, cnt_one); } return ones - max_one; } }
My attempt 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Solution { public int minSwaps (int [] data) { int l = data.length; int [] sum = new int [l]; sum[0 ] = data[0 ]; for (int i = 1 ; i < l; i++) { sum[i] = data[i] + sum[i - 1 ]; } if (sum[l - 1 ] < 2 || sum[l - 1 ] == l) { return 0 ; } int min = Integer.MAX_VALUE; for (int i = 0 ; i <= l - sum[l - 1 ]; i++) { int lastIndex = i + sum[l-1 ] - 1 ; int localMin = sum[l - 1 ] - sum[lastIndex] + sum[i]; if (data[i] == 1 ) { localMin--; } min = Math.min(localMin, min); } return min; } }
Maximum Length of Subarray With Positive Product
https://leetcode.com/problems/maximum-length-of-subarray-with-positive-product/
Solutions
record the first negative number’s index(my solution)
dry run
My solution 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class Solution { public int getMaxLen (int [] nums) { int negatives = 0 ; int max = 0 ; int count = 0 ; int firstNegative = -1 ; for (int i = 0 ; i < nums.length; i++) { if (nums[i] == 0 ) { negatives = 0 ; count = 0 ; firstNegative = -1 ; continue ; } if (nums[i] < 0 ) { if (firstNegative == -1 ) { firstNegative = i; } negatives++; } if (negatives % 2 == 1 && firstNegative != -1 ) { max = Math.max(max, i - firstNegative); } else if (negatives % 2 == 0 ) { max = Math.max(max, count + 1 ); } count++; } return max; } }
dry run link 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution { public int getMaxLen (int [] nums) { int positive = 0 , negative = 0 ; int ans = 0 ; for (int x : nums) { if (x == 0 ) { positive = 0 ; negative = 0 ; } else if (x > 0 ) { positive++; negative = negative == 0 ? 0 : negative+1 ; } else { int temp = positive; positive = negative == 0 ? 0 : negative+1 ; negative = temp+1 ; } ans = Math.max(ans, positive); } return ans; } }
Nested List Weight Sum
https://leetcode.com/problems/nested-list-weight-sum/
solutions
Coding tricks 1 2 Queue<NestedInteger> queue = new LinkedList <NestedInteger>(nestedList); queue.addAll(ni.getList());
Lowest Common Ancestor with parent pointer
https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree-iii/
Solutions
S1. Set
S2. traverse both paths
Set Solution 1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Solution { public Node lowestCommonAncestor (Node p, Node q) { HashSet<Integer> set = new HashSet (); while (p != null ) { set.add(p.val); p = p.parent; } while (q != null ) { if (set.contains(q.val)) return q; q = q.parent; } return q; } }
travers both paths solution 1 2 3 4 5 6 7 8 9 10 11 class Solution { public Node lowestCommonAncestor (Node p, Node q) { Node n1 = p; Node n2 = q; while (n1 != n2) { n1 = n1.parent == null ? q : n1.parent; n2 = n2.parent == null ? p : n2.parent; } return n1; } }
Smallest Common Region
https://leetcode.com/problems/smallest-common-region/
Solutions
use a tree structure to record the parent of each node(my method)
use a hashMap to record the parent
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 class Node { String val = "" ; public Node (String val) { this .val = val; } Node parent = null ; } class Solution { public String findSmallestRegion (List<List<String>> regions, String region1, String region2) { HashMap<String, Node> map = new HashMap (); for (List<String> region: regions) { Node parentNode = map.getOrDefault(region.get(0 ), new Node (region.get(0 ))); map.put(region.get(0 ), parentNode); for (int i = 1 ; i < region.size(); i++) { Node child = map.getOrDefault(region.get(i), new Node (region.get(i))); map.put(region.get(i), child); child.parent = parentNode; } } Node n1 = map.get(region1); Node n2 = map.get(region2); HashSet<String> paths = new HashSet (); while (n1 != null ) { paths.add(n1.val); n1 = n1.parent; } while (n2 != null ) { if (paths.contains(n2.val)) return n2.val; n2 = n2.parent; } return "" ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution { public String findSmallestRegion (List<List<String>> regions, String region1, String region2) { HashMap<String, String> map = new HashMap (); for (List<String> region: regions) { for (int i = 1 ; i < region.size(); i++) { map.put(region.get(i), region.get(0 )); } } HashSet<String> paths = new HashSet (); while (region1 != null ) { paths.add(region1); region1 = map.get(region1); } while (region2 != null ) { if (paths.contains(region2)) return region2; region2 = map.get(region2); } return "" ; } }
without set 1 2 3 4 5 6 7 8 9 10 11 12 Map<String, String> parent = new HashMap <>(); for (List<String> rs: regions) { for (int j = 1 ; j < rs.size(); j++) { parent.put(rs.get(j), rs.get(0 )); } } String p1 = region1, p2 = region2;while (!p1.equals(p2)) { p1 = parent.getOrDefault(p1, region2); p2 = parent.getOrDefault(p2, region1); } return p1;
Cinema seat allocation
https://leetcode.com/problems/cinema-seat-allocation/submissions/
Solutions
only iterate reserved rows
S1. use a boolean array for each row
S2. use a set for each row
S2. use an integer for the row, use bitwise operations
1.5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class Solution { public int maxNumberOfFamilies (int n, int[][] reservedSeats ) { HashMap <Integer , boolean[]> reservedRows = new HashMap (); for (int[] seat : reservedSeats) { boolean[] cols = reservedRows.getOrDefault (seat[0 ] - 1 , new boolean[10 ]); cols[seat[1 ] - 1 ] = true ; reservedRows.put (seat[0 ] - 1 , cols); } int result = 2 * (n - reservedRows.size ()); for (boolean[] cols : reservedRows.values ()) { if (!cols[1 ] && !cols[2 ] && !cols[3 ] && !cols[4 ]) { cols[3 ] = true ; cols[4 ] = true ; result++; } if (!cols[3 ] && !cols[4 ] && !cols[5 ] && !cols[6 ]) { cols[5 ] = true ; cols[6 ] = true ; result++; } if (!cols[5 ] && !cols[6 ] && !cols[7 ] && !cols[8 ]) { result++; } } return result; } }
S2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class Solution { public int maxNumberOfFamilies (int n, int [][] reservedSeats) { HashMap<Integer, HashSet<Integer>> reservedRows = new HashMap (); for (int [] seat: reservedSeats) { HashSet<Integer> cols = reservedRows.getOrDefault(seat[0 ] - 1 , new HashSet <Integer>()); cols.add(seat[1 ] - 1 ); reservedRows.put(seat[0 ] - 1 , cols); } int result = 2 * (n - reservedRows.size()); for (HashSet<Integer> cols : reservedRows.values()) { if (!cols.contains(1 ) && !cols.contains(2 ) && !cols.contains(3 ) && !cols.contains(4 )) { cols.add(3 ); cols.add(4 ); result++; } if (!cols.contains(3 ) && !cols.contains(4 ) && !cols.contains(5 ) && !cols.contains(6 )) { cols.add(5 ); cols.add(6 ); result++; } if (!cols.contains(5 ) && !cols.contains(6 ) && !cols.contains(7 ) && !cols.contains(8 )) { result++; } } return result; } }
S3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Solution { public int maxNumberOfFamilies (int n, int [][] reservedSeats) { HashMap<Integer, Integer> reservedRows = new HashMap (); for (int [] seat: reservedSeats) { reservedRows.put(seat[0 ], reservedRows.getOrDefault(seat[0 ], 0 ) | (1 << seat[1 ])); } int result = 2 * (n - reservedRows.size()); for (int cols : reservedRows.values()) { boolean reserved = false ; if ((cols & 60 ) == 0 ) { reserved = true ; result++; } if ((cols & 960 ) == 0 ) { reserved = true ; result++; } if (!reserved && (cols & 240 ) == 0 ) { result++; } } return result; } }
Distribute Coins in Binary Tree
https://leetcode.com/problems/distribute-coins-in-binary-tree/
Solutions
divide and conquer, only look at two layers (parent, left, right)
return excess number of coins up each level, as it levels, it increase the total answer
record answer on each level.
overall way of thinking, bottom up solution, move excess number as soon as we find it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Solution { private int ans; public int distributeCoins (TreeNode root) { dfs(root); return ans; } private int dfs (TreeNode root) { if (root == null ) return 0 ; int l = dfs(root.left); int r = dfs(root.right); ans += Math.abs(l) + Math.abs(r); return root.val + l + r - 1 ; } }
Roblox
Design Browser History
https://leetcode.com/problems/design-browser-history/
Solutions
two stacks
trick, while loop two conditions (steps > 0 && back.size() > 1)
doubly linked list (trickier to write)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class BrowserHistory { Stack<String> back; Stack<String> forward; public BrowserHistory (String homepage) { back = new Stack (); forward = new Stack (); back.add(homepage); } public void visit (String url) { forward.clear(); back.add(url); } public String back (int steps) { String page = "" ; while (steps > 0 && back.size() > 1 ) { page = back.pop(); forward.add(page); steps--; } return back.peek(); } public String forward (int steps) { String page = "" ; while (steps > 0 && !forward.isEmpty()) { page = forward.pop(); back.add(page); steps--; } return back.peek(); } }
Text Justification
https://leetcode.com/problems/text-justification/
Solutions
Single Responsibility Principle (split into smaller functions)
It’s a special case when there’s only one word in the row
last row is different too, because it needs to split into two parts, one appending 1 space, one append all the rest of the spaces
my own solution 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 class Solution { public List<String> fullJustify (String[] words, int maxWidth) { if (words.length == 0 ) return new ArrayList <String>(); List<String> res = new ArrayList <String>(); int left = 0 , right = 0 , wordCharLength = 0 ; while (right < words.length) { int wordLength = words[right].length(); int rowLengthWithSpaces = wordCharLength + (right - left) - 1 ; if (rowLengthWithSpaces + 1 + wordLength > maxWidth) { res.add(justify(words, left, right - 1 , wordCharLength, maxWidth - rowLengthWithSpaces + (right - left) - 1 , maxWidth)); left = right; wordCharLength = 0 ; } right = right + 1 ; wordCharLength += wordLength; } res.add(lastRowConverting(words, left, words.length - 1 , maxWidth)); return res; } private String lastRowConverting (String[] words, int left, int right, int maxWidth) { StringBuilder lastRow = new StringBuilder (); while (left < right) { lastRow.append(words[left] + " " ); maxWidth -= (words[left].length() + 1 ); left++; } int lastWordLength = words[right].length(); lastRow.append(justify(words, left, right, lastWordLength, maxWidth - lastWordLength, maxWidth)); return lastRow.toString(); } private String justify (String[] words, int left, int right, int charLength, int totalSpaces, int maxWidth) { int slots = right - left; int spacePerSlot = slots == 0 ? totalSpaces : totalSpaces / slots; int spaceDiff = slots == 0 ? 0 : totalSpaces % slots; StringBuilder sb = new StringBuilder (); while (left <= right) { sb.append(words[left]); int spacesAfterThisWord = (slots != 0 && left == right) ? 0 : spacePerSlot + (spaceDiff > 0 ? 1 : 0 ); for (int j = 0 ; j < spacesAfterThisWord;j++) { sb.append(" " ); } left++; spaceDiff--; } return sb.toString(); } }
Word Search
https://leetcode.com/problems/word-search/
Solutions
use existing board instead of extra space, mark visited cell “#”
check if there’s char that’s not in the board
check if the word’s length is longer than total num of chars
check 4 directions at each cell.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class Solution { public boolean exist (char [][] board, String word) { int m = board.length; int n = board[0 ].length; if (word.length() > m * n) return false ; HashSet<Character> set = new HashSet (); for (char [] cs : board) for (char c : cs) set.add(c); for (char c : word.toCharArray()) if (!set.contains(c)) return false ; for (int i = 0 ; i < m; i++) { for (int j = 0 ; j < n; j++) { if (board[i][j] == word.charAt(0 )) { boolean res = dfs(board, word, 0 , i, j); if (res) return true ; } } } return false ; } private boolean dfs (char [][] board, String word, int idx, int i, int j) { int m = board.length; int n = board[0 ].length; if (i < 0 || i >= m || j < 0 || j >= n || board[i][j] != word.charAt(idx)) return false ; if (idx == word.length() - 1 ) return true ; board[i][j] = '#' ; boolean up = dfs(board, word, idx + 1 , i - 1 , j); boolean down = dfs(board, word, idx + 1 , i + 1 , j); boolean left = dfs(board, word, idx + 1 , i, j - 1 ); boolean right = dfs(board, word, idx + 1 , i, j + 1 ); board[i][j] = word.charAt(idx); return up || down || left || right; } }
4/28/2022
Course Schedule II
https://leetcode.com/problems/course-schedule-ii/
solutions
Topological sort methods
dfs with colors (permanent, temporary, and empty), add permanent node only. start with each empty node, and mark each one gray, top down, if a gray is met again, that means there’s a cycle.
indegree, indegree means how many parents/dependencies one node has, only add node whose indegree is 0, that means all the dependencies are process already. decrease each node’s indegrees by one when a different node unlocks this node
indegrees 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 class Solution { public int [] findOrder(int numCourses, int [][] prerequisites) { int [] indegrees = new int [numCourses]; HashMap<Integer, List<Integer>> unlocks = new HashMap (); for (int [] pre : prerequisites) { indegrees[pre[0 ]]++; List<Integer> unlock = unlocks.getOrDefault(pre[1 ], new ArrayList <Integer>()); unlock.add(pre[0 ]); unlocks.put(pre[1 ], unlock); } Queue<Integer> q = new LinkedList (); int [] ans = new int [numCourses]; int k = 0 ; for (int i = 0 ; i < numCourses; i++) { if (indegrees[i] == 0 ) { q.add(i); } } while (!q.isEmpty()) { int size = q.size(); for (int i = 0 ; i < size; i++) { int cur = q.poll(); ans[k++] = cur; if (unlocks.containsKey(cur)) { List<Integer> unlock = unlocks.get(cur); for (int dependency : unlock) { if (--indegrees[dependency] == 0 ) { q.add(dependency); } } } } } if (k == numCourses) { return ans; } return new int [0 ]; } }
Number of Matching Subsequences
https://leetcode.com/problems/number-of-matching-subsequences/submissions/
Solutions
binary search (my solution)
record all indice for all chars in s
for each word’s character, check if there exists an char that’s behind the previous char’s index
go through each word in parallel (m being the length of s
, n being the length of words
)
brute force O(mn), TLE
for each char in s
, create a HashMap
or array[26]
, optimised, O(m + num of chars of all words) < O(mn), because m * n - (m + n * l) = mn - m - nl = m(n-1) - nl ~= n(m-l), as long as m is bigger than l, this method is more efficient, which is true. otherwise, most of words longer than l can be eliminated by checking the length diff between l and m in O(1) for each word
my binary solution (my solution) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class Solution { public int numMatchingSubseq (String s, String[] words) { HashMap<Character, List<Integer>> map = new HashMap (); for (int i = 0 ; i < s.length(); i++) { List<Integer> l = map.getOrDefault(s.charAt(i), new ArrayList <Integer>()); l.add(i); map.put(s.charAt(i), l); } int ans = 0 ; for (String word : words) { int idx = -1 ; int i = 0 ; for (; i < word.length(); i++) { if (!map.containsKey(word.charAt(i))) break ; idx = findIndexToTheRightOf(idx, map.get(word.charAt(i))); if (idx == -1 ) break ; } if (i == word.length()) ans++; } return ans; } private int findIndexToTheRightOf (int idx, List<Integer> list) { if (list.size() == 0 || list.get(list.size() - 1 ) <= idx) return -1 ; int left = 0 , right = list.size() - 1 ; while (left < right) { int mid = left + (right - left) / 2 ; if (list.get(mid) <= idx) { left = mid + 1 ; } else { right = mid; } } return list.get(left) > idx ? list.get(left) : list.get(right); } }
parallel with all indices (my solution) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution { public int numMatchingSubseq (String s, String[] words) { int ans = 0 ; int [] indice = new int [words.length]; List<Integer>[] heads = new ArrayList [26 ]; for (int i = 0 ; i < 26 ; i++) heads[i] = new ArrayList <Integer>(); for (int i = 0 ; i < words.length; i++) heads[words[i].charAt(0 ) - 'a' ].add(i); for (char c: s.toCharArray()) { List<Integer> l = heads[c - 'a' ]; heads[c - 'a' ] = new ArrayList <Integer>(); for (int i : l) { indice[i]++; if (indice[i] == words[i].length()) { ans++; } else if (indice[i] < words[i].length()) { char ch = words[i].charAt(indice[i]); heads[ch - 'a' ].add(i); } } } return ans; } }
parallel OOP (given solution) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class Solution { public int numMatchingSubseq (String S, String[] words) { int ans = 0 ; ArrayList<Node>[] heads = new ArrayList [26 ]; for (int i = 0 ; i < 26 ; ++i) heads[i] = new ArrayList <Node>(); for (String word: words) heads[word.charAt(0 ) - 'a' ].add(new Node (word, 0 )); for (char c: S.toCharArray()) { ArrayList<Node> old_bucket = heads[c - 'a' ]; heads[c - 'a' ] = new ArrayList <Node>(); for (Node node: old_bucket) { node.index++; if (node.index == node.word.length()) { ans++; } else { heads[node.word.charAt(node.index) - 'a' ].add(node); } } old_bucket.clear(); } return ans; } } class Node { String word; int index; public Node (String w, int i) { word = w; index = i; } }