├── Solutions
├── 3sum Closest.md
├── 3sum.md
├── 4Sum II.md
├── Add Binary.md
├── Add Two Numbers II.md
├── Add Two Numbers.md
├── Balanced Binary Tree.md
├── Best Time to Buy and Sell Stock II.md
├── Best Time to Buy and Sell Stock with Cooldown.md
├── Best Time to Buy and Sell Stock.md
├── Big Countries.md
├── Binary Search.md
├── Binary Tree Inorder Traversal.md
├── Binary Tree Level Order Traversal II.md
├── Binary Tree Level Order Traversal.md
├── Binary Tree Postorder Traversal.md
├── Binary Tree Preorder Traversal.md
├── Building H2O.md
├── Classes More Than 5 Students.md
├── Climbing Stairs.md
├── Coin Change 2.md
├── Combine Two Tables.md
├── Consecutive Numbers.md
├── Contains Duplicate.md
├── Contiguous Array.md
├── Convert Sorted Array to Binary Search Tree.md
├── Count Primes.md
├── Count and Say.md
├── Course Schedule II.md
├── Course Schedule.md
├── Customers Who Never Order.md
├── Delete Duplicate Emails.md
├── Delete Node in a Linked List.md
├── Department Highest Salary.md
├── Department Top Three Salaries.md
├── Design HashMap.md
├── Design Linked List.md
├── Detect Capital.md
├── Diameter of Binary Tree.md
├── Duplicate Emails.md
├── Employees Earning More Than Their Managers.md
├── Excel Sheet Column Number.md
├── Excel Sheet Column Title.md
├── Exchange Seats.md
├── Factorial Trailing Zeroes.md
├── Fibonacci Number.md
├── Find All Duplicates in an Array.md
├── Find All Numbers Disappeared in an Array.md
├── Find First and Last Position of Element in Sorted Array.md
├── Find Median from Data Stream.md
├── Find Peak Element.md
├── Find the Difference.md
├── First Bad Version.md
├── First Unique Character in a String.md
├── Fizz Buzz Multithreaded.md
├── Fizz Buzz.md
├── Flood Fill.md
├── Generate Parentheses.md
├── Group Anagrams.md
├── Hamming Distance.md
├── Happy Number.md
├── House Robber.md
├── Human Traffic of Stadium.md
├── Implement Queue using Stacks.md
├── Implement Rand10() Using Rand7().md
├── Implement Trie (Prefix Tree).md
├── Implement strStr.md
├── Insert Delete GetRandom O(1) - Duplicates allowed.md
├── Insert Delete GetRandom O(1).md
├── Integer to English Words.md
├── Intersection of Two Arrays II.md
├── Intersection of Two Arrays.md
├── Intersection of Two linked Lists.md
├── Invert Binary Tree.md
├── Jewels and Stones.md
├── Jump Game.md
├── Keyboard Row.md
├── Kth Largest Element in a Stream.md
├── LRU Cache.md
├── Largest 1-Bordered Square.md
├── Largest Perimeter Triangle.md
├── Length of Last Word.md
├── Letter Combinations of a Phone Number.md
├── Linked List Cycle II.md
├── Linked List Cycle.md
├── Longest Common Prefix.md
├── Longest Increasing Subsequence.md
├── Longest Palindromic Subsequence.md
├── Longest Palindromic Substring.md
├── Lowest Common Ancestor of a Binary Search Tree.md
├── Lowest Common Ancestor of a Binary Tree.md
├── Majority Element.md
├── Max Area of Island.md
├── Max Points on a Line.md
├── Maximum Depth of Binary Tree.md
├── Maximum Depth of N-ary Tree.md
├── Maximum Frequency Stack.md
├── Maximum Subarray.md
├── Median of Two Sorted Arrays.md
├── Merge Sorted Array.md
├── Merge Two Binary Trees.md
├── Merge Two Sorted Lists.md
├── Merge k Sorted Lists.md
├── Min Stack.md
├── Minimum Depth of Binary Tree.md
├── Missing Number.md
├── Move Zeroes.md
├── N-Queens II.md
├── N-Queens.md
├── N-ary Tree Level Order Traversal.md
├── N-ary Tree Postorder Traversal.md
├── N-ary Tree Preorder Traversal.md
├── Nim Game.md
├── Not Boring Movies.md
├── Nth Highest Salary.md
├── Number of 1 Bits.md
├── Number of Islands.md
├── Odd Even Linked List.md
├── Pairs of Songs With Total Durations Divisible by 60.md
├── Palindrome Linked List.md
├── Palindrome Number.md
├── Pascal's Triangle II.md
├── Pascal's Triangle.md
├── Path Sum III.md
├── Permutations II.md
├── Permutations.md
├── Plus One.md
├── Power of Four.md
├── Power of Three.md
├── Power of Two.md
├── Print FooBar Alternately.md
├── Print Zero Even Odd.md
├── Print in Order.md
├── Product of Array Except Self.md
├── Range Sum Query - Immutable.md
├── Rank Scores.md
├── Ransom Note.md
├── Reformat Department Table.md
├── Remove Duplicates from Sorted Array II.md
├── Remove Duplicates from Sorted Array.md
├── Remove Duplicates from Sorted List II.md
├── Remove Duplicates from Sorted List.md
├── Remove Element.md
├── Remove Linked List Elements.md
├── Remove Nth Node From End of List.md
├── Reorder List.md
├── Reverse Bits.md
├── Reverse Integer.md
├── Reverse Linked List II.md
├── Reverse Linked List.md
├── Reverse String.md
├── Reverse Words in a String.md
├── Rising Temperature.md
├── Roman to Integer.md
├── Rotate Array.md
├── Rotate Image.md
├── Russian Doll Envelopes.md
├── Same Tree.md
├── Search Insert Position.md
├── Search a 2D Matrix II.md
├── Search in Rotated Sorted Array II.md
├── Search in Rotated Sorted Array.md
├── Second Highest Salary.md
├── Set Matrix Zeroes.md
├── Shortest Common Supersequence.md
├── Shortest Unsorted Continuous Subarray.md
├── Shuffle an Array.md
├── Single Number.md
├── Sliding Window Maximum.md
├── Sliding Window Median.md
├── Sort List.md
├── Sort an Array.md
├── Sqrt(x).md
├── String Compression.md
├── Subarray Sum Equals K.md
├── Subsets II.md
├── Subsets.md
├── Subtree of Another Tree.md
├── Sum of Two Integers.md
├── Swap Salary.md
├── Symmetric Tree.md
├── Third Maximum Number.md
├── To Lower Case.md
├── Top K Frequent Elements.md
├── Top K Frequent Words.md
├── Total Hamming Distance.md
├── Trapping Rain Water.md
├── Trips and Users.md
├── Two Sum II - Input array is sorted.md
├── Two Sum.md
├── Ugly Number II.md
├── Ugly Number.md
├── Unique Number of Occurrences.md
├── Unique Paths II.md
├── Unique Paths.md
├── Valid Anagram.md
├── Valid Palindrome.md
├── Valid Parentheses.md
├── Valid Perfect Square.md
├── Validate Binary Search Tree.md
├── Word Break.md
├── Word Ladder.md
├── Word Pattern.md
└── images
│ ├── BidirectionalSearch.png
│ └── sieveOfEratosthenes.gif
└── readme.md
/Solutions/3sum Closest.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | 1. Sort provided array.
4 | 1. Loop through initial array. On each i-th value, search for pairs of j, k that create a triplet with a sum closest to our "target".
5 |
6 | ### Assumption
7 |
8 | We assume integer overflow is not possible when summing any 3 numbers in `int[] num`.
9 |
10 | ### Solution
11 |
12 | ```java
13 | class Solution {
14 | public int threeSumClosest(int[] num, int target) {
15 | if (num == null || num.length < 3) {
16 | return Integer.MAX_VALUE; // no solution
17 | }
18 | Arrays.sort(num);
19 | int bestSum = num[0] + num[1] + num[2];
20 | for (int i = 0; i < num.length - 2; i++) {
21 | int j = i + 1;
22 | int k = num.length - 1;
23 | while (j < k) {
24 | int sum = num[i] + num[j] + num[k];
25 | if (Math.abs(sum - target) < Math.abs(bestSum - target)) {
26 | bestSum = sum;
27 | }
28 | if (sum < target) {
29 | j++;
30 | } else if (sum > target) {
31 | k--;
32 | } else {
33 | return target; // we found an exact match
34 | }
35 | }
36 | }
37 | return bestSum;
38 | }
39 | }
40 | ```
41 |
42 | ### Time/Space Complexity
43 |
44 | - Time Complexity: O(n2)
45 | - Space Complexity: Depends on `Arrays.sort()`. Can be as low as O(1).
46 |
47 | ### Links
48 |
49 | - [github.com/RodneyShag](https://github.com/RodneyShag)
50 |
--------------------------------------------------------------------------------
/Solutions/4Sum II.md:
--------------------------------------------------------------------------------
1 | ### Assumptions
2 |
3 | - Integer overflow cannot occur. Problem Description says: All integers are in the range of -228 to 228 - 1 and the result is guaranteed to be at most 231 - 1.
4 |
5 | ### Algorithm
6 |
7 | 1. Rewrite the equation as A[i] + B[j] = -(C[k] + D[l]).
8 | 1. Create a Map where 'key' is A[i] + B[j] and 'value' is the number of pairs with this sum.
9 | 1. For each -(C[k] + D[l]), see if this desired sum is in our map. If so, add the map's 'value' to our total count.
10 |
11 | ### Solution
12 |
13 | ```java
14 | class Solution {
15 | public int fourSumCount(int[] A, int[] B, int[] C, int[] D) {
16 | if (A == null || B == null || C == null || D == null) {
17 | return 0;
18 | }
19 | int count = 0;
20 | Map map = new HashMap();
21 | for (int i = 0; i < A.length; i++) {
22 | for (int j = 0; j < B.length; j++) {
23 | map.merge(A[i] + B[j], 1, Integer::sum);
24 | }
25 | }
26 |
27 | for (int k = 0; k < C.length; k++) {
28 | for (int l = 0; l < D.length; l++) {
29 | int desiredSum = -(C[k] + D[l]);
30 | if (map.containsKey(desiredSum)) {
31 | count += map.get(desiredSum);
32 | }
33 | }
34 | }
35 | return count;
36 | }
37 | }
38 | ```
39 |
40 | ### Time/Space Complexity
41 |
42 | - Time Complexity: O(n2)
43 | - Space Complexity: O(n2) since our `Map` will have n2 keys if every sum A[i] + B[j] is unique
44 |
45 | ### Links
46 |
47 | - [github.com/RodneyShag](https://github.com/RodneyShag)
48 |
--------------------------------------------------------------------------------
/Solutions/Add Binary.md:
--------------------------------------------------------------------------------
1 | ### Notes
2 |
3 | This problem is similar to [LeetCode #2 - Add Two Numbers](https://leetcode.com/problems/add-two-numbers). We will use the same algorithm used in the [solution to that problem](https://github.com/RodneyShag/LeetCode_solutions/blob/master/Solutions/Add%20Two%20Numbers.md)
4 |
5 | ### Solution
6 |
7 | ```java
8 | class Solution {
9 | public String addBinary(String s1, String s2) {
10 | if (s1 == null) {
11 | return s2;
12 | } else if (s2 == null) {
13 | return s1;
14 | }
15 |
16 | int carry = 0;
17 | int i = s1.length() - 1;
18 | int j = s2.length() - 1;
19 | StringBuffer sb = new StringBuffer();
20 |
21 | while (i >= 0 || j >= 0 || carry != 0) {
22 | int sum = carry;
23 | if (i >= 0 && s1.charAt(i) == '1') {
24 | sum++;
25 | }
26 | if (j >= 0 && s2.charAt(j) == '1') {
27 | sum++;
28 | }
29 | int digit = sum % 2;
30 | carry = sum / 2;
31 | sb.append(digit);
32 | i--;
33 | j--;
34 | }
35 |
36 | return sb.reverse().toString();
37 | }
38 | }
39 | ```
40 |
41 | ### Time/Space Complexity
42 |
43 | - Time Complexity: O(n + m)
44 | - Space Complexity: O(n + m)
45 |
46 | ### Links
47 |
48 | - [github.com/RodneyShag](https://github.com/RodneyShag)
49 |
--------------------------------------------------------------------------------
/Solutions/Add Two Numbers II.md:
--------------------------------------------------------------------------------
1 | ### Notes
2 |
3 | - Use 1 stack for each Linked List to reverse each Linked List. It will now be easier to add numbers in the lists.
4 | - I use an `ArrayDeque` as a `Stack` since it's faster.
5 |
6 | ### Provided Code
7 |
8 | ```java
9 | public class ListNode {
10 | int val;
11 | ListNode next;
12 | ListNode(int x) {
13 | val = x;
14 | }
15 | }
16 | ```
17 |
18 | ### Solution
19 |
20 | ```java
21 | class Solution {
22 | public ListNode addTwoNumbers(ListNode m, ListNode n) {
23 | if (m == null) {
24 | return n;
25 | } else if (n == null) {
26 | return m;
27 | }
28 |
29 | Deque deque1 = new ArrayDeque(); // use as a stack
30 | Deque deque2 = new ArrayDeque(); // use as a stack
31 |
32 | while (m != null) {
33 | deque1.push(m.val);
34 | m = m.next;
35 | }
36 | while (n != null) {
37 | deque2.push(n.val);
38 | n = n.next;
39 | }
40 |
41 | int carry = 0;
42 | ListNode dummy = new ListNode(0); // 1 Node before the actual head of list
43 | while (!deque1.isEmpty() || !deque2.isEmpty() || carry != 0) {
44 | int value = carry;
45 | if (!deque1.isEmpty()) {
46 | value += deque1.pop();
47 | }
48 | if (!deque2.isEmpty()) {
49 | value += deque2.pop();
50 | }
51 | int digit = value % 10;
52 | carry = value / 10;
53 | ListNode head = new ListNode(digit);
54 | head.next = dummy.next;
55 | dummy.next = head;
56 | }
57 | return dummy.next;
58 | }
59 | }
60 | ```
61 |
62 | ### Time/Space Complexity
63 |
64 | - Time Complexity: O(m + n)
65 | - Space Complexity: O(m + n)
66 |
67 | ### Links
68 |
69 | - [github.com/RodneyShag](https://github.com/RodneyShag)
70 |
--------------------------------------------------------------------------------
/Solutions/Add Two Numbers.md:
--------------------------------------------------------------------------------
1 | ### Provided Code
2 |
3 | ```java
4 | public class ListNode {
5 | int val;
6 | ListNode next;
7 | ListNode(int x) {
8 | val = x;
9 | }
10 | }
11 | ```
12 |
13 | ### Solution
14 |
15 | ```java
16 | class Solution {
17 | public ListNode addTwoNumbers(ListNode m, ListNode n) {
18 | int carry = 0;
19 | ListNode dummy = new ListNode(0); // 1 Node before the actual head of list
20 | ListNode tail = dummy;
21 | while (m != null || n!= null || carry != 0) {
22 | int value = carry;
23 | if (m != null) {
24 | value += m.val;
25 | m = m.next;
26 | }
27 | if (n != null) {
28 | value += n.val;
29 | n = n.next;
30 | }
31 | int digit = value % 10;
32 | carry = value / 10;
33 | tail.next = new ListNode(digit);
34 | tail = tail.next;
35 | }
36 | return dummy.next;
37 | }
38 | }
39 | ```
40 |
41 | ### Time/Space Complexity
42 |
43 | - Time Complexity: O(m + n)
44 | - Space Complexity: O(m + n)
45 |
46 | ### Links
47 |
48 | - [github.com/RodneyShag](https://github.com/RodneyShag)
49 |
--------------------------------------------------------------------------------
/Solutions/Balanced Binary Tree.md:
--------------------------------------------------------------------------------
1 | ### Provided Code
2 |
3 | ```java
4 | class TreeNode {
5 | TreeNode left;
6 | TreeNode right;
7 | }
8 | ```
9 |
10 | ### Solution
11 |
12 | ```java
13 | class Solution {
14 | public boolean isBalanced(TreeNode root) {
15 | return isBalancedHelper(root) != -1;
16 | }
17 |
18 | private int isBalancedHelper(TreeNode root) {
19 | if (root == null) {
20 | return 0;
21 | }
22 |
23 | int leftHeight = isBalancedHelper(root.left);
24 | if (leftHeight == -1) {
25 | return -1; // left tree is unbalanced
26 | }
27 |
28 | int rightHeight = isBalancedHelper(root.right);
29 | if (rightHeight == -1) {
30 | return -1; // right tree is unbalanced
31 | }
32 |
33 | if (Math.abs(leftHeight - rightHeight) > 1) {
34 | return -1; // imbalance between the 2 subtrees
35 | }
36 |
37 | return 1 + Math.max(leftHeight, rightHeight);
38 | }
39 | }
40 | ```
41 |
42 | ### Time/Space Complexity
43 |
44 | - Time Complexity: O(n)
45 | - Space Complexity: O(log n) if balanced tree. O(n) otherwise.
46 |
47 | ### Links
48 |
49 | - [github.com/RodneyShag](https://github.com/RodneyShag)
50 |
--------------------------------------------------------------------------------
/Solutions/Best Time to Buy and Sell Stock II.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | Here's a sample graph of Price/Day:
4 |
5 | ```
6 | P \ /\ /\
7 | R \ /\ / \/ \
8 | I \/ \/ \ /
9 | C \/
10 | E
11 | Day
12 | ```
13 |
14 | We can always buy at the stock prices "local min" and sell at the stock prices "local max". So all we need to keep track of is how much the price increased between every pair of [local min, local max].
15 |
16 | To calculate our total profit, every time the stock price increases, we add the price increase to our total profit.
17 |
18 | ### Solution
19 |
20 | ```java
21 | class Solution {
22 | public int maxProfit(int[] prices) {
23 | if (prices == null) {
24 | return 0;
25 | }
26 | int profit = 0;
27 | for (int i = 1; i < prices.length; i++) {
28 | if (prices[i] > prices[i - 1])
29 | profit += prices[i] - prices[i - 1];
30 | }
31 | return profit;
32 | }
33 | }
34 | ```
35 |
36 | ### Time/Space Complexity
37 |
38 | - Time Complexity: O(n)
39 | - Space Complexity: O(1)
40 |
41 | ### Links
42 |
43 | - [github.com/RodneyShag](https://github.com/RodneyShag)
44 |
--------------------------------------------------------------------------------
/Solutions/Best Time to Buy and Sell Stock.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | 1. Iterate through the array. While iterating, keep track of 2 variables
4 | - `min` representing the minimum value you've seen so far
5 | - `maxProf` representing the maximum profit that can be generated (through a buy/sell) so far.
6 | 1. Return `maxProf`
7 |
8 | ### Solution
9 |
10 | ```java
11 | class Solution {
12 | public int maxProfit(int[] prices) {
13 | if (prices == null || prices.length == 0) {
14 | return 0;
15 | }
16 | int min = prices[0];
17 | int maxProf = 0;
18 | for (int price : prices) {
19 | min = Math.min(min, price);
20 | maxProf = Math.max(maxProf, price - min);
21 | }
22 | return maxProf;
23 | }
24 | }
25 | ```
26 |
27 | ### Time/Space Complexity
28 |
29 | - Time Complexity: O(n)
30 | - Space Complexity: O(1)
31 |
32 | ### Variation of problem
33 |
34 | [This post](https://leetcode.com/problems/best-time-to-buy-and-sell-stock/discuss/39038) inspired a variation of the problem below.
35 |
36 | Instead of giving stock prices `{1, 7, 4, 11}`, the interviewer may give the differences of prices between successive days `{0, 6, -3, 7}`.
37 |
38 | In this case, we need to find a contiguous subarray giving the maximum profit. If the profit falls below 0, reset it to 0.
39 |
40 | ```java
41 | public int maxProfit(int[] prices) {
42 | int maxCur = 0
43 | int maxSoFar = 0;
44 | for(int i = 1; i < prices.length; i++) {
45 | maxCur = Math.max(0, maxCur + prices[i] - prices[i - 1]);
46 | maxSoFar = Math.max(maxSoFar, maxCur);
47 | }
48 | return maxSoFar;
49 | }
50 | ```
51 |
52 | - Time Complexity: O(n)
53 | - Space Complexity: O(1)
54 |
55 | ### Links
56 |
57 | - [github.com/RodneyShag](https://github.com/RodneyShag)
58 |
--------------------------------------------------------------------------------
/Solutions/Big Countries.md:
--------------------------------------------------------------------------------
1 | ### MySQL Solution
2 |
3 | ```sql
4 | SELECT name, population, area FROM World
5 | WHERE population > 25000000 OR
6 | area > 3000000
7 | ```
8 |
9 | ### Links
10 |
11 | - [github.com/RodneyShag](https://github.com/RodneyShag)
12 |
--------------------------------------------------------------------------------
/Solutions/Binary Search.md:
--------------------------------------------------------------------------------
1 | ### Solution
2 |
3 | ```java
4 | class Solution {
5 | public int search(int[] sortedArray, int value) {
6 | int lo = 0;
7 | int hi = sortedArray.length - 1;
8 |
9 | while (lo <= hi) {
10 | int mid = lo + (hi - lo) / 2;
11 | if (sortedArray[mid] > value) {
12 | hi = mid - 1;
13 | } else if (sortedArray[mid] < value) {
14 | lo = mid + 1;
15 | } else {
16 | return mid;
17 | }
18 | }
19 | return -1;
20 | }
21 | }
22 | ```
23 |
24 | ### Implementation Details
25 |
26 | Instead of calculating the middle value as `mid = (lo + hi) / 2`, do `mid = lo + (hi - lo) / 2` to avoid integer overflow
27 |
28 | ### Time/Space Complexity
29 |
30 | - Time Complexity: O(log n)
31 | - Space Complexity: O(1)
32 |
33 | ### Links
34 |
35 | - [github.com/RodneyShag](https://github.com/RodneyShag)
36 |
--------------------------------------------------------------------------------
/Solutions/Binary Tree Inorder Traversal.md:
--------------------------------------------------------------------------------
1 | ### Provided Code
2 |
3 | ```java
4 | class TreeNode {
5 | int val;
6 | TreeNode left;
7 | TreeNode right;
8 | }
9 | ```
10 |
11 | ### Solution
12 |
13 | ```java
14 | class Solution {
15 | public List inorderTraversal(TreeNode root) {
16 | List list = new ArrayList();
17 | inorderTraversal(root, list);
18 | return list;
19 | }
20 |
21 | private void inorderTraversal(TreeNode node, List list) {
22 | if (node != null) {
23 | inorderTraversal(node.left, list);
24 | list.add(node.val);
25 | inorderTraversal(node.right, list);
26 | }
27 | }
28 | }
29 | ```
30 |
31 | ### Time/Space Complexity
32 |
33 | - Time Complexity: O(n) since we must visit all nodes.
34 | - Space Complexity: O(log n) on balanced tree. O(n) otherwise.
35 |
36 | ### Notes
37 |
38 | The follow-up question asks us for an iterative solution, but there is no benefit to that solution as neither the time or space complexity is improved by solving the problem iteratively.
39 |
40 | ### Links
41 |
42 | - [github.com/RodneyShag](https://github.com/RodneyShag)
43 |
--------------------------------------------------------------------------------
/Solutions/Binary Tree Level Order Traversal II.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | - This problem is the same as [LeetCode #102 - Binary Tree Level Order Traversal](https://leetcode.com/problems/binary-tree-level-order-traversal) except that it wants the order of the lists reversed
4 | - Use the same [solution to that problem](https://github.com/RodneyShag/LeetCode_solutions/blob/master/Solutions/Binary%20Tree%20Level%20Order%20Traversal.md), except insert lists into the solution in reverse order
5 | - Since we keep inserting into our list at position 0, we will use a `LinkedList` instead of an `ArrayList` for efficiency
6 |
7 | ### Provided Code
8 |
9 | ```java
10 | class TreeNode {
11 | int val;
12 | TreeNode left;
13 | TreeNode right;
14 | }
15 | ```
16 |
17 | ### Solution
18 |
19 | ```java
20 | class Solution {
21 | public List> levelOrderBottom(TreeNode root) {
22 | if (root == null) {
23 | return new LinkedList();
24 | }
25 | List> lists = new LinkedList();
26 | Deque deque = new ArrayDeque(); // use deque as a queue
27 | deque.add(root);
28 | while (!deque.isEmpty()) {
29 | int numNodesInLevel = deque.size();
30 | List level = new ArrayList(numNodesInLevel);
31 | while (numNodesInLevel-- > 0) {
32 | TreeNode n = deque.remove();
33 | level.add(n.val);
34 | if (n.left != null) {
35 | deque.add(n.left);
36 | }
37 | if (n.right != null) {
38 | deque.add(n.right);
39 | }
40 | }
41 | lists.add(0, level);
42 | }
43 | return lists;
44 | }
45 | }
46 | ```
47 |
48 | ### Time/Space Complexity
49 |
50 | - Time Complexity: O(n)
51 | - Space Complexity: O(n)
52 |
53 | ### Links
54 |
55 | - [github.com/RodneyShag](https://github.com/RodneyShag)
56 |
--------------------------------------------------------------------------------
/Solutions/Binary Tree Level Order Traversal.md:
--------------------------------------------------------------------------------
1 | ### Provided Code
2 |
3 | ```java
4 | class TreeNode {
5 | int val;
6 | TreeNode left;
7 | TreeNode right;
8 | }
9 | ```
10 |
11 | ### Solution
12 |
13 | ```java
14 | class Solution {
15 | public List> levelOrder(TreeNode root) {
16 | if (root == null) {
17 | return new ArrayList();
18 | }
19 | List> lists = new ArrayList();
20 | Deque deque = new ArrayDeque(); // use deque as a queue
21 | deque.add(root);
22 | while (!deque.isEmpty()) {
23 | int numNodesInLevel = deque.size();
24 | List level = new ArrayList(numNodesInLevel);
25 | while (numNodesInLevel-- > 0) {
26 | TreeNode n = deque.remove();
27 | level.add(n.val);
28 | if (n.left != null) {
29 | deque.add(n.left);
30 | }
31 | if (n.right != null) {
32 | deque.add(n.right);
33 | }
34 | }
35 | lists.add(level);
36 | }
37 | return lists;
38 | }
39 | }
40 | ```
41 |
42 | ### Time/Space Complexity
43 |
44 | - Time Complexity: O(n)
45 | - Space Complexity: O(n)
46 |
47 | ### Links
48 |
49 | - [github.com/RodneyShag](https://github.com/RodneyShag)
50 |
--------------------------------------------------------------------------------
/Solutions/Binary Tree Postorder Traversal.md:
--------------------------------------------------------------------------------
1 | ### Provided Code
2 |
3 | ```java
4 | class TreeNode {
5 | int val;
6 | TreeNode left;
7 | TreeNode right;
8 | }
9 | ```
10 |
11 | ### Solution
12 |
13 | ```java
14 | class Solution {
15 | public List postorderTraversal(TreeNode root) {
16 | List list = new ArrayList();
17 | postorderTraversal(root, list);
18 | return list;
19 | }
20 |
21 | private void postorderTraversal(TreeNode node, List list) {
22 | if (node != null) {
23 | postorderTraversal(node.left, list);
24 | postorderTraversal(node.right, list);
25 | list.add(node.val);
26 | }
27 | }
28 | }
29 | ```
30 |
31 | ### Time/Space Complexity
32 |
33 | - Time Complexity: O(n) since we must visit all nodes.
34 | - Space Complexity: O(log n) on balanced tree. O(n) otherwise.
35 |
36 | ### Notes
37 |
38 | The follow-up question asks us for an iterative solution, but there is no benefit to that solution as neither the time or space complexity is improved by solving the problem iteratively.
39 |
40 | ### Links
41 |
42 | - [github.com/RodneyShag](https://github.com/RodneyShag)
43 |
--------------------------------------------------------------------------------
/Solutions/Binary Tree Preorder Traversal.md:
--------------------------------------------------------------------------------
1 | ### Provided Code
2 |
3 | ```java
4 | class TreeNode {
5 | int val;
6 | TreeNode left;
7 | TreeNode right;
8 | }
9 | ```
10 |
11 | ### Solution
12 |
13 | ```java
14 | class Solution {
15 | public List preorderTraversal(TreeNode root) {
16 | List list = new ArrayList();
17 | preorderTraversal(root, list);
18 | return list;
19 | }
20 |
21 | private void preorderTraversal(TreeNode node, List list) {
22 | if (node != null) {
23 | list.add(node.val);
24 | preorderTraversal(node.left, list);
25 | preorderTraversal(node.right, list);
26 | }
27 | }
28 | }
29 | ```
30 |
31 | ### Time/Space Complexity
32 |
33 | - Time Complexity: O(n) since we must visit all nodes.
34 | - Space Complexity: O(log n) on balanced tree. O(n) otherwise.
35 |
36 | ### Notes
37 |
38 | The follow-up question asks us for an iterative solution, but there is no benefit to that solution as neither the time or space complexity is improved by solving the problem iteratively.
39 |
40 | ### Links
41 |
42 | - [github.com/RodneyShag](https://github.com/RodneyShag)
43 |
--------------------------------------------------------------------------------
/Solutions/Building H2O.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | Use `Semaphore`s to represent `H` and `O`. Here is a good explanation of [Semaphores](https://www.geeksforgeeks.org/semaphore-in-java/) (read their explanation, skip their code).
4 |
5 | We can use a [CyclicBarrier](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CyclicBarrier.html#await--) to create a barrier for every 3 elements. However, `CyclicBarrier` can throw a `BrokenBarrierException` when calling `await()`, so we instead use a [Phaser](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Phaser.html) to avoid having to catch or throw `BrokenBarrierException`. We use this `Phaser` to wait for 3 elements to form a molecule, before releasing another 2 `H` and 1 `O` elements.
6 |
7 | The problem statement is unclear whether there are 2 threads or 3 threads of `H20` class running. The code below assumes we have 3 threads of `H20` running simultaneously.
8 |
9 | ### Solution
10 |
11 | ```java
12 | class H2O {
13 | private Semaphore semH = new Semaphore(2);
14 | private Semaphore semO = new Semaphore(1);
15 | private Phaser phaser = new Phaser(3);
16 |
17 | public void hydrogen(Runnable releaseHydrogen) throws InterruptedException {
18 | semH.acquire();
19 | releaseHydrogen.run(); // outputs "H"
20 | phaser.arriveAndAwaitAdvance();
21 | semH.release();
22 | }
23 |
24 | public void oxygen(Runnable releaseOxygen) throws InterruptedException {
25 | semO.acquire();
26 | releaseOxygen.run(); // outputs "O"
27 | phaser.arriveAndAwaitAdvance();
28 | semO.release();
29 | }
30 | }
31 | ```
32 |
33 | ### Time/Space Complexity
34 |
35 | - Time Complexity: O(n) since string will have O(n) characters
36 | - Space Complexity: O(1)
37 |
38 | ### Links
39 |
40 | - [github.com/RodneyShag](https://github.com/RodneyShag)
41 |
--------------------------------------------------------------------------------
/Solutions/Classes More Than 5 Students.md:
--------------------------------------------------------------------------------
1 | ### Hints
2 |
3 | Use [GROUP BY](https://www.w3schools.com/sql/sql_groupby.asp) on `class` and find the [COUNT](https://www.w3schools.com/sql/sql_count_avg_sum.asp) of students in each `class`.
4 |
5 | Use the [HAVING](https://www.w3schools.com/sql/sql_having.asp) clause since the `WHERE` clause doesn't support aggregate functions
6 |
7 | ### Notes
8 |
9 | If the table was designed properly without duplicate entries, the following code would work:
10 |
11 | ```sql
12 | SELECT class FROM courses
13 | GROUP BY class
14 | HAVING COUNT(class) >= 5
15 | ```
16 |
17 | However, the duplicate entries in the table prevent the above code from working properly.
18 |
19 | ### MySQL Solution
20 |
21 | We use `DISTINCT` to remove the duplicate entries.
22 |
23 | ```sql
24 | SELECT class FROM courses
25 | GROUP BY class
26 | HAVING COUNT(DISTINCT student) >= 5
27 | ```
28 |
29 | ### Links
30 |
31 | - [github.com/RodneyShag](https://github.com/RodneyShag)
32 |
--------------------------------------------------------------------------------
/Solutions/Coin Change 2.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | [Video explanation](https://www.youtube.com/watch?time_continue=350&v=jaNZ83Q3QGc)
4 |
5 | ### Solution
6 |
7 | ```java
8 | class Solution {
9 | public int change(int amount, int[] coins) {
10 | int[] dp = new int[amount + 1];
11 | dp[0] = 1;
12 | for (int coin : coins) {
13 | for (int i = coin; i <= amount; i++) {
14 | dp[i] += dp[i-coin];
15 | }
16 | }
17 | return dp[amount];
18 | }
19 | }
20 | ```
21 |
22 | ### Notes
23 |
24 | - In the general case, our solution may overflow our `int` return value. Can use a `long` instead.
25 |
26 | ### Time/Space Complexity
27 |
28 | - Time Complexity: O(amount * coins)
29 | - Space Complexity: O(amount)
30 |
31 | ### Links
32 |
33 | - [github.com/RodneyShag](https://github.com/RodneyShag)
34 |
--------------------------------------------------------------------------------
/Solutions/Combine Two Tables.md:
--------------------------------------------------------------------------------
1 | ### MySQL Solution
2 |
3 | ```sql
4 | SELECT FirstName, LastName, City, State FROM Person
5 | LEFT JOIN Address USING(PersonId)
6 | ```
7 |
8 | ### Notes
9 |
10 | We could also replace
11 |
12 | ```sql
13 | USING(PersonId)
14 | ```
15 |
16 | with
17 |
18 | ```sql
19 | ON Person.PersonId = Address.PersonId
20 | ```
21 |
22 | The `ON` clause is used to join tables where the column names don’t match in both tables.
23 |
24 | ### Links
25 |
26 | - [github.com/RodneyShag](https://github.com/RodneyShag)
27 |
--------------------------------------------------------------------------------
/Solutions/Consecutive Numbers.md:
--------------------------------------------------------------------------------
1 | ### Notes
2 |
3 | We assume the `Id` column increases sequentially by 1 for every row. Otherwise, the below solution would not work properly.
4 |
5 | The below solution uses a [SELF JOIN](https://www.w3schools.com/sql/sql_join_self.asp).
6 |
7 | ### MySQL Solution
8 |
9 | ```sql
10 | SELECT DISTINCT l1.Num AS ConsecutiveNums
11 | FROM
12 | Logs AS l1,
13 | Logs AS l2,
14 | Logs AS l3
15 | WHERE
16 | l1.Id + 1 = l2.Id AND
17 | l2.Id + 1 = l3.Id AND
18 | l1.Num = l2.Num AND
19 | l2.Num = l3.Num
20 | ```
21 |
22 | ### Why use `Distinct`?
23 |
24 | Without `Distinct`, this test case fails:
25 |
26 | ```
27 | Input: {"headers": {"Logs": ["Id", "Num"]}, "rows": {"Logs": [[1, 3], [2, 3], [3, 3], [4, 3]]}}
28 | Output: {"headers": ["ConsecutiveNums"], "values": [[3], [3]]}
29 | Expected: {"headers":["ConsecutiveNums"],"values":[[3]]}
30 | ```
31 |
32 | since for `[3,3]`, it's a match for `[1,3], [2,3], [3,3]` and also for `[2,3], [3,3], [4,3]`. We end up matching on `[3,3]` twice, and the `l1.Num` on it incorrectly gives us `[3]` twice
33 |
34 | ### Links
35 |
36 | - [github.com/RodneyShag](https://github.com/RodneyShag)
37 |
--------------------------------------------------------------------------------
/Solutions/Contains Duplicate.md:
--------------------------------------------------------------------------------
1 | ### Hint
2 |
3 | Use a `HashSet` to detect duplicates.
4 |
5 | ### Solution
6 |
7 | ```java
8 | class Solution {
9 | public boolean containsDuplicate(int[] nums) {
10 | Set set = new HashSet();
11 | for (int num : nums) {
12 | if (set.contains(num)) {
13 | return true;
14 | }
15 | set.add(num);
16 | }
17 | return false;
18 | }
19 | }
20 | ```
21 |
22 | ### Time/Space Complexity
23 |
24 | - Time Complexity: O(n)
25 | - Space Complexity: O(n)
26 |
27 | ### Links
28 |
29 | - [github.com/RodneyShag](https://github.com/RodneyShag)
30 |
--------------------------------------------------------------------------------
/Solutions/Contiguous Array.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | 1. Create "deltas" array. Each value in this array will represent (number of 1s) minus (number of 0s) seen so far.
4 | 1. Create a HashMap, that for each delta, it saves the first index we saw this delta in our array
5 | - "key" is the "delta" calculated earlier
6 | - "value" is first index of this delta in original array
7 |
8 | ### Example
9 |
10 | ```
11 | index: [ 0 1 2 3 4 5 6 7]
12 | input: [ 0 0 1 0 0 0 1 1]
13 | deltas: [-1 -2 -1 -2 -3 -4 -3 -2]
14 | ```
15 |
16 | - In `int[] deltas`, if 2 indices have the same value, then number of 0s and number of 1s are equal between these indices.
17 | - The largest valid subarray corresponds to the largest `j-i` where `deltas[i] == deltas[j]`.
18 | - In this case, `i=1`, `j=7`, `deltas[i] == deltas[j] == -2`, and `j-i = 7-1 = 6`.
19 | - This corresponds to subarray `(i, j]` which is `[1, 0, 0, 0, 1, 1]`
20 |
21 | ### Solution
22 |
23 | ```java
24 | class Solution {
25 | private int[] findDeltas(int[] array) {
26 | int[] deltas = new int[array.length];
27 | int delta = 0;
28 | for (int i = 0; i < array.length; i++) {
29 | if (array[i] == 1) {
30 | delta++;
31 | } else if (array[i] == 0) {
32 | delta--;
33 | }
34 | deltas[i] = delta;
35 | }
36 | return deltas;
37 | }
38 |
39 | public int findMaxLength(int[] array) {
40 | if (array == null) {
41 | return 0;
42 | }
43 | int[] deltas = findDeltas(array);
44 | Map map = new HashMap();
45 | map.put(0, -1); // for testcases such as [1, 0], [1, 0, 0]
46 | int maxLength = 0;
47 | for (int i = 0; i < array.length; i++) {
48 | if (!map.containsKey(deltas[i])) {
49 | map.put(deltas[i], i);
50 | } else {
51 | maxLength = Math.max(maxLength, i - map.get(deltas[i]));
52 | }
53 | }
54 | return maxLength;
55 | }
56 | }
57 | ```
58 |
59 | ### Time/Space Complexity
60 |
61 | - Time Complexity: O(n)
62 | - Space Complexity: O(n)
63 |
64 | ### Links
65 |
66 | - [github.com/RodneyShag](https://github.com/RodneyShag)
67 |
--------------------------------------------------------------------------------
/Solutions/Convert Sorted Array to Binary Search Tree.md:
--------------------------------------------------------------------------------
1 | ### Provided Code
2 |
3 | ```java
4 | class TreeNode {
5 | int val;
6 | TreeNode left;
7 | TreeNode right;
8 | TreeNode(int x) {
9 | val = x;
10 | }
11 | }
12 | ```
13 |
14 | ### Solution
15 |
16 | ```java
17 | class Solution {
18 | public TreeNode sortedArrayToBST(int[] sortedArray) {
19 | if (sortedArray == null) {
20 | return null;
21 | }
22 | return createBST(sortedArray, 0, sortedArray.length - 1);
23 | }
24 |
25 | private TreeNode createBST(int[] sortedArray, int startIndex, int endIndex) {
26 | if (startIndex > endIndex) {
27 | return null;
28 | }
29 | int mid = (startIndex + endIndex) / 2;
30 | TreeNode root = new TreeNode(sortedArray[mid]);
31 | root.left = createBST(sortedArray, startIndex, mid - 1);
32 | root.right = createBST(sortedArray, mid + 1, endIndex);
33 | return root;
34 | }
35 | }
36 | ```
37 |
38 | ### Time/Space Complexity
39 |
40 | - Time Complexity: O(n)
41 | - Space Complexity: O(n) since we're creating a Binary Search Tree
42 |
43 | ### Links
44 |
45 | - [github.com/RodneyShag](https://github.com/RodneyShag)
46 |
--------------------------------------------------------------------------------
/Solutions/Count Primes.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | This algorithm is called [Sieve of Eratosthenes](https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes)
4 |
5 | 
6 |
7 | 1. Create `boolean[] flags` where each `true` represents a prime number.
8 | - Initialize all numbers 2 and bigger as `true` for now, we will later cross off the non-prime numbers.
9 | 1. Start at prime number 2 and cross off all multiples of 2. Repeat this step for the remaining prime numbers.
10 |
11 | ### Optimization 1
12 |
13 | Notice we only need to loop to square root of n (instead of n) to cross off all non-primes
14 |
15 | ### Optimization 2
16 |
17 | To cross off multiples of prime `p`, we want to cross off `2p`, `3p`, `4p`, `5p`, but all `kp` where `k < p` have already been crossed off in a previous step. For this reason, for each prime, we can start crossing off at `p * p`
18 |
19 |
20 | ### Solution
21 |
22 | ```java
23 | class Solution {
24 | public int countPrimes(int n) {
25 | if (n < 2) {
26 | return 0;
27 | }
28 | boolean[] isPrime = new boolean[n];
29 | for (int i = 2; i < n; i++) {
30 | isPrime[i] = true;
31 | }
32 |
33 | int sqrt = (int) Math.sqrt(n);
34 | for (int p = 2; p <= sqrt; p++) {
35 | if (isPrime[p]) {
36 | for (int i = p * p; i < n; i += p) {
37 | isPrime[i] = false;
38 | }
39 | }
40 | }
41 |
42 | int count = 0;
43 | for (int i = 2; i < n; i++) {
44 | if (isPrime[i]) {
45 | count++;
46 | }
47 | }
48 | return count;
49 | }
50 | }
51 | ```
52 |
53 | ### Time Complexity
54 |
55 | Since we have nested loops, our runtime is `O(sqrt(n) * n)`.
56 |
57 | However, this analysis did not take into account that the inner loop is skipped whenever `isPrime[i]` is true. The actual time complexity is `O(n * log(log(n)))` according to [this link](https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes#Algorithmic_complexity), but understanding/explaining it during an interview is definitely not expected.
58 |
59 | ### Space Complexity
60 |
61 | O(n) due to `boolean[] isPrime`
62 |
63 | ### Links
64 |
65 | - [github.com/RodneyShag](https://github.com/RodneyShag)
66 |
--------------------------------------------------------------------------------
/Solutions/Count and Say.md:
--------------------------------------------------------------------------------
1 | ### Solution
2 |
3 | ```java
4 | class Solution {
5 | public String countAndSay(int n) {
6 | if (n <= 0) {
7 | return "";
8 | }
9 | String s = "1";
10 | for (int i = 2; i <= n; i++) {
11 | s = say(s);
12 | }
13 | return s;
14 | }
15 |
16 | private String say(String s) {
17 | StringBuffer sb = new StringBuffer();
18 | int count = 1;
19 | for (int i = 1; i < s.length(); i++) {
20 | char prev = s.charAt(i - 1);
21 | char curr = s.charAt(i);
22 | if (curr == prev) {
23 | count++;
24 | } else {
25 | sb.append(count).append(prev);
26 | count = 1;
27 | }
28 | }
29 | // append count of last character
30 | sb.append(count).append(s.charAt(s.length() - 1));
31 |
32 | return sb.toString();
33 | }
34 | }
35 | ```
36 |
37 | ### Time/Space Complexity
38 |
39 | - One way to represent the space complexity is `O(nm)` where `m` is the length of the `String` on the last iteration.
40 | - However, `m` is not part of the input, and we want to write space complexity in terms of just the input, which is `n`.
41 | - `m` depends on `n`. In the worst case, `m` doubles in size whenever the previous string does not have 2 adjacent digits that are the same. For example, when `n = 3`, we have `21`, and on `n = 4`, we have `1211`.
42 | - Since m = 2n in the worst case, we rewrite the space complexity as O(nm) = O(n2n)
43 |
44 | ### Space Complexity
45 |
46 | O(1)
47 |
48 | ### Links
49 |
50 | - [github.com/RodneyShag](https://github.com/RodneyShag)
51 |
--------------------------------------------------------------------------------
/Solutions/Customers Who Never Order.md:
--------------------------------------------------------------------------------
1 | ### Notes
2 |
3 | Use a [LEFT JOIN](https://www.w3schools.com/sql/sql_join_left.asp)
4 |
5 | ### MySQL Solution
6 |
7 | ```sql
8 | SELECT Name AS Customers FROM Customers
9 | LEFT JOIN Orders
10 | ON Customers.Id = Orders.CustomerId
11 | WHERE Orders.CustomerId IS NULL
12 | ```
13 |
14 | ### Links
15 |
16 | - [github.com/RodneyShag](https://github.com/RodneyShag)
17 |
--------------------------------------------------------------------------------
/Solutions/Delete Duplicate Emails.md:
--------------------------------------------------------------------------------
1 | ### Hint
2 |
3 | Use a [SELF JOIN](https://www.w3schools.com/sql/sql_join_self.asp)
4 |
5 | ### MySQL Solution
6 |
7 | ```sql
8 | DELETE p1
9 | FROM
10 | Person AS p1,
11 | Person AS p2
12 | WHERE
13 | p1.Email = p2.Email AND
14 | p1.Id > p2.Id
15 | ```
16 |
17 | ### Example
18 |
19 | Input:
20 |
21 | ```
22 | +----+------------------+
23 | | Id | Email |
24 | +----+------------------+
25 | | 1 | john@example.com |
26 | | 2 | bob@example.com |
27 | | 3 | john@example.com |
28 | +----+------------------+
29 | ```
30 |
31 | The table after the implicit join and the `WHERE p1.Email = p2.Email`:
32 |
33 | ```
34 | +-------+------------------+-------+------------------+
35 | | p1.Id | p1.Email | p2.Id | p2.Email
36 | +-------+------------------+-------+------------------+
37 | | 1 | john@example.com | 1 | john@example.com |
38 | | 3 | john@example.com | 1 | john@example.com |
39 | | 2 | bob@example.com | 1 | bob@example.com |
40 | | 1 | john@example.com | 3 | john@example.com |
41 | | 3 | john@example.com | 3 | john@example.com |
42 | +-------+------------------+-------+------------------+
43 | ```
44 | The following row matches the criteria of `p1.Id > p2.Id`:
45 |
46 | ```
47 | | 3 | john@example.com | 1 | john@example.com |
48 | ```
49 |
50 | In our original `p1` table this row will be deleted:
51 |
52 | ```
53 | | 3 | john@example.com |
54 | ```
55 |
56 | Now `p1` is our final table:
57 |
58 | ```
59 | +----+------------------+
60 | | Id | Email |
61 | +----+------------------+
62 | | 1 | john@example.com |
63 | | 2 | bob@example.com |
64 | +----+------------------+
65 | ```
66 |
67 | ### Links
68 |
69 | - [github.com/RodneyShag](https://github.com/RodneyShag)
70 |
--------------------------------------------------------------------------------
/Solutions/Delete Node in a Linked List.md:
--------------------------------------------------------------------------------
1 | ### Assumptions from Problem Description
2 |
3 | 1. "The given node will not be the tail and it will always be a valid node of the linked list" - Our trick below only works if the input node is not the tail of the list
4 | 1. "The linked list will have at least two elements" - However, we still check for 2+ element lists in the code
5 |
6 | ### Provided Code
7 |
8 | ```java
9 | public class ListNode {
10 | int val;
11 | ListNode next;
12 | }
13 | ```
14 |
15 | ### Solution
16 |
17 | ```java
18 | class Solution {
19 | public void deleteNode(ListNode n) {
20 | if (n == null || n.next == null) {
21 | return;
22 | }
23 | n.val = n.next.val;
24 | n.next = n.next.next;
25 | }
26 | }
27 | ```
28 |
29 | ### Time/Space Complexity
30 |
31 | - Time Complexity: O(1)
32 | - Space Complexity: O(1)
33 |
34 | ### Links
35 |
36 | - [github.com/RodneyShag](https://github.com/RodneyShag)
37 |
--------------------------------------------------------------------------------
/Solutions/Department Highest Salary.md:
--------------------------------------------------------------------------------
1 | ### MySQL Solution
2 |
3 | ```sql
4 | SELECT D.Name AS Department, E.Name AS Employee, E.Salary AS Salary
5 | FROM Employee AS E, Department AS D
6 | WHERE E.DepartmentId = D.Id AND
7 | E.Salary = (SELECT MAX(Salary) FROM Employee WHERE Employee.DepartmentId = D.Id)
8 | ```
9 |
10 | ### Notes
11 |
12 | The part after the `AND` finds the `MAX` salary for the `Department` we're interested in.
13 |
14 | ### Links
15 |
16 | - [github.com/RodneyShag](https://github.com/RodneyShag)
17 |
--------------------------------------------------------------------------------
/Solutions/Department Top Three Salaries.md:
--------------------------------------------------------------------------------
1 | ### MySQL Solution
2 |
3 | ```sql
4 | SELECT D.Name AS Department, E1.Name AS Employee, E1.Salary AS Salary
5 | FROM Employee AS E1, Department AS D
6 | WHERE E1.DepartmentId = D.Id AND
7 | (SELECT COUNT(DISTINCT E2.Salary)
8 | FROM Employee E2
9 | WHERE E1.DepartmentId = E2.DepartmentId AND
10 | E2.Salary > E1.Salary) < 3
11 | ```
12 |
13 | ### Notes
14 |
15 | The subquery `SELECT COUNT...` counts how many Employees `E2` have a salary greater than Employee `E1`. That value must be less than 3 for the `E1` salary to be in the top 3 salaries.
16 |
17 | ### Links
18 |
19 | - [github.com/RodneyShag](https://github.com/RodneyShag)
20 |
--------------------------------------------------------------------------------
/Solutions/Detect Capital.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | Use a "regular expression" (regex) by using [.matches()](https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#matches-java.lang.String-).
4 |
5 | - `[]` around a 'set' of characters is a match if any of the characters match.
6 | - `[A-Z]` matches any character from A to Z.
7 | - `*` means 0 or more of whatever precedes it
8 | - `|` means "or"
9 | - `.` matches any character
10 |
11 | ### Solution
12 |
13 | ```java
14 | class Solution {
15 | public boolean detectCapitalUse(String word) {
16 | if (word == null) {
17 | return false;
18 | }
19 | return word.matches("[A-Z]*|.[a-z]*");
20 | }
21 | }
22 | ```
23 |
24 | ### Time/Space Complexity
25 |
26 | - Time Complexity: O(n)
27 | - Space Complexity: O(1)
28 |
29 | ### Links
30 |
31 | - [github.com/RodneyShag](https://github.com/RodneyShag)
32 |
--------------------------------------------------------------------------------
/Solutions/Diameter of Binary Tree.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | Let's calculate the _depth_ of a tree for a root `TreeNode`. The [Maximum Depth of Binary Tree](https://leetcode.com/problems/maximum-depth-of-binary-tree) problem has a [solution](https://github.com/RodneyShag/LeetCode_solutions/blob/master/Solutions/Maximum%20Depth%20of%20Binary%20Tree.md) that shows how to do this.
4 |
5 | If at a root node (without using parents), the diameter is the maximum of either:
6 | 1. Max depth for Left Subtree + max depth for right subtree
7 | 1. Diameter of Left subtree (without using this `TreeNode`)
8 | 1. Diameter of Right subtree (without using this `TreeNode`)
9 |
10 | We visit every `TreeNode` recursively and calculate (1), saving the largest value we've found in `max`. Since we calculate this value for every `TreeNode`, we have indirectly calculated (2) and (3) as well. Our solution is the final value for `max`.
11 |
12 | ### Provided Code
13 |
14 | ```java
15 | class TreeNode {
16 | TreeNode left;
17 | TreeNode right;
18 | }
19 | ```
20 |
21 | ### Solution
22 |
23 | ```java
24 | class Solution {
25 | private int max = 0;
26 |
27 | public int diameterOfBinaryTree(TreeNode root) {
28 | maxDepth(root);
29 | return max;
30 | }
31 |
32 | private int maxDepth(TreeNode root) { // defines 1-TreeNode tree to have depth 1
33 | if (root == null) {
34 | return 0;
35 | }
36 | int L = maxDepth(root.left);
37 | int R = maxDepth(root.right);
38 | max = Math.max(max, L + R); // 'L+R' is diameter: L to root to R
39 | return 1 + Math.max(L, R);
40 | }
41 | }
42 | ```
43 |
44 | ### Implementation Notes
45 |
46 | For `max`, we used a global instance variable. Alternatively, you can [wrap the variable up in an array](https://leetcode.com/problems/diameter-of-binary-tree/discuss/101130/C%2B%2B-Java-Clean-Code) (or class) so changing its value is preserved between function calls.
47 |
48 | ### Time/Space Complexity
49 |
50 | - Time Complexity: O(n) since we must visit each node.
51 | - Space Complexity: O(log n) if balanced tree, O(n) otherwise. Space complexity is due to the recursion.
52 |
53 | ### Links
54 |
55 | - [github.com/RodneyShag](https://github.com/RodneyShag)
56 |
--------------------------------------------------------------------------------
/Solutions/Duplicate Emails.md:
--------------------------------------------------------------------------------
1 | ### Hints
2 |
3 | Use [GROUP BY](https://www.w3schools.com/sql/sql_groupby.asp) on `Email` to see how many of each `Id` there exists for each email.
4 |
5 | Use the [HAVING](https://www.w3schools.com/sql/sql_having.asp) clause since the `WHERE` clause doesn't support aggregate functions
6 |
7 | ### MySQL Solution
8 |
9 | ```sql
10 | SELECT Email FROM Person
11 | GROUP BY Email
12 | HAVING Count(Email) > 1
13 | ```
14 |
15 | ### Links
16 |
17 | - [github.com/RodneyShag](https://github.com/RodneyShag)
18 |
--------------------------------------------------------------------------------
/Solutions/Employees Earning More Than Their Managers.md:
--------------------------------------------------------------------------------
1 | ### Hint
2 |
3 | Use a [SELF JOIN](https://www.w3schools.com/sql/sql_join_self.asp)
4 |
5 | ### MySQL Solution
6 |
7 | ```sql
8 | SELECT
9 | a.Name AS Employee
10 | FROM
11 | Employee AS a,
12 | Employee AS b
13 | WHERE
14 | a.ManagerId = b.Id AND a.Salary > b.Salary
15 | ```
16 |
17 | ### Links
18 |
19 | - [github.com/RodneyShag](https://github.com/RodneyShag)
20 |
--------------------------------------------------------------------------------
/Solutions/Excel Sheet Column Number.md:
--------------------------------------------------------------------------------
1 | ### Notes
2 |
3 | - Our standard number system has digits 0 to 9, which is a _base 10_ system.
4 | - In this problem we have letters A to Z, so we would like to say this is a _base 26_ system. However, we have no way to represent 0, so the analogy to a "base something" system cannot be made.
5 |
6 | ### Solution
7 |
8 | ```java
9 | class Solution {
10 | public int titleToNumber(String s) {
11 | if (s == null) {
12 | return -1;
13 | }
14 | int num = 0;
15 | for (int i = 0; i < s.length(); i++) {
16 | num *= 26; // 26 possible letters
17 | num += s.charAt(i) - 'A' + 1;
18 | }
19 | return num;
20 | }
21 | }
22 | ```
23 |
24 | ### Time/Space Complexity
25 |
26 | - Time Complexity: O(n)
27 | - Space Complexity: O(1)
28 |
29 | ### Links
30 |
31 | - [github.com/RodneyShag](https://github.com/RodneyShag)
32 |
--------------------------------------------------------------------------------
/Solutions/Excel Sheet Column Title.md:
--------------------------------------------------------------------------------
1 | ### Notes
2 |
3 | - Our standard number system has digits 0 to 9, which is a _base 10_ system.
4 | - In this problem we have letters A to Z, so we would like to say this is a _base 26_ system. However, we have no way to represent 0, so the analogy to a "base something" system cannot be made.
5 |
6 | ### Solution
7 |
8 | ```java
9 | class Solution {
10 | public String convertToTitle(int n) {
11 | if (n <= 0) {
12 | return "";
13 | }
14 | StringBuffer sb = new StringBuffer();
15 | while (n > 0) {
16 | sb.append((char) ('A' + (n - 1) % 26));
17 | n = (n - 1) / 26;
18 | }
19 | return sb.reverse().toString();
20 | }
21 | }
22 | ```
23 |
24 | ### Additional Notes
25 |
26 | We used `.append()` (instead of inserting at the front) since `append()` is O(1) time. Since we build the string backwards, we reverse it before returning it.
27 |
28 | ### Details Explained
29 |
30 | 26 represents number of uppercase letters: A to Z.
31 |
32 | For the `(char) ('A' + (n - 1) % 26)` in above code:
33 |
34 | ```
35 | n: 1, 2, 3, ... 25, 26, 27, 28 ...
36 | n-1: 0, 1, 2, ... 24, 25, 26, 27 ...
37 | (n-1) % 26: 0, 1, 2, ... 24, 25, 0, 1 ...
38 | (char) ('A' + (n - 1) % 26): A, B, C, ... Y, Z, A, B ...
39 | ```
40 |
41 | For the `(n - 1) / 26`
42 |
43 | ```
44 | n: 1, 2, 3, ... 25, 26, 27, 28 ...
45 | (n - 1) / 26: 0, 0, 0, ... 0, 0, 1, 1 ...
46 | ```
47 |
48 | ### Example
49 |
50 | Let's use input `28` as an example.
51 |
52 | - The `(char) ('A' + (n - 1) % 26)` gives us value `B`.
53 | - The `n = (n - 1) / 26` updates our number to `1`.
54 | - The `(char) ('A' + (n - 1) % 26)` gives us value `A`.
55 | - Our `StringBuffer` is now `BA`. We reverse it to get `AB`
56 |
57 | ### Time/Space Complexity
58 |
59 | - Time Complexity: O(log n)
60 | - Space Complexity: O(log n)
61 |
62 | ### Links
63 |
64 | - [github.com/RodneyShag](https://github.com/RodneyShag)
65 |
--------------------------------------------------------------------------------
/Solutions/Exchange Seats.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | There are 3 cases
4 | 1. For students with even-numbered ids, subtract 1 from their id
5 | 1. For students with odd-numbered ids, add 1 to their id (Except if this odd-numbered student has the highest id in the class
6 | 1. For student with odd-numbered id who also has the highest id in the class, don't change the id.
7 |
8 | ### MySQL Solution
9 |
10 | ```sql
11 | SELECT
12 | CASE
13 | WHEN id % 2 = 0 THEN id - 1
14 | WHEN id % 2 = 1 AND id != (SELECT COUNT(*) FROM seat) THEN id + 1
15 | ELSE id
16 | END as id,
17 | student
18 | FROM seat
19 | ORDER BY id
20 | ```
21 |
22 | ### Links
23 |
24 | - [github.com/RodneyShag](https://github.com/RodneyShag)
25 |
--------------------------------------------------------------------------------
/Solutions/Factorial Trailing Zeroes.md:
--------------------------------------------------------------------------------
1 | ### Tips
2 |
3 | 1. We can't simply multiply out n! and count number of 0s since n! may be too big to fit in an int/long.
4 | 1. Trailing 0's are created by 2's and 5's. Since we will always have more 2's than 5's, the 5's will determine # of 0's.
5 | 1. 1 solution is to count # of factors of 5's in each term of the factorial (1...n), however, this is a time-intensive solution
6 | 1. Instead, count multiples of 5 (btwn 1 and n), then multiples of 25, then 125... using a `for` loop that gives us `n/5 + n/25 + n/125 + n/625 + ...;`
7 |
8 |
9 | ```
10 | Special numbers:
11 | 5 = 5
12 | 25 = 5 x 5
13 | 125 = 5 x 5 x 5
14 | 625 = 5 x 5 x 5 x 5
15 | ```
16 |
17 | ### Solution
18 | ```java
19 | int numTrailingZeros(int n) {
20 | if (n < 1) {
21 | return 0;
22 | }
23 | int fives = 0;
24 | for (long i = 5; i <= n; i *= 5) { // i is 5, 25, 125, 625 ...
25 | fives += n/i; // to count how many multiples of "i" are in range 1...n, we just do n/i
26 | }
27 | return fives;
28 | }
29 | ```
30 |
31 | ### Implementation Notes
32 |
33 | Must use `long i` to prevent integer overflow from the `i *= 5`
34 |
35 | ### Time/Space Complexity
36 |
37 | - Time Complexity: O(log n)
38 | - Space Complexity: O(1)
39 |
40 | ### Links
41 |
42 | - [github.com/RodneyShag](https://github.com/RodneyShag)
43 |
--------------------------------------------------------------------------------
/Solutions/Find All Duplicates in an Array.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | 1. Loop through the input array to save the number of times each `int` appears, into a `Map`
4 | 1. Loop through the `Map` to see which elements appear twice.
5 |
6 | ### Solution
7 |
8 | ```java
9 | class Solution {
10 | public List findDuplicates(int[] nums) {
11 | Map map = new HashMap();
12 | List list = new ArrayList();
13 | for (int i = 0; i < nums.length; i++) {
14 | map.merge(nums[i], 1, Integer::sum);
15 | }
16 | for (int key : map.keySet()) {
17 | if (map.get(key) == 2) {
18 | list.add(key);
19 | }
20 | }
21 | return list;
22 | }
23 | }
24 | ```
25 |
26 | ### Time/Space Complexity
27 |
28 | - Time Complexity: O(n)
29 | - Space Complexity: O(n)
30 |
31 | ### Follow-up Question
32 |
33 | The follow-up question asks to "do it without extra space and O(n) runtime", but since we still need O(n) space for the returned list, I don't see a practical reason to solve this problem with the follow-up added restriction.
34 |
35 | ### Links
36 |
37 | - [github.com/RodneyShag](https://github.com/RodneyShag)
38 |
--------------------------------------------------------------------------------
/Solutions/Find All Numbers Disappeared in an Array.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | 1. Create a Set of elements with values 1 to n (inclusive)
4 | 1. Loop through input array to remove corresponding elements from our Set.
5 |
6 | ### Solution
7 |
8 | ```java
9 | class Solution {
10 | public List findDisappearedNumbers(int[] nums) {
11 | Set set = new HashSet();
12 | for (int i = 1; i <= nums.length; i++) {
13 | set.add(i);
14 | }
15 | for (int num : nums) {
16 | set.remove(num);
17 | }
18 | return new ArrayList(set);
19 | }
20 | }
21 | ```
22 |
23 | ### Time/Space Complexity
24 |
25 | - Time Complexity: O(n)
26 | - Space Complexity: O(n)
27 |
28 | ### Follow-up Question
29 |
30 | The follow-up question asks to "do it without extra space and O(n) runtime", but since we still need O(n) space for the returned list, I don't see a practical reason to solve this problem with the follow-up added restriction.
31 |
32 | ### Links
33 |
34 | - [github.com/RodneyShag](https://github.com/RodneyShag)
35 |
--------------------------------------------------------------------------------
/Solutions/Find Peak Element.md:
--------------------------------------------------------------------------------
1 | ### Notes
2 |
3 | - We are given `nums[-1] = nums[n] = negative infinity`. This ensures we have at least 1 local maximum.
4 | - A simple O(n) solution exists by checking each element linearly, but let's try to solve it in O(log n) instead.
5 |
6 | ### Algorithm
7 |
8 | - The key insight is that we only need to find 1 peak element. _Any_ peak element will do.
9 | - By doing binary search and comparing `A[mid]` to `A[mid + 1]`, we can see which side has a guaranteed peak maximum and recurse on just that side.
10 |
11 | ### Solution
12 |
13 | ```java
14 | class Solution {
15 | public int findPeakElement(int[] nums) {
16 | int start = 0;
17 | int end = nums.length - 1;
18 | while (start < end) {
19 | int mid = (start + end) / 2;
20 | if (nums[mid] > nums[mid + 1]) {
21 | end = mid;
22 | } else {
23 | start = mid + 1;
24 | }
25 | }
26 | return start;
27 | }
28 | }
29 | ```
30 |
31 | ### Time/Space Complexity
32 |
33 | - Time Complexity: O(log n)
34 | - Space Complexity: O(1)
35 |
36 | ### Links
37 |
38 | - [github.com/RodneyShag](https://github.com/RodneyShag)
39 |
--------------------------------------------------------------------------------
/Solutions/Find the Difference.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | If you XOR 2 identical characters by using `^`, you get 0. If we XOR all the characters in the 2 `String`s, all characters that are duplicates will be removed, and we will be left with the only character that occurs once.
4 |
5 | ### Solution
6 |
7 | ```java
8 | class Solution {
9 | public char findTheDifference(String s, String t) { // assumes non-null input
10 | char c = 0;
11 | for (int i = 0; i < s.length(); i++) {
12 | c ^= s.charAt(i);
13 | }
14 | for (int i = 0; i < t.length(); i++) {
15 | c ^= t.charAt(i);
16 | }
17 | return c;
18 | }
19 | }
20 | ```
21 |
22 | ### Time/Space Complexity
23 |
24 | - Time Complexity: O(s + t)
25 | - Space Complexity: O(1)
26 |
27 | ### Links
28 |
29 | - [github.com/RodneyShag](https://github.com/RodneyShag)
30 |
--------------------------------------------------------------------------------
/Solutions/First Bad Version.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | There is just 1 place in the array where the versions go from "good" to "bad". We can use a modified version of [binary search](https://github.com/RodneyShag/LeetCode_solutions/blob/master/Solutions/Binary%20Search.md) to find this location.
4 |
5 | ### Provided Code
6 |
7 | `boolean isBadVersion(int version)` is defined in the parent class `VersionControl`.
8 |
9 | ### Solution
10 |
11 | ```java
12 | public class Solution extends VersionControl {
13 | public int firstBadVersion(int n) {
14 | int lo = 1;
15 | int hi = n;
16 | while (lo < hi) {
17 | int mid = lo + (hi - lo) / 2;
18 | if (isBadVersion(mid)) {
19 | hi = mid;
20 | } else {
21 | lo = mid + 1;
22 | }
23 | }
24 | return hi;
25 | }
26 | }
27 | ```
28 |
29 | ### Implementation Details
30 |
31 | Instead of calculating the middle value as `mid = (lo + hi) / 2`, do `mid = lo + (hi - lo) / 2` to avoid integer overflow
32 |
33 | ### Time/Space Complexity
34 |
35 | - Time Complexity: O(log n)
36 | - Space Complexity: O(1)
37 |
38 | ### Links
39 |
40 | - [github.com/RodneyShag](https://github.com/RodneyShag)
41 |
--------------------------------------------------------------------------------
/Solutions/First Unique Character in a String.md:
--------------------------------------------------------------------------------
1 | ### Solution
2 |
3 | ```java
4 | class Solution {
5 | public int firstUniqChar(String s) {
6 | if (s == null || s.length() == 0) {
7 | return -1;
8 | }
9 |
10 | HashMap counts = new HashMap();
11 |
12 | // Save counts of characters
13 | for (int i = 0; i < s.length(); i++) {
14 | char ch = s.charAt(i);
15 | counts.merge(ch, 1, Integer::sum);
16 | }
17 |
18 | // Find 1st unique character
19 | for (int i = 0; i < s.length(); i++) {
20 | char ch = s.charAt(i);
21 | if (counts.get(ch) == 1) {
22 | return i;
23 | }
24 | }
25 | return -1;
26 | }
27 | }
28 | ```
29 |
30 | ### Time/Space Complexity
31 |
32 | - Time Complexity: O(n)
33 | - Space Complexity: O(1) since we have a finite number of characters (ASCII or Unicode) to store in a `HashMap`
34 |
35 | ### Links
36 |
37 | - [github.com/RodneyShag](https://github.com/RodneyShag)
38 |
--------------------------------------------------------------------------------
/Solutions/Fizz Buzz.md:
--------------------------------------------------------------------------------
1 | ### Solution
2 |
3 | ```java
4 | class Solution {
5 | public List fizzBuzz(int n) {
6 | List list = new ArrayList();
7 |
8 | for (int num = 1; num <= n; num++) {
9 | boolean divisibleBy3 = (num % 3 == 0);
10 | boolean divisibleBy5 = (num % 5 == 0);
11 |
12 | if (divisibleBy3 && divisibleBy5) {
13 | list.add("FizzBuzz");
14 | } else if (divisibleBy3) {
15 | list.add("Fizz");
16 | } else if (divisibleBy5) {
17 | list.add("Buzz");
18 | } else {
19 | list.add(String.valueOf(num));
20 | }
21 | }
22 | return list;
23 | }
24 | }
25 | ```
26 |
27 | ### Time/Space Complexity
28 |
29 | - Time Complexity: O(n)
30 | - Space Complexity: O(1)
31 |
32 | ### Links
33 |
34 | - [github.com/RodneyShag](https://github.com/RodneyShag)
35 |
--------------------------------------------------------------------------------
/Solutions/Flood Fill.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | Use Depth-First Search (DFS) to fill the image.
4 |
5 | Need to check `image[startRow][startCol] == newColor` before we start DFS, as otherwise we will be in an infinite loop.
6 |
7 | ### Solution
8 |
9 | ```java
10 | class Solution {
11 | public int[][] floodFill(int[][] image, int startRow, int startCol, int newColor) {
12 | if (image == null || image[startRow][startCol] == newColor) {
13 | return image;
14 | }
15 | fill(image, startRow, startCol, newColor, image[startRow][startCol]);
16 | return image;
17 | }
18 |
19 | private void fill(int[][] image, int r, int c, int newColor, int firstColor) {
20 | if (r < 0 || r >= image.length || c < 0 || c >= image[0].length) {
21 | return;
22 | }
23 | if (image[r][c] == firstColor) {
24 | image[r][c] = newColor;
25 | fill(image, r - 1, c, newColor, firstColor);
26 | fill(image, r + 1, c, newColor, firstColor);
27 | fill(image, r, c - 1, newColor, firstColor);
28 | fill(image, r, c + 1, newColor, firstColor);
29 | }
30 | }
31 | }
32 | ```
33 |
34 | ### Time/Space Complexity
35 |
36 | - Time Complexity: O(rows * cols)
37 | - Space Complexity: O(rows * cols) due to recursion
38 |
39 | ### Links
40 |
41 | - [github.com/RodneyShag](https://github.com/RodneyShag)
42 |
--------------------------------------------------------------------------------
/Solutions/Generate Parentheses.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | - Use "Backtracking" - an algorithm for finding all solutions by exploring all potential candidates.
4 | - While building our `expression` left to right, for every index `i`, we must ensure the number of right parenthesis never exceed the number of left parenthesis in the range [0, i]
5 |
6 | ### Solution
7 |
8 | ```java
9 | class Solution {
10 | public List generateParenthesis(int n) {
11 | List solutions = new ArrayList();
12 | addParenthesis(new char[n * 2], 0, n, n, solutions);
13 | return solutions;
14 | }
15 |
16 | private void addParenthesis(char[] expression, int index, int leftRem, int rightRem, List solutions) {
17 | if (leftRem == 0 && rightRem == 0) {
18 | solutions.add(new String(expression));
19 | return;
20 | }
21 | if (leftRem > 0) {
22 | expression[index] = '(';
23 | addParenthesis(expression, index + 1, leftRem - 1, rightRem, solutions);
24 | }
25 | if (rightRem > 0 && rightRem > leftRem) {
26 | expression[index] = ')';
27 | addParenthesis(expression, index + 1, leftRem, rightRem - 1, solutions);
28 | }
29 | }
30 | }
31 | ```
32 |
33 | ### Implementation Details
34 |
35 | A `char[]` was used instead of a `StringBuffer` to remove necessity of including a "remove" for every "add" to our expression (when coming out of the recursive call)
36 |
37 | ### Time/Space Complexity
38 |
39 | - Time Complexity: O(2n)
40 | - Space Complexity: O(2n)
41 |
42 | However, the official LeetCode solutions there is a very difficult mathematical proof to get a tighter bound on the time/space complexity, by using "Catalan" numbers. You are not expected to know this for an interview.
43 |
44 | ### Links
45 |
46 | - [github.com/RodneyShag](https://github.com/RodneyShag)
47 |
--------------------------------------------------------------------------------
/Solutions/Hamming Distance.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | XOR has a value of 1 only when 2 bits are different:
4 |
5 | ```
6 | XOR
7 |
8 | a b a ^ b
9 | -------------
10 | 0 0 0
11 | 0 1 1
12 | 1 0 1
13 | 1 1 0
14 | ```
15 |
16 | 1. Use XOR as `x ^ y`
17 | 1. The number of bits set as `1` in `x ^ y` is our solution
18 |
19 | ### Solution
20 |
21 | ```java
22 | class Solution {
23 | public int hammingDistance(int x, int y) {
24 | return Integer.bitCount(x ^ y);
25 | }
26 | }
27 | ```
28 |
29 | ### Time/Space Complexity
30 |
31 | - Time Complexity: O(1)
32 | - Space Complexity: O(1)
33 |
34 | ### Links
35 |
36 | - [github.com/RodneyShag](https://github.com/RodneyShag)
37 |
--------------------------------------------------------------------------------
/Solutions/Happy Number.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | This is similar to [LeetCode #141 - Linked List Cycle](https://leetcode.com/problems/linked-list-cycle). We will reuse the [algorithm from that problem](https://github.com/RodneyShag/LeetCode_solutions/blob/master/Solutions/Linked%20List%20Cycle.md) to detect cycles.
4 |
5 | 1. Create `slow`. It will move 1 step at a time.
6 | 1. Create `fast`. It will move 2 steps at a time.
7 | 1. We will keep generating numbers until either
8 | 1. We generate `1` (we have a "happy number"), or
9 | 1. `slow` and `fast` collide (we don't have a "happy number").
10 |
11 | ### Solution
12 |
13 | ```java
14 | class Solution {
15 | public boolean isHappy(int n) {
16 | if (n <= 0) {
17 | return false;
18 | }
19 | int slow = n;
20 | int fast = digitSquareSum(n); // setting fast to n would cause an immediate `slow == fast` collision
21 |
22 | while (fast != 1 && slow != fast) {
23 | slow = digitSquareSum(slow);
24 | fast = digitSquareSum(fast);
25 | fast = digitSquareSum(fast);
26 | }
27 |
28 | return fast == 1;
29 | }
30 |
31 | private int digitSquareSum(int n) {
32 | int sum = 0;
33 | while (n > 0) {
34 | int digit = n % 10;
35 | sum += digit * digit;
36 | n /= 10;
37 | }
38 | return sum;
39 | }
40 | }
41 | ```
42 |
43 | ### Time Complexity
44 |
45 | #### If number of bits in `int n` is capped at 32 by Java
46 |
47 | `O(1)`
48 |
49 | #### If number of bits in `int n` is allowed to grow
50 |
51 | - `digitSquareSum()` will be `O(log n)`
52 | - When (or if) `while (fast != 1 && slow != fast)` terminates as `n` increases needs a mathematical proof that won't be necessary in an interview.
53 | - This gives us `O(log n) < time complexity < ???`
54 |
55 | ### Space Complexity
56 |
57 | `O(1)`
58 |
59 | ### Links
60 |
61 | - [github.com/RodneyShag](https://github.com/RodneyShag)
62 |
--------------------------------------------------------------------------------
/Solutions/Implement Queue using Stacks.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | - `stack1` will accept input elements for `push()`
4 | - `stack2` will output elements for `pop()`, `peek()`
5 | - when trying to do a `pop()` or `peek()` on our queue, if `stack2` is empty, we will move all elements from `stack1` to `stack2`. This will reverse the order of the elements, giving us the correct order when we call `pop()` or `peek()` on our queue.
6 |
7 | ### Solution
8 |
9 | ```java
10 | class MyQueue {
11 | private Stack stack1 = new Stack();
12 | private Stack stack2 = new Stack();
13 |
14 | public void push(int x) {
15 | stack1.push(x);
16 | }
17 |
18 | public int pop() {
19 | if (stack2.isEmpty()) {
20 | shiftStacks();
21 | }
22 | return stack2.pop();
23 | }
24 |
25 | public int peek() {
26 | if (stack2.isEmpty()) {
27 | shiftStacks();
28 | }
29 | return stack2.peek();
30 | }
31 |
32 | public boolean empty() {
33 | return stack1.isEmpty() && stack2.isEmpty();
34 | }
35 |
36 | private void shiftStacks() {
37 | while (!stack1.isEmpty()) {
38 | int temp = stack1.pop();
39 | stack2.push(temp);
40 | }
41 | }
42 | }
43 | ```
44 |
45 | ### Implementation Notes
46 |
47 | - LeetCode problem statement says it will not perform invalid operations such as `peek()` or `pop()` on an empty stack. A more general solution should check for an empty queue in `peek()` and `pop()`, and if the queue is empty, either:
48 | 1. throw an error
49 | 1. return null (which would require changing the return value from `int` to `Integer`)
50 | - `add()` is a better name than `push()` for a queue.
51 | - `remove()` is a better name than `pop()` for a queue.
52 |
53 | ### Time/Space Complexity
54 |
55 | - Time Complexity: O(1) _amortized_ time for `push()`, `pop()`, `peek()`, `empty()`, as each element is only moved from `stack1` to `stack2` at most once.
56 | - Space Complexity: O(1) for each element being put into our queue.
57 |
58 | ### Links
59 |
60 | - [github.com/RodneyShag](https://github.com/RodneyShag)
61 |
--------------------------------------------------------------------------------
/Solutions/Integer to English Words.md:
--------------------------------------------------------------------------------
1 | ### Tricks
2 |
3 | - Use arrays as data structure for the words.
4 | - Split the number at each comma into groups of 3 digits. Create a function to convert 3-digit numbers to words.
5 | - Don't forget to consider negative numbers, and 0.
6 |
7 | ### Solution
8 |
9 | ```java
10 | class Solution {
11 | private String[] first20 = {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"};
12 | private String[] tens = {"", "Ten", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};
13 | private String[] bigs = {"", "Thousand", "Million", "Billion"};
14 |
15 | public String numberToWords(int num) {
16 | if (num < 0) {
17 | return "Negative " + numberToWords(-1 * num);
18 | } else if (num == 0) {
19 | return "Zero";
20 | }
21 |
22 | int bigsIndex = 0;
23 | StringBuffer sb = new StringBuffer();
24 |
25 | // Create the string from right to left, inserting in the front.
26 | while (num > 0) {
27 | if (num % 1000 != 0) {
28 | sb.insert(0, numToWords100(num % 1000) + bigs[bigsIndex] + " ");
29 | }
30 | num /= 1000;
31 | bigsIndex++;
32 | }
33 |
34 | return sb.toString().trim();
35 | }
36 |
37 | private String numToWords100(int num) { // assumes 0 < num < 1000
38 | if (num == 0) {
39 | return "";
40 | } else if (num < 20) {
41 | return first20[num] + " ";
42 | } else if (num < 100) {
43 | return tens[num / 10] + " " + numToWords100(num % 10);
44 | } else {
45 | return first20[num / 100] + " Hundred " + numToWords100(num % 100);
46 | }
47 | }
48 | }
49 | ```
50 |
51 | ### Time/Space Complexity
52 |
53 | - Time Complexity: O(1)
54 | - Space Complexity: O(1)
55 |
56 | ### Links
57 |
58 | - [github.com/RodneyShag](https://github.com/RodneyShag)
59 |
--------------------------------------------------------------------------------
/Solutions/Intersection of Two Arrays.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | 1. Make a `Set` with numbers from `nums1`
4 | 1. Make a `Set` with numbers from `nums2`
5 | 1. The "set union" of these 2 sets is our solution. In Java we use the `retainAll()` for set union.
6 | 1. Since our return value must be an array, convert our solution set into an array.
7 |
8 | ### Solution
9 |
10 | ```java
11 | class Solution {
12 | public int[] intersection(int[] nums1, int[] nums2) {
13 | Set set1 = new HashSet();
14 | for (Integer n : nums1) {
15 | set1.add(n);
16 | }
17 | Set set2 = new HashSet();
18 | for (Integer n : nums2) {
19 | set2.add(n);
20 | }
21 |
22 | set1.retainAll(set2); // set1 becomes union of set1 and set2
23 |
24 | int[] output = new int[set1.size()];
25 | int i = 0;
26 | for (int num : set1) {
27 | output[i++] = num;
28 | }
29 | return output;
30 | }
31 | }
32 | ```
33 |
34 | ### Time/Space Complexity
35 |
36 | - Time Complexity: O(n + m)
37 | - Space Complexity: O(n + m)
38 |
39 | ### Links
40 |
41 | - [github.com/RodneyShag](https://github.com/RodneyShag)
42 |
--------------------------------------------------------------------------------
/Solutions/Intersection of Two linked Lists.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | - Let "tail" refer to the first null at the end of the list.
4 | - Create a pointer that iterates through a list.
5 | - When it's at the tail of the list, have it jump to the beginning of the other list.
6 | - Create 2 of these pointers, pointing to 2 different list heads.
7 | - The pointers will collide at the merge point after 1 or 2 passes.
8 | - If they don't collide after 2 passes, then they will both be null, and there is no merge point.
9 |
10 | ### Provided Code
11 |
12 | ```java
13 | public class ListNode {
14 | ListNode next;
15 | }
16 | ```
17 |
18 | ### Solution
19 |
20 | ```java
21 | public class Solution {
22 | public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
23 | if (headA == null || headB == null) {
24 | return null;
25 | }
26 | ListNode a = headA;
27 | ListNode b = headB;
28 | while (a != b) {
29 | a = (a == null) ? headB : a.next;
30 | b = (b == null) ? headA : b.next;
31 | }
32 | return a;
33 | }
34 | }
35 | ```
36 |
37 |
38 | ### Time/Space Complexity
39 |
40 | - Time Complexity: O(m + n)
41 | - Space Complexity: O(1)
42 |
43 | ### Links
44 |
45 | - [github.com/RodneyShag](https://github.com/RodneyShag)
46 |
--------------------------------------------------------------------------------
/Solutions/Invert Binary Tree.md:
--------------------------------------------------------------------------------
1 | ### Provided Code
2 |
3 | ```java
4 | class TreeNode {
5 | TreeNode left;
6 | TreeNode right;
7 | }
8 | ```
9 |
10 | ### Solution
11 |
12 | ```java
13 | class Solution {
14 | public TreeNode invertTree(TreeNode root) {
15 | if (root == null) {
16 | return null;
17 | }
18 | TreeNode left = invertTree(root.left);
19 | TreeNode right = invertTree(root.right);
20 | root.left = right;
21 | root.right = left;
22 | return root;
23 | }
24 | }
25 | ```
26 |
27 | ### Time/Space Complexity
28 |
29 | - Time Complexity: O(n) since we must visit every TreeNode.
30 | - Space Complexity: O(log n) if balanced tree. O(n) otherwise.
31 |
32 | ### Links
33 |
34 | - [github.com/RodneyShag](https://github.com/RodneyShag)
35 |
--------------------------------------------------------------------------------
/Solutions/Jewels and Stones.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | 1. Put jewels in a `Set` for O(1) access.
4 | 1. For each stone, check if it is a jewel.
5 |
6 | ### Solution
7 |
8 | ```java
9 | class Solution {
10 | public int numJewelsInStones(String j, String s) {
11 | Set jewels = new HashSet();
12 | for (int i = 0; i < j.length(); i++) {
13 | jewels.add(j.charAt(i));
14 | }
15 | int count = 0;
16 | for (int i = 0; i < s.length(); i++) {
17 | if (jewels.contains(s.charAt(i))) {
18 | count++;
19 | }
20 | }
21 | return count;
22 | }
23 | }
24 | ```
25 |
26 | ### Time/Space Complexity
27 |
28 | - Time Complexity: O(j + s)
29 | - Space Complexity: O(j)
30 |
31 | ### Links
32 |
33 | - [github.com/RodneyShag](https://github.com/RodneyShag)
34 |
--------------------------------------------------------------------------------
/Solutions/Keyboard Row.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | Use a "regular expression" (regex) by using [.matches()](https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#matches-java.lang.String-).
4 |
5 | - `[]` around a 'set' of characters is a match if any of the characters match
6 | - `+` means 1 or more of whatever precedes it. We can alternatively use `*` which means 0 or more.
7 | - `|` means "or"
8 |
9 | ### Solution
10 |
11 | ```java
12 | class Solution {
13 | public String[] findWords(String[] words) {
14 | if (words == null) {
15 | return null;
16 | }
17 | List list = new ArrayList();
18 | for (String word : words) {
19 | if (word.toLowerCase().matches("[qwertyuiop]+|[asdfghjkl]+|[zxcvbnm]+")) {
20 | list.add(word);
21 | }
22 | }
23 | return list.toArray(new String[list.size()]);
24 | }
25 | }
26 | ```
27 |
28 | ### Time/Space Complexity
29 |
30 | - Time Complexity: O(n) where n is the number of words
31 | - Space Complexity: O(1)
32 |
33 | ### Links
34 |
35 | - [github.com/RodneyShag](https://github.com/RodneyShag)
36 |
--------------------------------------------------------------------------------
/Solutions/Kth Largest Element in a Stream.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | Use a min heap (which in Java is a `PriorityQueue`) to keep track of the `k` largest numbers, where the minimum of the min heap will represent the `k-th` largest number
4 |
5 | ### Example
6 |
7 | Here is the sample input from the problem:
8 | ```
9 | int k = 3;
10 | int[] arr = [4,5,8,2];
11 | KthLargest kthLargest = new KthLargest(3, arr);
12 | kthLargest.add(3); // returns 4
13 | kthLargest.add(5); // returns 5
14 | kthLargest.add(10); // returns 5
15 | kthLargest.add(9); // returns 8
16 | kthLargest.add(4); // returns 8
17 | ```
18 |
19 | Each line below corresponds to reading in 1 input from the stream. The brackets [] are used to show the values in the min heap:
20 | ```
21 | [4]
22 | [4 5]
23 | [4 5 8]
24 | 2 [4 5 8] // at this step, constructor has finished executing
25 | 2 3 [4 5 8] // returns 4
26 | 2 3 4 [5 5 8] // returns 5
27 | 2 3 4 5 [5 8 10] // returns 5
28 | 2 3 4 5 5 [8 9 10] // returns 8
29 | 2 3 4 4 5 5 [8 9 10] // returns 8
30 | ```
31 |
32 | ### Solution
33 |
34 | ```java
35 | class KthLargest {
36 | private Queue pq;
37 | private int k;
38 |
39 | public KthLargest(int k, int[] nums) {
40 | pq = new PriorityQueue(k + 1);
41 | this.k = k;
42 | for (int num : nums) {
43 | add(num);
44 | }
45 | }
46 |
47 | public int add(int val) {
48 | pq.add(val);
49 | if (pq.size() == k + 1) {
50 | pq.remove();
51 | }
52 | return pq.peek();
53 | }
54 | }
55 | ```
56 |
57 | ### Time Complexity
58 |
59 | - add() is O(log k)
60 | - the constructor KthLargest() is O(n log k)
61 |
62 | ### Space Complexity
63 |
64 | O(k) due to the size of the heap.
65 |
66 | ### Links
67 |
68 | - [github.com/RodneyShag](https://github.com/RodneyShag)
69 |
--------------------------------------------------------------------------------
/Solutions/Largest 1-Bordered Square.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | 1. Preprocess the data: create 2 additional matrices.
4 | - In `left[][]`, for each cell, we store the number of ones immediately at left (and itself)
5 | - In `up[][]`, for each cell, we store the number of ones immediately above (and itself)
6 |
7 | ```
8 | grid[3][3] = 1 1 1 left[3][3] = 1 2 3 up[3][3] = 1 1 1
9 | 1 0 1 1 0 1 2 0 2
10 | 1 1 1 1 2 3 3 1 3
11 | ```
12 | 2. Search for largest squares first. Loop through our `grid`. Treat each cell as a top-left corner of a square, and check if a valid square can be made from there.
13 |
14 | ### Solution
15 |
16 | ```java
17 | class Solution {
18 | public int largest1BorderedSquare(int[][] grid) {
19 | int rows = grid.length;
20 | int cols = grid[0].length;
21 |
22 | int[][] left = new int[rows][cols];
23 | int[][] up = new int[rows][cols];
24 |
25 | for (int r = 0; r < rows; r++) {
26 | for (int c = 0; c < cols; c++) {
27 | if (grid[r][c] == 1) {
28 | left[r][c] = (c == 0) ? 1 : left[r][c - 1] + 1;
29 | up[r][c] = (r == 0) ? 1 : up[r - 1][c] + 1;
30 | }
31 | }
32 | }
33 |
34 | for (int side = Math.min(rows, cols); side > 0; side--) {
35 | for (int r = 0; r + side - 1 < rows; r++) {
36 | for (int c = 0; c + side - 1 < cols; c++) {
37 | if (left[r][c + side - 1] >= side
38 | && left[r + side - 1][c + side - 1] >= side
39 | && up[r + side - 1][c] >= side
40 | && up[r + side - 1][c + side - 1] >= side) {
41 | return side * side;
42 | }
43 | }
44 | }
45 | }
46 | return 0;
47 | }
48 | }
49 | ```
50 |
51 | ### Time/Space Complexity
52 |
53 | - Time Complexity: O(n3) due to 3 nested "for" loops
54 | - Space Complexity: O(n2) due to preprocessing
55 |
56 | ### Links
57 |
58 | - [github.com/RodneyShag](https://github.com/RodneyShag)
59 |
--------------------------------------------------------------------------------
/Solutions/Largest Perimeter Triangle.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | For a triangle to have non-zero area, the 2 shorter sides must sum to be larger than the larger side.
4 |
5 | 1. Sort the array - the larger numbers will be at the end of the array
6 | 1. Grab triplets in decreasing order of size (right-to-left in array) and see if they form a valid triangle
7 |
8 | ### Solution
9 |
10 | ```java
11 | class Solution {
12 | public int largestPerimeter(int[] A) {
13 | Arrays.sort(A);
14 | for (int i = A.length - 1; i >= 2; i--) {
15 | if (A[i - 2] + A[i - 1] > A[i]) {
16 | return A[i - 2] + A[i - 1] + A[i];
17 | }
18 | }
19 | return 0;
20 | }
21 | }
22 | ```
23 |
24 | ### Time/Space Complexity
25 |
26 | - Time Complexity: `O(n log n)` due to Arrays.sort()
27 | - Space Complexity: Depends on space complexity of `Arrays.sort()`, which can be as low as `O(1)`.
28 |
29 | ### Links
30 |
31 | - [github.com/RodneyShag](https://github.com/RodneyShag)
32 |
--------------------------------------------------------------------------------
/Solutions/Length of Last Word.md:
--------------------------------------------------------------------------------
1 | ### Solution
2 |
3 | ```java
4 | class Solution {
5 | public int lengthOfLastWord(String s) {
6 | if (s == null) {
7 | return 0;
8 | }
9 | s = s.trim();
10 | for (int i = s.length() - 1; i >= 0; i--) {
11 | if (s.charAt(i) == ' ') {
12 | return s.length() - 1 - i;
13 | }
14 | }
15 | return s.length();
16 | }
17 | }
18 | ```
19 |
20 | ### Time/Space Complexity
21 |
22 | - Time Complexity: O(n)
23 | - Space Complexity: O(n)
24 |
25 | # Links
26 |
27 | - [github.com/RodneyShag](https://github.com/RodneyShag)
28 |
--------------------------------------------------------------------------------
/Solutions/Linked List Cycle II.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | 1. `k` = # of nodes from beginning of list to beginning of loop
4 | 1. `n` = loop size
5 | 1. Create a `slow` pointer (moves 1 step at a time) and a `fast` pointer (moves 2 steps at a time) .
6 | 1. When `slow` enters loop (after `k` nodes), `fast` is k nodes into the list.
7 | 1. That means they will meet in `n - k` steps (Since they get 1 step closer each time).
8 | 1. When they meet, `slow` is `n - k` steps into the loop, so `slow` will be at beginning of loop in `k` single steps.
9 | 1. Create `slow2` at head of list, and move `slow` and `slow2` 1 step at a time, they will collide in `k` steps, at the head of cycle.
10 |
11 | ### Provided Code
12 |
13 | ```java
14 | class ListNode {
15 | ListNode next;
16 | }
17 | ```
18 |
19 | ### Solution
20 |
21 | ```java
22 | public class Solution {
23 | public ListNode detectCycle(ListNode head) {
24 | ListNode slow = head;
25 | ListNode fast = head;
26 |
27 | while (fast != null && fast.next != null) {
28 | slow = slow.next;
29 | fast = fast.next.next;
30 | if (slow == fast) { // they collided
31 | ListNode slow2 = head;
32 | while (slow2 != slow) {
33 | slow = slow.next;
34 | slow2 = slow2.next;
35 | }
36 | return slow;
37 | }
38 | }
39 | return null;
40 | }
41 | }
42 | ```
43 |
44 | ### Time/Space Complexity
45 |
46 | - Time Complexity: O(n), where n is number of nodes in List.
47 | - Space Complexity: O(1)
48 |
49 | ### Links
50 |
51 | - [github.com/RodneyShag](https://github.com/RodneyShag)
52 |
--------------------------------------------------------------------------------
/Solutions/Linked List Cycle.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | 1. Create a pointer that moves 1 step at a time: `slow`
4 | 1. Create a pointer that moves 2 steps at a time: `fast`
5 | 1. If the Linked List has a cycle, `slow` and `fast` will collide.
6 |
7 | ### Provided code
8 |
9 | ```java
10 | class ListNode {
11 | ListNode next;
12 | }
13 | ```
14 |
15 | ### Solution
16 |
17 | ```java
18 | class Solution {
19 | public boolean hasCycle(ListNode head) {
20 | if (head == null) {
21 | return false;
22 | }
23 |
24 | ListNode slow = head; // moves 1 ListNode at a time
25 | ListNode fast = head; // moves 2 ListNodes at a time
26 |
27 | while (fast != null && fast.next != null) {
28 | slow = slow.next;
29 | fast = fast.next.next;
30 | if (slow == fast) {
31 | return true; // "slow" and "fast" collided, so we must have a cycle.
32 | }
33 | }
34 | return false;
35 | }
36 | }
37 | ```
38 | ### Time/Space Complexity
39 |
40 | - Time Complexity: O(n)
41 | - Space Complexity: O(1)
42 |
43 | ### Links
44 |
45 | - [github.com/RodneyShag](https://github.com/RodneyShag)
46 |
--------------------------------------------------------------------------------
/Solutions/Longest Common Prefix.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | We will compare the `i = 0` character of all the words, then `i = 1, 2, 3....`
4 |
5 | ```
6 | i: 012345
7 | ------
8 | flower
9 | flow
10 | flight
11 | ------
12 | prefix: fl____
13 | ```
14 |
15 | ### Solution
16 |
17 | ```java
18 | class Solution {
19 | public String longestCommonPrefix(String[] strs) {
20 | if (strs == null || strs.length == 0) {
21 | return "";
22 | }
23 | for (int i = 0; i < strs[0].length() ; i++){
24 | char c = strs[0].charAt(i);
25 | for (int j = 1; j < strs.length; j++) {
26 | if (i == strs[j].length() || strs[j].charAt(i) != c) {
27 | return strs[0].substring(0, i);
28 | }
29 | }
30 | }
31 | return strs[0];
32 | }
33 | }
34 | ```
35 |
36 | ### Time/Space Complexity
37 |
38 | - Time Complexity: O(s) where s is sum of all characters in all strings
39 | - Space Complexity: O(1)
40 |
41 | ### Links
42 |
43 | - [github.com/RodneyShag](https://github.com/RodneyShag)
44 |
--------------------------------------------------------------------------------
/Solutions/Longest Increasing Subsequence.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | 1. Create an array.
4 | - Keep this array sorted, with values iteratively populated by our input.
5 | - The length of this array will represent our solution: the length of the Longest Increasing Subsequence (LIS).
6 | 1. Progress linearly through our input.
7 | - For each input value, use binary search to insert it into our sorted array.
8 | - When inserting, we always overwrite a larger value in our sortedArray. If no such value exists, we insert at end of array.
9 |
10 | ### Example
11 |
12 | - Input: [0, 8, 4, 12, 2]
13 | - sortedArray: [0]
14 | - sortedArray: [0, 8]
15 | - sortedArray: [0, 4]
16 | - sortedArray: [0, 4, 12]
17 | - sortedArray: [0, 2, 12]
18 |
19 | ### Solution
20 |
21 | ```java
22 | public class Solution {
23 | public int lengthOfLIS(int[] nums) {
24 | int[] sortedArray = new int[nums.length];
25 | int size = 0;
26 | for (int num : nums) {
27 | int start = 0;
28 | int end = size; // 1 element past end of our sortedArray
29 | while (start != end) {
30 | int mid = (start + end) / 2;
31 | if (sortedArray[mid] < num) {
32 | start = mid + 1;
33 | } else {
34 | end = mid;
35 | }
36 | }
37 | sortedArray[start] = num;
38 | if (start == size) {
39 | size++;
40 | }
41 | }
42 | return size;
43 | }
44 | }
45 | ```
46 |
47 | ### Time/Space Complexity
48 | - Time Complexity: O(n log n), since we do O(log n) binary search 'n' times
49 | - Space Complexity: O(n)
50 |
51 | ### References
52 |
53 | 1. [Leetcode's official solution "Approach 4: Dynamic Programming with Binary Search"](https://leetcode.com/problems/longest-increasing-subsequence/solution/) - Explanation was confusing, but example and code made sense
54 | 1. [Discussion Solution](https://leetcode.com/problems/longest-increasing-subsequence/discuss/74824) - got code from here
55 |
56 | ### Links
57 |
58 | - [github.com/RodneyShag](https://github.com/RodneyShag)
59 |
--------------------------------------------------------------------------------
/Solutions/Lowest Common Ancestor of a Binary Search Tree.md:
--------------------------------------------------------------------------------
1 | ### Notes from Problem Statement
2 |
3 | - "A node is a descendant of itself"
4 | - "All node values are unique"
5 | - "`p` and `q` are different and both values will exist in the BST"
6 |
7 | ### Algorithm
8 |
9 | - Notice we have a binary __search__ tree. That means the numbers are ordered.
10 | - Traverse down the tree. At each node:
11 | - if the node's value is smaller than both `p` and `q`, go right
12 | - if it's bigger, go left
13 | - otherwise, we've found the Lowest Common Ancestor
14 |
15 |
16 | ### Provided Code
17 |
18 | ```java
19 | class TreeNode {
20 | int val;
21 | TreeNode left;
22 | TreeNode right;
23 | }
24 | ```
25 |
26 | ### Solution
27 |
28 | ```java
29 | class Solution {
30 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
31 | if (root == null || p == null || q == null) {
32 | return null;
33 | }
34 | TreeNode node = root;
35 | while (node != null) {
36 | if (node.val < p.val && node.val < q.val) {
37 | node = node.right;
38 | } else if (node.val > p.val && node.val > q.val) {
39 | node = node.left;
40 | } else {
41 | return node;
42 | }
43 | }
44 | return null;
45 | }
46 | }
47 | ```
48 |
49 | ### Time/Space Complexity
50 |
51 | - Time Complexity: O(log n) if balanced tree, O(n) otherwise
52 | - Space Complexity: O(1)
53 |
54 | ### Links
55 |
56 | - [github.com/RodneyShag](https://github.com/RodneyShag)
57 |
--------------------------------------------------------------------------------
/Solutions/Lowest Common Ancestor of a Binary Tree.md:
--------------------------------------------------------------------------------
1 | ### Notes from Problem Statement
2 |
3 | - "A node is a descendant of itself"
4 | - "All node values are unique"
5 | - "`p` and `q` are different and both values will exist in the BST"
6 |
7 | ### Algorithm
8 |
9 | Notice this is __not a binary search tree__. If it was, it would be equivalent to [this problem](https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/), which is simpler to solve.
10 |
11 | 1. Search left subtree. If we find `p` or `q`, return that node.
12 | 1. Search right subtree. If we find `p` or `q`, return that node.
13 | 1. If `left` is null, `p` and `q` must be in the right subtree
14 | 1. If `right` is null, `p` and `q` must be in the left subtree
15 | 1. If neither are null, `p` is on one side, `q` is on other side, so the current node is the lowest common ancestor.
16 |
17 | ### Provided Code
18 |
19 | ```java
20 | class TreeNode {
21 | TreeNode left;
22 | TreeNode right;
23 | }
24 | ```
25 |
26 | ### Solution
27 |
28 | ```java
29 | class Solution {
30 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
31 | return dfs(root, p, q);
32 | }
33 |
34 | public TreeNode dfs(TreeNode root, TreeNode p, TreeNode q) {
35 | if (root == null) {
36 | return null;
37 | } else if (root == p || root == q) {
38 | return root;
39 | }
40 |
41 | TreeNode left = dfs(root.left, p, q);
42 | TreeNode right = dfs(root.right, p, q);
43 |
44 | if (left == null) {
45 | return right;
46 | } else if (right == null) {
47 | return left;
48 | } else {
49 | return root;
50 | }
51 | }
52 | }
53 | ```
54 |
55 | ### Time/Space Complexity
56 |
57 | - Time Complexity: O(n) since we may have to search all the nodes.
58 | - Space Complexity: O(log n) if balanced tree, O(n) otherwise. The space complexity is due to recursion.
59 |
60 | ### Links
61 |
62 | - [github.com/RodneyShag](https://github.com/RodneyShag)
63 |
--------------------------------------------------------------------------------
/Solutions/Majority Element.md:
--------------------------------------------------------------------------------
1 | ### Assumptions
2 |
3 | - Provided array is not null
4 | - Provided array is not empty
5 | - Majority element always exists in provided array
6 |
7 | ### Algorithm
8 |
9 | - Loop through the array. At each index `i`, we treat the array as 2 pieces
10 | - prefix as `[0, i)`
11 | - suffix as `[i, end]`
12 | - Main idea: If we don't have the majority element in the prefix, then the suffix must have a majority element, and this majority element will also be the majority element for the entire array.
13 |
14 | ### Solution
15 |
16 | ```java
17 | class Solution {
18 | public int majorityElement(int[] array) {
19 | int count = 0;
20 | Integer candidate = null;
21 |
22 | for (int num : array) {
23 | if (count == 0) { // no majority element in prefix
24 | candidate = num; // selects new candidate majority element
25 | }
26 | count += (num == candidate) ? 1 : -1;
27 | }
28 |
29 | return candidate;
30 | }
31 | }
32 | ```
33 |
34 | ### Time/Space Complexity
35 |
36 | - Time Complexity: O(n)
37 | - Space Complexity: O(1)
38 |
39 | ### Additional Notes
40 |
41 | In the case that the majority element does not necessarily exist in the provided array, we would take the output of `majorityElement()` and test to see if our candidate qualifies as the majority element (by checking that the number makes up at least half of the array):
42 |
43 | ```java
44 | boolean isCandidateValid(int[] array, int candidate) {
45 | long count = Arrays.stream(array).filter(a -> (a == candidate)).count();
46 | return count * 2 > array.length;
47 | }
48 | ```
49 |
50 | ### Links
51 |
52 | - [github.com/RodneyShag](https://github.com/RodneyShag)
53 |
--------------------------------------------------------------------------------
/Solutions/Max Area of Island.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | - Loop through our `char[][] grid`. For each piece of land, we recursively search its neighbors to calculate island size.
4 | - We mark land by simply changing the `1` in our `grid` to a `0`.
5 |
6 | ### Solution
7 |
8 | ```java
9 | class Solution {
10 | public int maxAreaOfIsland(int[][] grid) {
11 | if (grid == null || grid.length == 0) {
12 | return 0;
13 | }
14 | int rows = grid.length;
15 | int cols = grid[0].length;
16 | int maxRegion = 0;
17 | for (int r = 0; r < rows; r++) {
18 | for (int c = 0; c < cols; c++) {
19 | // Find the largest region from the current cell
20 | if (grid[r][c] == 1) {
21 | int size = findLargestRegion(grid, r, c, rows, cols);
22 | maxRegion = Math.max(maxRegion, size);
23 | }
24 | }
25 | }
26 | return maxRegion;
27 | }
28 |
29 | private int findLargestRegion(int[][] grid, int r, int c, int rows, int cols) {
30 | if (r < 0 || r >= rows || c < 0 || c >= cols || grid == null || grid[r][c] == 0) {
31 | return 0;
32 | }
33 |
34 | grid[r][c] = 0; // we alter the original matrix here
35 | int size = 1;
36 |
37 | // Recursively search neighbors
38 | size += findLargestRegion(grid, r - 1, c, rows, cols);
39 | size += findLargestRegion(grid, r + 1, c, rows, cols);
40 | size += findLargestRegion(grid, r, c - 1, rows, cols);
41 | size += findLargestRegion(grid, r, c + 1, rows, cols);
42 |
43 | return size;
44 | }
45 | }
46 | ```
47 |
48 | ### Time/Space Complexity
49 |
50 | - Time Complexity: O(rows * cols)
51 | - Space Complexity: O(rows * cols)
52 |
53 | ### Links
54 |
55 | - [github.com/RodneyShag](https://github.com/RodneyShag)
56 |
--------------------------------------------------------------------------------
/Solutions/Maximum Depth of Binary Tree.md:
--------------------------------------------------------------------------------
1 | ### Notes
2 |
3 | This problem defines a 1-TreeNode tree to have height of 1.
4 |
5 | ### Provided code
6 |
7 | ```java
8 | class TreeNode {
9 | int val;
10 | TreeNode left;
11 | TreeNode right;
12 | }
13 | ```
14 |
15 | ### Solution
16 |
17 | ```java
18 | class Solution {
19 | public int maxDepth(TreeNode root) {
20 | if (root == null) {
21 | return 0;
22 | }
23 | return 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
24 | }
25 | }
26 | ```
27 |
28 | ### Time/Space Complexity
29 |
30 | - Time Complexity: O(n) since we must touch all nodes
31 | - Space Complexity: O(n) due to recursion (on a tree that may not be balanced)
32 |
33 | ### Links
34 |
35 | - [github.com/RodneyShag](https://github.com/RodneyShag)
36 |
--------------------------------------------------------------------------------
/Solutions/Maximum Depth of N-ary Tree.md:
--------------------------------------------------------------------------------
1 | ### Notes
2 |
3 | This problem defines a 1-TreeNode tree to have height of 1.
4 |
5 | ### Provided code
6 |
7 | ```java
8 | class Node {
9 | int val;
10 | List children;
11 | }
12 | ```
13 |
14 | ### Solution
15 |
16 | ```java
17 | class Solution {
18 | public int maxDepth(Node root) {
19 | if (root == null) {
20 | return 0;
21 | }
22 | int max = 0;
23 | for (Node child : root.children) {
24 | max = Math.max(max, maxDepth(child));
25 | }
26 | return 1 + max;
27 | }
28 | }
29 | ```
30 |
31 | ### Time/Space Complexity
32 |
33 | - Time Complexity: O(n) since we must touch all nodes
34 | - Space Complexity: O(n) due to recursion (on a tree that may not be balanced)
35 |
36 | ### Links
37 |
38 | - [github.com/RodneyShag](https://github.com/RodneyShag)
39 |
--------------------------------------------------------------------------------
/Solutions/Maximum Frequency Stack.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | __Saving frequency of each number__ - Create `Map freq` that's a `Map` from `x` to the number of occurrences of `x`.
4 |
5 | __Saving highest frequencies in descending order__ - Create `Map> stacks` which is a `Map` from frequency (1, 2,...) to a `Stack` of `Integers` with that frequency. For example, if `53` is pushed twice, the first copy will be saved to Stack 1, the second copy to Stack 2.
6 |
7 | We use `Stack`s so that "if there is a tie for most frequent element, the element closest to the top of the stack is removed and returned."
8 |
9 | Keep track of `maxFreq` which is basically a pointer to the largest key in `stacks`.
10 |
11 | `push()` and `pop()` are implemented by updating the above `freq`, `stacks`, and `maxFreq`.
12 |
13 | [Alternative explanation](https://leetcode.com/articles/maximum-frequency-stack/)
14 |
15 | ### Example
16 |
17 | Example showing how `Map> stacks` is updated:
18 |
19 | ```
20 | // push(5) gives
21 | Stack 1 = [5] // maxFreq = 1
22 | Stack 2 = []
23 |
24 | // push(4) gives
25 | Stack 1 = [5, 4] // maxFreq = 1
26 | Stack 2 = []
27 |
28 | // push(5) gives
29 | Stack 1 = [5, 4]
30 | Stack 2 = [5] // maxFreq = 2
31 |
32 | // pop(5) gives
33 | Stack 1 = [5, 4] // maxFreq = 1
34 | Stack 2 = []
35 |
36 | ```
37 |
38 | ### Solution
39 |
40 | ```java
41 | class FreqStack {
42 | private Map freq = new HashMap();
43 | private Map> stacks = new HashMap();
44 | private int maxFreq = 0;
45 |
46 | public void push(int x) {
47 | freq.merge(x, 1, Integer::sum);
48 | int f = freq.get(x);
49 | maxFreq = Math.max(maxFreq, f);
50 | stacks.putIfAbsent(f, new Stack());
51 | stacks.get(f).add(x);
52 | }
53 |
54 | public int pop() {
55 | int x = stacks.get(maxFreq).pop();
56 | freq.merge(x, -1, Integer::sum);
57 | if (stacks.get(maxFreq).isEmpty()) {
58 | maxFreq--;
59 | }
60 | return x;
61 | }
62 | }
63 | ```
64 |
65 | ### Time/Space Complexity
66 |
67 | - Time Complexity: O(1) for push and pop
68 | - Space Complexity: O(1) for storage of each element. Can alternatively describe it as O(n) for storage of n elements.
69 |
70 | ### Links
71 |
72 | - [github.com/RodneyShag](https://github.com/RodneyShag)
73 |
--------------------------------------------------------------------------------
/Solutions/Median of Two Sorted Arrays.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | [Tutorial video](https://www.youtube.com/watch?v=LPFhl65R7ww)
4 |
5 | ### Solution
6 |
7 | `findMedianSortedArrays()` below assumes input arrays are sorted.
8 |
9 | ```java
10 | class Solution {
11 | public double findMedianSortedArrays(int[] input1, int[] input2) throws IllegalArgumentException {
12 | if (input1 == null || input2 == null) {
13 | throw new IllegalArgumentException();
14 | } else if (input1.length > input2.length) {
15 | return findMedianSortedArrays(input2, input1); // ensures 1st array is smaller than 2nd array
16 | }
17 | int x = input1.length;
18 | int y = input2.length;
19 |
20 | int low = 0;
21 | int high = x;
22 | while (low <= high) {
23 | int partitionX = (low + high) / 2;
24 | int partitionY = (x + y + 1) / 2 - partitionX;
25 |
26 | int maxLeftX = (partitionX == 0) ? Integer.MIN_VALUE : input1[partitionX - 1];
27 | int minRightX = (partitionX == x) ? Integer.MAX_VALUE : input1[partitionX];
28 |
29 | int maxLeftY = (partitionY == 0) ? Integer.MIN_VALUE : input2[partitionY - 1];
30 | int minRightY = (partitionY == y) ? Integer.MAX_VALUE : input2[partitionY];
31 |
32 | if (maxLeftX <= minRightY && maxLeftY <= minRightX) {
33 | if ((x + y) % 2 == 0) {
34 | return ((double) Math.max(maxLeftX, maxLeftY) + Math.min(minRightX, minRightY)) / 2;
35 | } else {
36 | return (double) Math.max(maxLeftX, maxLeftY);
37 | }
38 | } else if (maxLeftX > minRightY) {
39 | high = partitionX - 1;
40 | } else {
41 | low = partitionX + 1;
42 | }
43 | }
44 |
45 | throw new IllegalArgumentException(); // can only occur if input arrays were not sorted.
46 | }
47 | }
48 | ```
49 |
50 | ### Time/Space Complexity
51 |
52 | - Time Complexity: O(min(log(x, y)))
53 | - Space Complexity: O(1)
54 |
55 | ### Links
56 |
57 | - [github.com/RodneyShag](https://github.com/RodneyShag)
58 |
--------------------------------------------------------------------------------
/Solutions/Merge Sorted Array.md:
--------------------------------------------------------------------------------
1 | ### Hint
2 |
3 | Copy to end of array since that's where our empty buffer is.
4 |
5 | ### Solution
6 |
7 | ```java
8 | class Solution {
9 | public void merge(int[] A, int m, int[] B, int n) {
10 | int lastA = m - 1;
11 | int lastB = n - 1;
12 | int curr = lastA + lastB + 1;
13 | while (lastA >= 0 && lastB >= 0) {
14 | if (A[lastA] > B[lastB]) {
15 | A[curr--] = A[lastA--];
16 | } else {
17 | A[curr--] = B[lastB--];
18 | }
19 | }
20 |
21 | // Copy Remaining Elements. No need to copy lastA elements since they're already in correct spot
22 | while (lastB >= 0) {
23 | A[curr--] = B[lastB--];
24 | }
25 | }
26 | }
27 | ```
28 |
29 | ### Time/Space Complexity
30 |
31 | - Time Complexity: O(n)
32 | - Space Complexity: O(1)
33 |
34 | ### Links
35 |
36 | - [github.com/RodneyShag](https://github.com/RodneyShag)
37 |
--------------------------------------------------------------------------------
/Solutions/Merge Two Binary Trees.md:
--------------------------------------------------------------------------------
1 | ### Provided code
2 |
3 | ```java
4 | class TreeNode {
5 | int val;
6 | TreeNode left;
7 | TreeNode right;
8 | TreeNode(int x) {
9 | val = x;
10 | }
11 | }
12 | ```
13 |
14 | ### Solution 1
15 |
16 | If inputs `t1` and `t2` represent immutable trees, we can reuse nodes from these trees instead of creating new nodes. This makes merging big subtrees with small subtrees much more efficient.
17 |
18 | ```java
19 | class Solution {
20 | public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
21 | if (t1 == null && t2 == null) {
22 | return null;
23 | } else if (t1 == null) {
24 | return t2; // keeps entire subtree at t2 intact and returns it.
25 | } else if (t2 == null) {
26 | return t1;
27 | } else {
28 | TreeNode t = new TreeNode(t1.val + t2.val);
29 | t.left = mergeTrees(t1.left, t2.left);
30 | t.right = mergeTrees(t1.right, t2.right);
31 | return t;
32 | }
33 | }
34 | }
35 | ```
36 |
37 | ### Solution 2
38 |
39 | If reusing `TreeNode`s is not allowed, we can always create new `TreeNode`s as shown below
40 |
41 | ```java
42 | class Solution {
43 | public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
44 | if (t1 == null && t2 == null) {
45 | return null;
46 | }
47 | TreeNode t = new TreeNode(
48 | (t1 == null ? 0 : t1.val) +
49 | (t2 == null ? 0 : t2.val)
50 | );
51 | t.left = mergeTrees(t1 == null ? null : t1.left, t2 == null ? null : t2.left);
52 | t.right = mergeTrees(t1 == null ? null : t1.right, t2 == null ? null : t2.right);
53 | return t;
54 | }
55 | }
56 | ```
57 |
58 | ### Time/Space Complexity (for both solutions)
59 |
60 | - Time Complexity: O(n + m) where n is number of nodes in t1, m is number of nodes in t2
61 | - Space Complexity: O(log (n+m)) if balanced tree, O(n + m) otherwise
62 |
63 | ### Links
64 |
65 | - [github.com/RodneyShag](https://github.com/RodneyShag)
66 |
--------------------------------------------------------------------------------
/Solutions/Merge Two Sorted Lists.md:
--------------------------------------------------------------------------------
1 | ### Provided code
2 |
3 | ```java
4 | class ListNode {
5 | int val;
6 | ListNode next;
7 | ListNode(int x) {
8 | val = x;
9 | }
10 | }
11 | ```
12 |
13 | ### Solution
14 |
15 | ```java
16 | class Solution {
17 | public ListNode mergeTwoLists(ListNode currA, ListNode currB) {
18 | if (currA == null) {
19 | return currB;
20 | } else if (currB == null) {
21 | return currA;
22 | }
23 |
24 | ListNode dummy = new ListNode(0);
25 | ListNode n = dummy;
26 | while (currA != null && currB != null) {
27 | if (currA.val < currB.val) {
28 | n.next = currA;
29 | currA = currA.next;
30 | } else {
31 | n.next = currB;
32 | currB = currB.next;
33 | }
34 | n = n.next;
35 | }
36 |
37 | // attach remaining elements
38 | n.next = (currA == null) ? currB : currA;
39 |
40 | return dummy.next;
41 | }
42 | }
43 | ```
44 |
45 | ### Time/Space Complexity
46 |
47 | - Time Complexity: O(n + m)
48 | - Space Complexity: O(1)
49 |
50 | ### Links
51 |
52 | - [github.com/RodneyShag](https://github.com/RodneyShag)
53 |
--------------------------------------------------------------------------------
/Solutions/Merge k Sorted Lists.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | 1. Create a `PriorityQueue` (a minHeap)
4 | 1. Insert 1st `ListNode` of each list into minHeap
5 | 1. Loop on removing minimum from minHeap and putting into solution list. For every removal, refer back to the list that the ListNode came from to add the next ListNode into minHeap.
6 |
7 | ### Provided code
8 |
9 | ```java
10 | public class ListNode {
11 | int val;
12 | ListNode next;
13 | ListNode(int x) {
14 | val = x;
15 | }
16 | }
17 | ```
18 |
19 | ### Solution
20 |
21 | ```java
22 | class Solution {
23 | public ListNode mergeKLists(ListNode[] lists) {
24 | // checking size since PriorityQueue cannot have initial size of 0.
25 | if (lists == null || lists.length == 0) {
26 | return null;
27 | }
28 |
29 | Queue minHeap = new PriorityQueue(
30 | lists.length,
31 | (node1, node2) -> Integer.compare(node1.val, node2.val)
32 | );
33 |
34 | ListNode dummy = new ListNode(0);
35 | ListNode tail = dummy;
36 |
37 | for (ListNode node : lists) {
38 | if (node != null) {
39 | minHeap.add(node);
40 | }
41 | }
42 |
43 | while (!minHeap.isEmpty()) {
44 | ListNode node = minHeap.remove();
45 | tail.next = node;
46 | tail = tail.next;
47 | if (node.next != null) {
48 | minHeap.add(node.next);
49 | }
50 | }
51 |
52 | return dummy.next;
53 | }
54 | }
55 | ```
56 |
57 | ### Time/Space Complexity
58 |
59 | - let `n` = total number of nodes
60 | - let `k` = number of lists
61 | - Time Complexity: `O(n log k)`
62 | - Space Complexity: `O(k)`, as that's the max size of our PriorityQueue.
63 |
64 | ### Links
65 |
66 | - [github.com/RodneyShag](https://github.com/RodneyShag)
67 |
--------------------------------------------------------------------------------
/Solutions/Min Stack.md:
--------------------------------------------------------------------------------
1 | ### Assumptions
2 |
3 | Since problem statement isn't clear on what to do when our stack is empty, we have to make the following assumptions:
4 |
5 | 1. `top()` will never be called on an empty stack
6 | 1. `getMin()` will never be called on an empty stack
7 |
8 | ### Solution
9 |
10 | ```java
11 | class MinStack {
12 | Stack stack = new Stack();
13 | Stack minStack = new Stack(); // keeps track of minimums
14 |
15 | // Always push onto stack. If it's a minimum, also push it onto minStack
16 | public void push(int x) {
17 | stack.push(x);
18 | if (minStack.isEmpty() || x <= getMin()) {
19 | minStack.push(x);
20 | }
21 | }
22 |
23 | // Pop off stack. If we popped a minimum, we remove it from minStack also
24 | public void pop() {
25 | if (stack.isEmpty()) {
26 | return;
27 | }
28 | int x = stack.pop();
29 | if (x == minStack.peek()) {
30 | minStack.pop();
31 | }
32 | }
33 |
34 | public int top() {
35 | return stack.peek();
36 | }
37 |
38 | public int getMin() {
39 | return minStack.peek();
40 | }
41 | }
42 | ```
43 |
44 | ### Time/Space Complexity
45 |
46 | - Time Complexity: O(1) for `push()`, `pop()`, `top()`, and `getMin()`
47 | - Space Complexity: O(n) to store n `Integer`s
48 |
49 | ### Links
50 |
51 | - [github.com/RodneyShag](https://github.com/RodneyShag)
52 |
--------------------------------------------------------------------------------
/Solutions/Missing Number.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | Use Gauss's formula: The sum of 1 to n is (n)(n+1)/2
4 |
5 | ### Solution
6 |
7 | ```java
8 | class Solution {
9 | public int missingNumber(int[] nums) {
10 | int expectedSum = nums.length * (nums.length + 1) / 2;
11 | int actualSum = 0;
12 | for (int num : nums) {
13 | actualSum += num;
14 | }
15 | return expectedSum - actualSum;
16 | }
17 | }
18 | ```
19 |
20 | ### Time/Space Complexity
21 |
22 | - Time Complexity: O(n)
23 | - Space Complexity: O(1)
24 |
25 | ### Links
26 |
27 | - [github.com/RodneyShag](https://github.com/RodneyShag)
28 |
--------------------------------------------------------------------------------
/Solutions/Move Zeroes.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | 1. Loop through array and write any non-zero values to beginning of array.
4 | 1. For remaining indices we didn't write to, set their values to 0.
5 |
6 | ### Solution
7 |
8 | ```java
9 | class Solution {
10 | public void moveZeroes(int[] nums) {
11 | if (nums == null || nums.length == 0) {
12 | return;
13 | }
14 | int i = 0;
15 | for (int num : nums) {
16 | if (num != 0) {
17 | nums[i] = num;
18 | i++;
19 | }
20 | }
21 | while (i < nums.length) {
22 | nums[i] = 0;
23 | i++;
24 | }
25 | }
26 | }
27 | ```
28 |
29 | ### Time/Space Complexity
30 |
31 | - Time Complexity: O(n)
32 | - Space Complexity: O(1) since we overwrite the array that was provided to us
33 |
34 | ### Links
35 |
36 | - [github.com/RodneyShag](https://github.com/RodneyShag)
37 |
--------------------------------------------------------------------------------
/Solutions/N-ary Tree Level Order Traversal.md:
--------------------------------------------------------------------------------
1 | ### Provided Code
2 |
3 | ```java
4 | public class Node {
5 | int val;
6 | List children;
7 | }
8 | ```
9 |
10 | ### Solution
11 |
12 | ```java
13 | class Solution {
14 | public List> levelOrder(Node root) {
15 | if (root == null) {
16 | return new ArrayList();
17 | }
18 | List> lists = new ArrayList();
19 | Deque deque = new ArrayDeque(); // use deque as a queue
20 | deque.add(root);
21 | while (!deque.isEmpty()) {
22 | int numNodesInLevel = deque.size();
23 | List level = new ArrayList(numNodesInLevel);
24 | while (numNodesInLevel-- > 0) {
25 | Node n = deque.remove();
26 | level.add(n.val);
27 | for (Node child : n.children) {
28 | deque.add(child);
29 | }
30 | }
31 | lists.add(level);
32 | }
33 | return lists;
34 | }
35 | }
36 | ```
37 |
38 | ### Time/Space Complexity
39 |
40 | - Time Complexity: O(n)
41 | - Space Complexity: O(n)
42 |
43 | ### Links
44 |
45 | - [github.com/RodneyShag](https://github.com/RodneyShag)
46 |
--------------------------------------------------------------------------------
/Solutions/N-ary Tree Postorder Traversal.md:
--------------------------------------------------------------------------------
1 | ### Provided Code
2 |
3 | ```java
4 | public class Node {
5 | int val;
6 | List children;
7 | }
8 | ```
9 |
10 | ### Solution
11 |
12 | ```java
13 | class Solution {
14 | public List postorder(Node root) {
15 | List list = new ArrayList();
16 | postorder(root, list);
17 | return list;
18 | }
19 |
20 | private void postorder(Node node, List list) {
21 | if (node != null) {
22 | for (Node n : node.children) {
23 | postorder(n, list);
24 | }
25 | list.add(node.val);
26 | }
27 | }
28 | }
29 | ```
30 |
31 | ### Time/Space Complexity
32 |
33 | - Time Complexity: O(n) since we must visit all nodes.
34 | - Space Complexity: O(log n) on balanced tree. O(n) otherwise.
35 |
36 | ### Notes
37 |
38 | The follow-up question asks us for an iterative solution, but there is no benefit to that solution as neither the time or space complexity is improved by solving the problem iteratively.
39 |
40 | ### Links
41 |
42 | - [github.com/RodneyShag](https://github.com/RodneyShag)
43 |
--------------------------------------------------------------------------------
/Solutions/N-ary Tree Preorder Traversal.md:
--------------------------------------------------------------------------------
1 | ### Provided Code
2 |
3 | ```java
4 | public class Node {
5 | int val;
6 | List children;
7 | }
8 | ```
9 |
10 | ### Solution
11 |
12 | ```java
13 | class Solution {
14 | public List preorder(Node root) {
15 | List list = new ArrayList();
16 | preorder(root, list);
17 | return list;
18 | }
19 |
20 | private void preorder(Node node, List list) {
21 | if (node != null) {
22 | list.add(node.val);
23 | for (Node n : node.children) {
24 | preorder(n, list);
25 | }
26 | }
27 | }
28 | }
29 | ```
30 |
31 | ### Time/Space Complexity
32 |
33 | - Time Complexity: O(n) since we must visit all nodes.
34 | - Space Complexity: O(log n) on balanced tree. O(n) otherwise.
35 |
36 | ### Notes
37 |
38 | The follow-up question asks us for an iterative solution, but there is no benefit to that solution as neither the time or space complexity is improved by solving the problem iteratively.
39 |
40 | ### Links
41 |
42 | - [github.com/RodneyShag](https://github.com/RodneyShag)
43 |
--------------------------------------------------------------------------------
/Solutions/Nim Game.md:
--------------------------------------------------------------------------------
1 | ### Explanation
2 |
3 | Assuming it's your turn, here are the base cases solved:
4 |
5 | ```
6 | 1 stone --> Win. Take 1 stone.
7 | 2 stones --> Win. Take 2 stones.
8 | 3 stones --> Win. Take 3 stones.
9 | 4 stones --> Lose. If you take 1, 2, or 3 stones, your opponent will take the remaining stones.
10 | 5 stones --> Win. Take 1 stone, and your opponent is left with the losing 4 stone situation.
11 | 6 stones --> Win. Take 2 stones, and your opponent is left with the losing 4 stone situation.
12 | 7 stones --> Win. Take 3 stones, and your opponent is left with the losing 4 stone situation.
13 | 8 stones --> Lose. If you take 1, 2, or 3 stones, your opponent can take enough stones to leave you with the 4 stone losing situation.
14 | ```
15 |
16 | This pattern repeats, where every multiple of 4 is a losing situation if it is your turn to play.
17 |
18 | ### Solution
19 |
20 | ```java
21 | class Solution {
22 | public boolean canWinNim(int n) {
23 | return n % 4 != 0;
24 | }
25 | }
26 | ```
27 |
28 | ### Time/Space Complexity
29 |
30 | - Time Complexity: O(1)
31 | - Space Complexity: O(1)
32 |
33 | ### Links
34 |
35 | - [github.com/RodneyShag](https://github.com/RodneyShag)
36 |
--------------------------------------------------------------------------------
/Solutions/Not Boring Movies.md:
--------------------------------------------------------------------------------
1 | ### MySQL Solution
2 |
3 | ```sql
4 | SELECT * FROM cinema
5 | WHERE id % 2 = 1 AND
6 | description != 'boring'
7 | ORDER BY rating DESC
8 | ```
9 |
10 | ### Links
11 |
12 | - [github.com/RodneyShag](https://github.com/RodneyShag)
13 |
--------------------------------------------------------------------------------
/Solutions/Nth Highest Salary.md:
--------------------------------------------------------------------------------
1 | ### MySQL Solution
2 |
3 | ```sql
4 | CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
5 | BEGIN
6 | DECLARE M INT;
7 | SET M = N - 1;
8 | RETURN (
9 | SELECT DISTINCT Salary FROM Employee
10 | ORDER BY Salary DESC
11 | LIMIT 1 OFFSET M
12 | );
13 | END
14 | ```
15 |
16 | ### Links
17 |
18 | - [github.com/RodneyShag](https://github.com/RodneyShag)
19 |
--------------------------------------------------------------------------------
/Solutions/Number of 1 Bits.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | Starting from the right of the number, look at each digit to see if it's a 1. Use an __unsigned__ bit shift as `n = n >>> 1` to shift the digits to the right by 1.
4 |
5 | ### Solution
6 |
7 | ```java
8 | public class Solution {
9 | public int hammingWeight(int n) {
10 | int bits = 0;
11 | while (n != 0) {
12 | if ((n & 1) == 1) {
13 | bits++;
14 | }
15 | n = n >>> 1;
16 | }
17 | return bits;
18 | }
19 | }
20 | ```
21 |
22 | ### Implementation Details
23 |
24 | - Use `while (n != 0)` instead of `while (n > 0)` since `n` can be a negative number
25 | - Put parentheses around `n & 1` as `((n & 1) == 1)` so that the `n & 1` is evaluated first
26 |
27 | ### Time/Space Complexity
28 |
29 | - Time Complexity: O(1) assuming `int n` is always capped at 32 bits
30 | - Space Complexity: O(1)
31 |
32 | ### Links
33 |
34 | - [github.com/RodneyShag](https://github.com/RodneyShag)
35 |
--------------------------------------------------------------------------------
/Solutions/Odd Even Linked List.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | - Create 2 `ListNode` pointers that will walk the original list
4 | - `odd` will build the odd list
5 | - `even` will build the even list
6 | - We also need to keep track of both list heads
7 | - `head` will keep track of the odd list head
8 | - `ListNode evenHead` (which we will create) will keep track of the even list head
9 | - After we build both lists, connect the even list to the end of the odd list
10 |
11 | ### Example
12 |
13 | - Let `o` represent the `odd` pointer.
14 | - Let `e` represent the `even` pointer.
15 | - This is how we intend `o` and `e` to traverse the list:
16 |
17 | ```
18 | 1 -> 2 -> 3 -> 4 -> 5 -> null
19 | o e
20 |
21 | 1 -> 2 -> 3 -> 4 -> 5 -> null
22 | o e
23 |
24 | 1 -> 2 -> 3 -> 4 -> 5 -> null
25 | o e
26 | ```
27 |
28 | except that we will be building an odd list and even list while traversing
29 |
30 | ### Provided code
31 |
32 | ```java
33 | class ListNode {
34 | ListNode next;
35 | }
36 | ```
37 |
38 | ### Solution
39 |
40 | ```java
41 | class Solution {
42 | public ListNode oddEvenList(ListNode head) {
43 | if (head == null) {
44 | return head;
45 | }
46 | ListNode odd = head;
47 | ListNode even = head.next;
48 | ListNode evenHead = even;
49 | while (even != null && even.next != null) {
50 | odd.next = even.next;
51 | odd = odd.next;
52 | even.next = odd.next;
53 | even = even.next;
54 | }
55 | odd.next = evenHead;
56 | return head;
57 | }
58 | }
59 | ```
60 |
61 | ### Time/Space Complexity
62 |
63 | - Time Complexity: O(n)
64 | - Space Complexity: O(1)
65 |
66 | ### Links
67 |
68 | - [github.com/RodneyShag](https://github.com/RodneyShag)
69 |
--------------------------------------------------------------------------------
/Solutions/Pairs of Songs With Total Durations Divisible by 60.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | We keep track of the mod values in buckets for each number we read. We can do this
4 | by creating `k` buckets where bucket `i` counts each number `n` where `n % k = i`.
5 |
6 | Notice that each bucket has a corresponding "complement" bucket. That is, if we take
7 | the mod value of one bucket and add it to the mod value of another bucket, we get `k`.
8 |
9 | ```
10 | Bucket Complement Bucket
11 | ------ -----------------
12 | 0 0
13 | 1 k-1
14 | 2 k-2
15 | 3 k-3
16 | ...
17 | k-3 3
18 | k-2 2
19 | k-1 1
20 | ```
21 |
22 | As we come across each number, we find its corresponding complement bucket. Each number in
23 | this complement bucket can be paired with our original number to create a sum divisible by `k`.
24 |
25 | ### Solution
26 |
27 | ```java
28 | class Solution {
29 | public int numPairsDivisibleBy60(int[] time) {
30 | int [] bucket = new int[60];
31 | int count = 0;
32 | for (int t : time) {
33 | int modValue = t % 60;
34 | count += bucket[(60 - modValue) % 60]; // adds # of elements in complement bucket.
35 | bucket[modValue]++; // saves in bucket.
36 | }
37 | return count;
38 | }
39 | }
40 | ```
41 |
42 | ### Time/Space Complexity
43 |
44 | - Time Complexity: O(n + k)
45 | - Space Complexity: O(k)
46 |
47 | ### Links
48 |
49 | - [github.com/RodneyShag](https://github.com/RodneyShag)
50 |
--------------------------------------------------------------------------------
/Solutions/Palindrome Number.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | Convert the `int` to a `String`, and check to see if the `String` is a palindrome.
4 |
5 | ### Solution
6 |
7 | ```java
8 | class Solution {
9 | public boolean isPalindrome(int x) {
10 | if (x < 0) {
11 | return false;
12 | }
13 | String s = String.valueOf(x);
14 | for (int i = 0; i < s.length() / 2; i++) {
15 | if (s.charAt(i) != s.charAt(s.length() - 1 - i)) {
16 | return false;
17 | }
18 | }
19 | return true;
20 | }
21 | }
22 | ```
23 |
24 | ### Time/Space Complexity
25 |
26 | Max size of an `int` in Java is a constant 32 bits, so our `String` length will not exceed 32.
27 |
28 | - Time Complexity
29 | - `O(1)` if you consider that `int` in Java is a constant 32 bits, so our `String` length will not exceed 32.
30 | - `O(log n)` if you allow `x` to grow infinitely large. The length of the `String` grows logarithmically as fast compared to the growth of `x`
31 | - Space Complexity: O(1)
32 |
33 | ### Follow-up Problem: "Don't use a String"
34 |
35 | The `String` solution above is the most efficient and straightforward way to solve this problem. Skip the follow-up.
36 |
37 | ### Links
38 |
39 | - [github.com/RodneyShag](https://github.com/RodneyShag)
40 |
--------------------------------------------------------------------------------
/Solutions/Pascal's Triangle II.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | - The elements of the `kth` row of Pascal's triangle are equal to the coefficients of the expansion of (a + b)k
4 | - For the 4th line, `k = 4`, so we have (a + b)4 = a4 + 4a3b + 6a2b2 + 4ab3 + b4
5 | - The coefficients of the above polymonial are `1 4 6 4 1`, which is the same as the 4th row of Pascal's triangle
6 | - These coefficients could be calculated directly as 4C0, 4C1, 4C2, 4C3, 4C4, using the [Combination Formula](https://www.mathwords.com/c/combination_formula.htm) which lets us [calculate any number in Pascal's triangle directly](https://www.mathwords.com/b/binomial_coefficients_pascal.htm)
7 | - As an optimization, we can reuse the previous number in a row to create the next number. [This is how you calculate the numbers in the kth row](https://math.stackexchange.com/a/1154968).
8 |
9 | ### Solution
10 |
11 | ```java
12 | class Solution {
13 | public List getRow(int k) {
14 | if (k < 0) {
15 | return new ArrayList();
16 | }
17 | List row = new ArrayList();
18 | row.add(1);
19 | int top = k; // multiplier in numerator
20 | int bot = 1; // multiplier in denominator
21 | long C = 1; // use a `long` to prevent integer overflow
22 | for (int i = 1; i <= k; i++) {
23 | C *= top;
24 | C /= bot;
25 | top--;
26 | bot++;
27 | row.add((int) C);
28 | }
29 | return row;
30 | }
31 | }
32 | ```
33 |
34 | which can be simplified to:
35 |
36 | ```java
37 | class Solution {
38 | public List getRow(int k) {
39 | if (k < 0) {
40 | return new ArrayList();
41 | }
42 | List row = new ArrayList();
43 | row.add(1);
44 | long C = 1; // use a `long` to prevent integer overflow
45 | for (int i = 1; i <= k; i++) {
46 | C = C * (k + 1 - i) / i;
47 | row.add((int) C);
48 | }
49 | return row;
50 | }
51 | }
52 | ```
53 |
54 | ### Time/Space Complexity
55 |
56 | - Time Complexity: O(k)
57 | - Space Complexity: O(k)
58 |
59 | ### Links
60 |
61 | - [github.com/RodneyShag](https://github.com/RodneyShag)
62 |
--------------------------------------------------------------------------------
/Solutions/Pascal's Triangle.md:
--------------------------------------------------------------------------------
1 | ### Hint
2 |
3 | Visualize the triangle in the shape shown below, so when we access it using `i` (for row) and `j` (for column), it is simpler to see which number we're accessing
4 |
5 | ```
6 | 1
7 | 1 1
8 | 1 2 1
9 | 1 3 3 1
10 | 1 4 6 4 1
11 | ```
12 |
13 | For example, `i = 4` and `j = 2` gives us value `4`
14 |
15 | ### Solution
16 |
17 | ```java
18 | class Solution {
19 | public List> generate(int numRows) {
20 | if (numRows <= 0) {
21 | return new ArrayList();
22 | }
23 | List> triangle = new ArrayList();
24 | triangle.add(Arrays.asList(1)); // Row 0
25 | for (int i = 1; i < numRows; i++) {
26 | List prevRow = triangle.get(i - 1);
27 | List row = new ArrayList();
28 | row.add(1);
29 | for (int j = 1; j < i; j++) {
30 | row.add(prevRow.get(j - 1) + prevRow.get(j));
31 | }
32 | row.add(1);
33 | triangle.add(row);
34 | }
35 | return triangle;
36 | }
37 | }
38 | ```
39 |
40 | ### Time/Space Complexity
41 |
42 | - Time Complexity: O(n2)
43 | - Space Complexity: O(n2)
44 |
45 | ### Links
46 |
47 | - [github.com/RodneyShag](https://github.com/RodneyShag)
48 |
--------------------------------------------------------------------------------
/Solutions/Path Sum III.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | This is the same problem as [Subarray Sum Equals K](https://leetcode.com/problems/subarray-sum-equals-k), except instead of being in a 1-Dimensional array, it is in a tree.
4 |
5 | See [my solution to the above problem](https://github.com/RodneyShag/LeetCode_solutions/blob/master/Solutions/Subarray%20Sum%20Equals%20K.md), then apply it to this problem.
6 |
7 | ### Provided code
8 |
9 | ```java
10 | public class TreeNode {
11 | int val;
12 | TreeNode left;
13 | TreeNode right;
14 | }
15 | ```
16 |
17 | ### Solution
18 |
19 | ```java
20 | class Solution {
21 | public int pathSum(TreeNode node, int target) {
22 | Map map = new HashMap();
23 | map.put(0, 1);
24 | return pathSum(node, target, 0, map);
25 | }
26 |
27 | private int pathSum(TreeNode node, int target, int sum, Map map) {
28 | if (node == null) {
29 | return 0;
30 | }
31 | sum += node.val;
32 | int result = map.getOrDefault(sum - target, 0);
33 |
34 | map.merge(sum, 1, Integer::sum);
35 | result += pathSum(node.left, target, sum, map);
36 | result += pathSum(node.right, target, sum, map);
37 | map.merge(sum, -1, Integer::sum);
38 | if (map.get(sum) == 0) { // Remove when 0 to reduce space usage
39 | map.remove(sum);
40 | }
41 |
42 | return result;
43 | }
44 | }
45 | ```
46 |
47 | ### Time/Space Complexity
48 |
49 | - Time Complexity: O(n)
50 | - Space Complexity: O(log n) if balanced tree. O(n) otherwise.
51 |
52 | ### Links
53 |
54 | - [github.com/RodneyShag](https://github.com/RodneyShag)
55 |
--------------------------------------------------------------------------------
/Solutions/Permutations II.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | Use "Backtracking" - an algorithm for finding all solutions by exploring all potential candidates.
4 |
5 | This is the same as the [Permutations](https://leetcode.com/problems/permutations) problem, except that we use a `Set` to remove duplicates.
6 |
7 | ### Solution
8 |
9 | ```java
10 | class Solution {
11 | public List> permuteUnique(int[] array) {
12 | if (array == null || array.length == 0) {
13 | return new ArrayList();
14 | }
15 | Set> solutions = new HashSet();
16 | permute(array, 0, new boolean[array.length], solutions, new ArrayList());
17 | return new ArrayList(solutions);
18 | }
19 |
20 | private void permute(int[] array, int index, boolean[] used, Set> solutions, List list) {
21 | if (index == array.length) {
22 | solutions.add(new ArrayList(list));
23 | return;
24 | }
25 | for (int i = 0; i < array.length; i++) {
26 | if (used[i] == false) {
27 | list.add(array[i]);
28 | used[i] = true;
29 | permute(array, index + 1, used, solutions, list);
30 | used[i] = false;
31 | list.remove(list.size() - 1);
32 | }
33 | }
34 | }
35 | }
36 | ```
37 |
38 | ### Time/Space Complexity
39 |
40 | If you view this recursion as a tree, there will be `n!` leaf nodes, so there are O(n!) nodes in total. At each node, we do O(n) work looping through the array. So our runtime is O(n * n!).
41 |
42 | - Time Complexity: O(n * n!)
43 | - Space Complexity: O(n * n!)
44 |
45 | ### Similar BackTracking Problems
46 |
47 | - [Permutations](https://leetcode.com/problems/permutations)
48 | - [Subsets](https://leetcode.com/problems/subsets) and [Subsets II](https://leetcode.com/problems/subsets-ii)
49 | - [Letter Combinations of a Phone Number](https://leetcode.com/problems/letter-combinations-of-a-phone-number)
50 | - [N-Queens](https://leetcode.com/problems/n-queens)
51 |
52 | ### Links
53 |
54 | - [github.com/RodneyShag](https://github.com/RodneyShag)
55 |
--------------------------------------------------------------------------------
/Solutions/Permutations.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | Use "Backtracking" - an algorithm for finding all solutions by exploring all potential candidates.
4 |
5 | ### Solution
6 |
7 | ```java
8 | class Solution {
9 | public List> permute(int[] array) {
10 | if (array == null || array.length == 0) {
11 | return new ArrayList();
12 | }
13 | List> solutions = new ArrayList();
14 | permute(array, 0, new boolean[array.length], solutions, new ArrayList());
15 | return solutions;
16 | }
17 |
18 | private void permute(int[] array, int index, boolean[] used, List> solutions, List list) {
19 | if (index == array.length) {
20 | solutions.add(new ArrayList(list));
21 | return;
22 | }
23 | for (int i = 0; i < array.length; i++) {
24 | if (used[i] == false) {
25 | list.add(array[i]);
26 | used[i] = true;
27 | permute(array, index + 1, used, solutions, list);
28 | used[i] = false;
29 | list.remove(list.size() - 1);
30 | }
31 | }
32 | }
33 | }
34 | ```
35 |
36 | ### Time/Space Complexity
37 |
38 | If you view this recursion as a tree, there will be `n!` leaf nodes, so there are O(n!) nodes in total. At each node, we do O(n) work looping through the array. So our runtime is O(n * n!).
39 |
40 | - Time Complexity: O(n * n!)
41 | - Space Complexity: O(n * n!)
42 |
43 | ### Similar BackTracking Problems
44 |
45 | - [Permutations II](https://leetcode.com/problems/permutations-ii)
46 | - [Subsets](https://leetcode.com/problems/subsets) and [Subsets II](https://leetcode.com/problems/subsets-ii)
47 | - [Letter Combinations of a Phone Number](https://leetcode.com/problems/letter-combinations-of-a-phone-number)
48 | - [N-Queens](https://leetcode.com/problems/n-queens)
49 |
50 | ### Links
51 |
52 | - [github.com/RodneyShag](https://github.com/RodneyShag)
53 |
--------------------------------------------------------------------------------
/Solutions/Plus One.md:
--------------------------------------------------------------------------------
1 | ### Solution
2 |
3 | ```java
4 | class Solution {
5 | public int[] plusOne(int[] digits) {
6 | if (digits == null) {
7 | return null;
8 | }
9 | for (int i = digits.length - 1; i >= 0; i--) {
10 | if (digits[i] < 9) {
11 | digits[i]++;
12 | return digits;
13 | } else {
14 | digits[i] = 0;
15 | // simulate a "carry" by continuing the loop
16 | }
17 | }
18 |
19 | // Code reaches here for inputs of all 9s such as [9, 9, 9]
20 | int[] result = new int[digits.length + 1];
21 | result[0] = 1;
22 | return result;
23 | }
24 | }
25 | ```
26 |
27 | ### Time/Space Complexity
28 |
29 | - Time Complexity: O(n)
30 | - Space Complexity: O(n)
31 |
32 | ### Links
33 |
34 | - [github.com/RodneyShag](https://github.com/RodneyShag)
35 |
--------------------------------------------------------------------------------
/Solutions/Power of Four.md:
--------------------------------------------------------------------------------
1 | This is very similar to the [Power of Three](https://leetcode.com/problems/power-of-three) question on LeetCode.
2 |
3 | # Solution 1 - Using Loop
4 |
5 | ### Algorithm
6 |
7 | If a number is a power of 4, we can keep dividing it by 4 until we end up with a value of 1.
8 |
9 | ### Code
10 |
11 | ```java
12 | class Solution {
13 | public boolean isPowerOfFour(int n) {
14 | if (n < 1) {
15 | return false;
16 | }
17 | while (n % 4 == 0) {
18 | n /= 4;
19 | }
20 | return n == 1;
21 | }
22 | }
23 | ```
24 |
25 | ### Notes
26 |
27 | This algorithm works for any "Power of X" question for X = 2, 3, 4,...
28 |
29 | ### Time/Space Complexity
30 |
31 | - Time Complexity
32 | - if number of bits in `int n` is capped at 32: `O(1)`
33 | - if number of bits is allowed to grow: `O(log n)`
34 | - Space Complexity: O(1)
35 |
36 |
37 | # Solution 2 - Base Conversion
38 |
39 | ### Algorithm
40 |
41 | 1. Convert the number to base-4 representation.
42 | 1. Check if it starts with `1` (and followed by 0 or more 0s)
43 |
44 | ### Code
45 |
46 | ```java
47 | class Solution {
48 | public boolean isPowerOfFour(int n) {
49 | return Integer.toString(n, 4).matches("10*");
50 | }
51 | }
52 | ```
53 |
54 | ### Notes
55 |
56 | This algorithm works for any "Power of X" question for X = 2, 3, 4,...
57 |
58 | ### Time/Space Complexity
59 |
60 | - Time Complexity
61 | - if number of bits in `int n` is capped at 32: `O(1)`
62 | - if number of bits is allowed to grow: `O(log n)` since base conversion is implemented as repeated division
63 | - Space Complexity: `O(1)`
64 |
65 |
66 | # Links
67 |
68 | - [github.com/RodneyShag](https://github.com/RodneyShag)
69 |
--------------------------------------------------------------------------------
/Solutions/Power of Two.md:
--------------------------------------------------------------------------------
1 | # Solution 1
2 |
3 | ### Code
4 |
5 | ```java
6 | class Solution {
7 | public boolean isPowerOfTwo(int n) {
8 | if (n < 1) {
9 | return false;
10 | }
11 | return (n & (n - 1)) == 0;
12 | }
13 | }
14 | ```
15 |
16 | ### Example
17 |
18 | Let n = 2^5 = 32. In binary, we have:
19 |
20 | ```
21 | n = 00010000
22 | n - 1 = 00001111
23 | n & (n - 1) = 00000000
24 | ```
25 |
26 | ### Time/Space Complexity
27 |
28 | - Time Complexity: O(1)
29 | - Space Complexity: O(1)
30 |
31 |
32 | # Solution 2
33 |
34 | ### Algorithm
35 |
36 | `n` must be positive for it to be a power of 2. It also must have only one 1 bit.
37 |
38 | ```
39 | Binary Decimal
40 | 000000001 = 1
41 | 000000100 = 4
42 | 000010000 = 16
43 | ```
44 |
45 | ### Code
46 |
47 | ```java
48 | public boolean isPowerOfTwo(int n) {
49 | if (n < 1) {
50 | return false;
51 | }
52 | return n > 0 && Integer.bitCount(n) == 1;
53 | }
54 | ```
55 |
56 | ### Time/Space Complexity
57 |
58 | - Time Complexity: O(1)
59 | - Space Complexity: O(1)
60 |
61 |
62 | # Links
63 |
64 | - [github.com/RodneyShag](https://github.com/RodneyShag)
65 |
--------------------------------------------------------------------------------
/Solutions/Print FooBar Alternately.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | Use Semaphores. Here is a good explanation of [Semaphores](https://www.geeksforgeeks.org/semaphore-in-java/) (read their explanation, skip their code).
4 |
5 | - use `Semaphore fooLock` to block execution of `foo()`
6 | - use `Semaphore barLock` to block execution of `bar()`
7 | - `fooLock` will start unlocked so that `foo()` is first function to execute.
8 |
9 | ### Solution
10 |
11 | ```java
12 | class FooBar {
13 | private int n;
14 | private Semaphore fooLock = new Semaphore(1);
15 | private Semaphore barLock = new Semaphore(0);
16 |
17 | public FooBar(int n) {
18 | this.n = n;
19 | }
20 |
21 | public void foo(Runnable printFoo) throws InterruptedException {
22 | for (int i = 0; i < n; i++) {
23 | fooLock.acquire();
24 | printFoo.run();
25 | barLock.release();
26 | }
27 | }
28 |
29 | public void bar(Runnable printBar) throws InterruptedException {
30 | for (int i = 0; i < n; i++) {
31 | barLock.acquire();
32 | printBar.run();
33 | fooLock.release();
34 | }
35 | }
36 | }
37 | ```
38 |
39 | ### Time/Space Complexity
40 |
41 | - Time Complexity: O(n)
42 | - Space Complexity: O(1)
43 |
44 | ### Links
45 |
46 | - [github.com/RodneyShag](https://github.com/RodneyShag)
47 |
--------------------------------------------------------------------------------
/Solutions/Print Zero Even Odd.md:
--------------------------------------------------------------------------------
1 | ### Hints
2 |
3 | Use Semaphores. Here is a good explanation of [Semaphores](https://www.geeksforgeeks.org/semaphore-in-java/) (read their explanation, skip their code).
4 |
5 | ### Solution
6 |
7 | ```java
8 | class ZeroEvenOdd {
9 | private final int n;
10 | private final Semaphore zeroLock = new Semaphore(1);
11 | private final Semaphore oddLock = new Semaphore(0);
12 | private final Semaphore evenLock = new Semaphore(0);
13 |
14 | public ZeroEvenOdd(int n) {
15 | this.n = n;
16 | }
17 |
18 | public void zero(IntConsumer printNumber) throws InterruptedException {
19 | for (int i = 0; i < n; i++) {
20 | zeroLock.acquire();
21 | printNumber.accept(0);
22 | if (i % 2 == 0) {
23 | oddLock.release();
24 | } else {
25 | evenLock.release();
26 | }
27 | }
28 | }
29 |
30 | public void even(IntConsumer printNumber) throws InterruptedException {
31 | for (int i = 2; i <= n; i += 2) {
32 | evenLock.acquire();
33 | printNumber.accept(i);
34 | zeroLock.release();
35 | }
36 | }
37 |
38 | public void odd(IntConsumer printNumber) throws InterruptedException {
39 | for (int i = 1; i <= n; i += 2) {
40 | oddLock.acquire();
41 | printNumber.accept(i);
42 | zeroLock.release();
43 | }
44 | }
45 | }
46 | ```
47 |
48 | ### Time/Space Complexity
49 |
50 | - Time Complexity: O(n)
51 | - Space Complexity: O(1)
52 |
53 | ### Links
54 |
55 | - [github.com/RodneyShag](https://github.com/RodneyShag)
56 |
--------------------------------------------------------------------------------
/Solutions/Print in Order.md:
--------------------------------------------------------------------------------
1 | # Solution 1 - Semaphore
2 |
3 | Use a Semaphore. Here is a good explanation of [Semaphores](https://www.geeksforgeeks.org/semaphore-in-java/) (read their explanation, skip their code).
4 |
5 | "Semaphore is a bowl of marbles. If you need a marble, and there are none, you wait. You wait until there is one marble and then you take it. If you release(), you will add one marble to the bowl (from thin air). If you release(100), you will add 100 marbles to the bowl (from thin air)." - from [this post](https://leetcode.com/problems/print-in-order/discuss/332890/Java-Basic-semaphore-solution-8ms-36MB)
6 |
7 | ### Code
8 |
9 | ```java
10 | class Foo {
11 | private Semaphore run2 = new Semaphore(0);
12 | private Semaphore run3 = new Semaphore(0);
13 |
14 | public void first(Runnable printFirst) throws InterruptedException {
15 | printFirst.run();
16 | run2.release();
17 | }
18 |
19 | public void second(Runnable printSecond) throws InterruptedException {
20 | run2.acquire();
21 | printSecond.run();
22 | run3.release();
23 | }
24 |
25 | public void third(Runnable printThird) throws InterruptedException {
26 | run3.acquire();
27 | printThird.run();
28 | }
29 | }
30 | ```
31 |
32 | ### Time/Space Complexity
33 |
34 | - Time Complexity: O(1)
35 | - Space Complexity: O(1)
36 |
37 |
38 | # Solution 2 - CountDownLatch
39 |
40 | Use a [CountDownLatch](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html)
41 |
42 | ### Code
43 |
44 | ```java
45 | class Foo {
46 | private CountDownLatch latch2 = new CountDownLatch(1);
47 | private CountDownLatch latch3 = new CountDownLatch(1);
48 |
49 | public void first(Runnable printFirst) throws InterruptedException {
50 | printFirst.run();
51 | latch2.countDown();
52 | }
53 |
54 | public void second(Runnable printSecond) throws InterruptedException {
55 | latch2.await();
56 | printSecond.run();
57 | latch3.countDown();
58 | }
59 |
60 | public void third(Runnable printThird) throws InterruptedException {
61 | latch3.await();
62 | printThird.run();
63 | }
64 | }
65 | ```
66 |
67 | ### Time/Space Complexity
68 |
69 | - Time Complexity: O(1)
70 | - Space Complexity: O(1)
71 |
72 |
73 | # Links
74 |
75 | - [github.com/RodneyShag](https://github.com/RodneyShag)
76 |
--------------------------------------------------------------------------------
/Solutions/Range Sum Query - Immutable.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | 1. Create a class variable called `int[] sum`.
4 | 1. Let `sum[i]` represent the sum from `num[0]` to `num[i]` inclusive.
5 | 1. To calculate `sumRange(int i, int j)`, just return `sum[j] - sum[i - 1]`
6 | - if `i == 0`, treat that as a special case
7 |
8 | ### Solution
9 |
10 | ```java
11 | class NumArray {
12 | private int[] sum;
13 |
14 | public NumArray(int[] nums) {
15 | if (nums == null || nums.length == 0) {
16 | return;
17 | }
18 | sum = new int[nums.length];
19 | sum[0] = nums[0];
20 | for (int i = 1; i < nums.length; i++) {
21 | sum[i] = sum[i - 1] + nums[i];
22 | }
23 | }
24 |
25 | public int sumRange(int i, int j) { // assumes 0 <= i <= j, and 'int[] sum' is not empty
26 | if (i == 0) {
27 | return sum[j];
28 | } else {
29 | return sum[j] - sum[i - 1];
30 | }
31 | }
32 | }
33 | ```
34 |
35 | ### Time/Space Complexity
36 |
37 | - Time Complexity: O(n) to pre-compute. O(1) for `sumRange()` calls after precomputation.
38 | - Space Complexity: O(n)
39 |
40 | ### Links
41 |
42 | - [github.com/RodneyShag](https://github.com/RodneyShag)
43 |
--------------------------------------------------------------------------------
/Solutions/Rank Scores.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | To determine the ranking of a score, count the number of distinct scores that are `>=` to that score
4 |
5 | ### MySQL Solution
6 |
7 | ```sql
8 | SELECT
9 | S1.Score,
10 | (SELECT COUNT(DISTINCT Score) FROM Scores AS S2 WHERE S2.Score >= S1.Score) AS 'Rank'
11 | FROM Scores AS S1
12 | ORDER BY Score DESC
13 | ```
14 |
15 | ### Links
16 |
17 | - [github.com/RodneyShag](https://github.com/RodneyShag)
18 |
--------------------------------------------------------------------------------
/Solutions/Ransom Note.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | 1. Store `magazine` as `Character`s in a `HashMap` (where `key` is the `Character` and `value` is the count)
4 | 1. Loop through `ransomNote` and use the `Character`s in our `HashMap`.
5 |
6 | ### Solution
7 |
8 | ```java
9 | class Solution {
10 | public boolean canConstruct(String ransomNote, String magazine) {
11 | Map usableLetters = getLetters(magazine);
12 | for (int i = 0; i < ransomNote.length(); i++) {
13 | char letter = ransomNote.charAt(i);
14 | if (usableLetters.containsKey(letter) && usableLetters.get(letter) > 0) {
15 | usableLetters.merge(letter, -1, Integer::sum); // uses the letter
16 | } else {
17 | return false;
18 | }
19 | }
20 | return true;
21 | }
22 |
23 | private Map getLetters(String magazine) {
24 | Map letters = new HashMap();
25 | for (int i = 0; i < magazine.length(); i++) {
26 | letters.merge(magazine.charAt(i), 1, Integer::sum);
27 | }
28 | return letters;
29 | }
30 | }
31 | ```
32 |
33 | ### Time/Space Complexity
34 |
35 | - Time Complexity: O(n + m)
36 | - Space Complexity: O(m) to store `magazine` in a `HashMap` of characters
37 |
38 |
39 | ### Links
40 |
41 | - [github.com/RodneyShag](https://github.com/RodneyShag)
42 |
--------------------------------------------------------------------------------
/Solutions/Reformat Department Table.md:
--------------------------------------------------------------------------------
1 | ### Hints
2 |
3 | Use [GROUP BY](https://www.w3schools.com/sql/sql_groupby.asp) on `id`, so that the different `month` values for the same `id` can be combined.
4 |
5 | ### MySQL Solution
6 |
7 | ```sql
8 | SELECT
9 | id,
10 | MAX(IF(month = 'Jan', revenue, null)) AS Jan_Revenue,
11 | MAX(IF(month = 'Feb', revenue, null)) AS Feb_Revenue,
12 | MAX(IF(month = 'Mar', revenue, null)) AS Mar_Revenue,
13 | MAX(IF(month = 'Apr', revenue, null)) AS Apr_Revenue,
14 | MAX(IF(month = 'May', revenue, null)) AS May_Revenue,
15 | MAX(IF(month = 'Jun', revenue, null)) AS Jun_Revenue,
16 | MAX(IF(month = 'Jul', revenue, null)) AS Jul_Revenue,
17 | MAX(IF(month = 'Aug', revenue, null)) AS Aug_Revenue,
18 | MAX(IF(month = 'Sep', revenue, null)) AS Sep_Revenue,
19 | MAX(IF(month = 'Oct', revenue, null)) AS Oct_Revenue,
20 | MAX(IF(month = 'Nov', revenue, null)) AS Nov_Revenue,
21 | MAX(IF(month = 'Dec', revenue, null)) AS Dec_Revenue
22 | FROM Department
23 | GROUP BY id
24 | ```
25 |
26 | ### MAX vs SUM
27 |
28 | - It seems the input data has at most 1 row for every `id` and `month` pair, so the revenue for an `id` and `month` pair will always be a single value
29 | - Therefore, for a specific `id`, we can only have 1 value for each of `Jan`, `Feb`, `Mar`, etc.
30 | - Since multiple rows in the input can have the same `id`, the `GROUP BY` needs an aggregate function (such as `MAX` or `SUM`) to combine the rows for an `id`. Since each `id` and `month` pair can only have 1 `revenue`, it doesn't matter whether we use `MAX` or `SUM` for combining rows
31 | - I use `MAX`. If the `month` has a revenue, it will use it, otherwise, the value will be `null`
32 |
33 | ### Links
34 |
35 | - [github.com/RodneyShag](https://github.com/RodneyShag)
36 |
--------------------------------------------------------------------------------
/Solutions/Remove Duplicates from Sorted Array II.md:
--------------------------------------------------------------------------------
1 | ### Notes
2 |
3 | - First solve [Remove Duplicates from Sorted Array](https://leetcode.com/problems/remove-duplicates-from-sorted-array), then apply the same concepts here.
4 | - Remember, the input array is _sorted_.
5 |
6 | ### Solution
7 |
8 | ```java
9 | class Solution {
10 | public int removeDuplicates(int[] nums) {
11 | if (nums == null || nums.length == 0) {
12 | return 0;
13 | }
14 | int i = 0;
15 | for (int n : nums) {
16 | if (i < 2 || nums[i - 2] != n) {
17 | nums[i] = n;
18 | i++;
19 | }
20 | }
21 | return i;
22 | }
23 | }
24 | ```
25 |
26 | ### Implementation Notes
27 |
28 | In the `for` loop, notice we only have to do the `nums[i - 2] != n` comparison.
29 |
30 | A `nums[i - 1] != n` comparison is not necessary since the input array is sorted.
31 |
32 |
33 | ### Time/Space Complexity
34 |
35 | - Time Complexity: O(n)
36 | - Space Complexity: O(1)
37 |
38 | ### Links
39 |
40 | - [github.com/RodneyShag](https://github.com/RodneyShag)
41 |
--------------------------------------------------------------------------------
/Solutions/Remove Duplicates from Sorted Array.md:
--------------------------------------------------------------------------------
1 | ### Notes
2 |
3 | Remember, the input array is _sorted_.
4 |
5 | ### Solution
6 |
7 | ```java
8 | class Solution {
9 | public int removeDuplicates(int[] nums) {
10 | if (nums == null || nums.length == 0) {
11 | return 0;
12 | }
13 | int i = 0;
14 | for (int n : nums) {
15 | if (i == 0 || nums[i - 1] != n) {
16 | nums[i] = n;
17 | i++;
18 | }
19 | }
20 | return i;
21 | }
22 | }
23 | ```
24 |
25 | ### Time/Space Complexity
26 |
27 | - Time Complexity: O(n)
28 | - Space Complexity: O(1)
29 |
30 | ### Similar Problems
31 |
32 | [Remove Duplicates from Sorted Array II](https://leetcode.com/problems/remove-duplicates-from-sorted-array-ii)
33 |
34 | ### Links
35 |
36 | - [github.com/RodneyShag](https://github.com/RodneyShag)
37 |
--------------------------------------------------------------------------------
/Solutions/Remove Duplicates from Sorted List II.md:
--------------------------------------------------------------------------------
1 | ### Notes
2 |
3 | This problem is tricky to code correctly. We will use 2 `ListNode` variables to simplify our code:
4 |
5 | 1. `ListNode dummy` will represent the `ListNode` before the start of the list.
6 | 1. `ListNode n` will walk the list and point to 1 `ListNode` before the `ListNode` we're processing. This makes it easier to remove `ListNode`s
7 |
8 | ### Provided code
9 |
10 | ```java
11 | class ListNode {
12 | int val;
13 | ListNode next;
14 | ListNode(int x) {
15 | val = x;
16 | }
17 | }
18 | ```
19 |
20 | ### Solution
21 |
22 | ```java
23 | class Solution {
24 | public ListNode deleteDuplicates(ListNode head) {
25 | if (head == null) {
26 | return null;
27 | }
28 | ListNode dummy = new ListNode(0);
29 | dummy.next = head;
30 | ListNode n = dummy;
31 | while (n.next != null && n.next.next != null) {
32 | if (n.next.val == n.next.next.val) {
33 | int duplicate = n.next.val;
34 | while (n.next != null && n.next.val == duplicate) {
35 | n.next = n.next.next;
36 | }
37 | } else {
38 | n = n.next;
39 | }
40 | }
41 | return dummy.next;
42 | }
43 | }
44 | ```
45 |
46 | ### Time/Space Complexity
47 |
48 | - Time Complexity: O(n)
49 | - Space Complexity: O(1)
50 |
51 | ### Links
52 |
53 | - [github.com/RodneyShag](https://github.com/RodneyShag)
54 |
--------------------------------------------------------------------------------
/Solutions/Remove Duplicates from Sorted List.md:
--------------------------------------------------------------------------------
1 | ### Provided code
2 |
3 | ```java
4 | class ListNode {
5 | int val;
6 | ListNode next;
7 | }
8 | ```
9 |
10 | ### Solution
11 |
12 | ```java
13 | class Solution {
14 | public ListNode deleteDuplicates(ListNode head) {
15 | if (head == null) {
16 | return null;
17 | }
18 | ListNode n = head;
19 | while (n.next != null) {
20 | if (n.next.val == n.val) {
21 | n.next = n.next.next; // deletes ListNode
22 | } else {
23 | n = n.next;
24 | }
25 | }
26 | return head;
27 | }
28 | }
29 | ```
30 |
31 | ### Time/Space Complexity
32 |
33 | - Time Complexity: O(n)
34 | - Space Complexity: O(1)
35 |
36 | ### Links
37 |
38 | - [github.com/RodneyShag](https://github.com/RodneyShag)
39 |
--------------------------------------------------------------------------------
/Solutions/Remove Element.md:
--------------------------------------------------------------------------------
1 | ### Notes
2 |
3 | The problem mentions "It doesn't matter what you leave beyond the new length."
4 |
5 | ### Solution
6 |
7 | ```java
8 | class Solution {
9 | public int removeElement(int[] nums, int val) {
10 | if (nums == null) {
11 | return 0;
12 | }
13 | int i = 0;
14 | for (int n : nums) {
15 | if (n != val) {
16 | nums[i] = n;
17 | i++;
18 | }
19 | }
20 | return i;
21 | }
22 | }
23 | ```
24 |
25 | ### Time/Space Complexity
26 |
27 | - Time Complexity: O(n)
28 | - Space Complexity: O(1)
29 |
30 | ### Links
31 |
32 | - [github.com/RodneyShag](https://github.com/RodneyShag)
33 |
--------------------------------------------------------------------------------
/Solutions/Remove Linked List Elements.md:
--------------------------------------------------------------------------------
1 | ### Hint
2 |
3 | Create a `ListNode dummy`, where `dummy.next = head`. This will make it easier to remove elements at the head of the list, if necessary.
4 |
5 | ### Provided Code
6 |
7 | ```java
8 | class ListNode {
9 | int val;
10 | ListNode next;
11 | ListNode(int x) {
12 | val = x;
13 | }
14 | }
15 | ```
16 |
17 | ### Solution
18 |
19 | ```java
20 | class Solution {
21 | public ListNode removeElements(ListNode head, int val) {
22 | ListNode dummy = new ListNode(-1);
23 | dummy.next = head;
24 | ListNode n = dummy;
25 | while (n.next != null) {
26 | if (n.next.val == val) {
27 | n.next = n.next.next;
28 | } else {
29 | n = n.next;
30 | }
31 | }
32 | return dummy.next;
33 | }
34 | }
35 | ```
36 |
37 | ### Time/Space Complexity
38 |
39 | - Time Complexity: O(n)
40 | - Space Complexity: O(1)
41 |
42 | ### Links
43 |
44 | - [github.com/RodneyShag](https://github.com/RodneyShag)
45 |
--------------------------------------------------------------------------------
/Solutions/Remove Nth Node From End of List.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | 1. Find the size of the list by walking through entire list.
4 | 1. Do `size - n - 1` to see how many steps you should take before removing the next node.
5 | 1. Walk that many steps and remove the node.
6 | 1. Return the head of the list.
7 |
8 | ### Provided Code
9 |
10 | ```java
11 | class ListNode {
12 | ListNode next;
13 | }
14 | ```
15 |
16 | ### Solution
17 |
18 | ```java
19 | class Solution {
20 | public ListNode removeNthFromEnd(ListNode head, int n) {
21 | int size = findSize(head);
22 | if (n == size) {
23 | return head.next;
24 | } else {
25 | int steps = size - n - 1;
26 | ListNode node = head;
27 | while (steps-- > 0) {
28 | node = node.next;
29 | }
30 | node.next = node.next.next; // remove node
31 | return head;
32 | }
33 | }
34 |
35 | private int findSize(ListNode head) {
36 | ListNode n = head;
37 | int size = 0;
38 | while (n != null) {
39 | size++;
40 | n = n.next;
41 | }
42 | return size;
43 | }
44 | }
45 | ```
46 |
47 | ### Time/Space Complexity
48 |
49 | - Time Complexity: O(n)
50 | - Space Complexity: O(1)
51 |
52 | ### Follow-up Solution
53 |
54 | There is no benefit in solving this problem in 1 pass instead of 2 passes, as the time and space complexity remain the same. In both solutions, you would still have to traverse every element in the list.
55 |
56 | ### Links
57 |
58 | - [github.com/RodneyShag](https://github.com/RodneyShag)
59 |
--------------------------------------------------------------------------------
/Solutions/Reorder List.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | 1. Use slow & fast pointers to find middle of list.
4 | 1. Reverse the list after the middle point.
5 | 1. Merge the 1st half of linked list with the reversed 2nd half we just created.
6 |
7 | ### Provided code
8 |
9 | ```java
10 | class ListNode {
11 | int val;
12 | ListNode next;
13 | ListNode(int x) {
14 | val = x;
15 | }
16 | }
17 | ```
18 |
19 | ### Solution
20 |
21 | ```java
22 | class Solution {
23 | public void reorderList(ListNode head) {
24 | if (head == null || head.next == null) {
25 | return;
26 | }
27 |
28 | // find middle of list
29 | ListNode slow = head;
30 | ListNode fast = head;
31 | while (fast.next != null && fast.next.next != null) {
32 | slow = slow.next;
33 | fast = fast.next.next;
34 | }
35 |
36 | ListNode reversedList = reverseList(slow.next);
37 | slow.next = null;
38 | mergeLists(head, reversedList);
39 | }
40 |
41 | private ListNode reverseList(ListNode head) {
42 | if (head == null || head.next == null) {
43 | return head;
44 | }
45 | ListNode prev = null;
46 | ListNode curr = head;
47 | ListNode next = null;
48 | while (curr != null) {
49 | next = curr.next;
50 | curr.next = prev; // changes arrow direction
51 | prev = curr;
52 | curr = next;
53 | }
54 | return prev;
55 | }
56 |
57 | private ListNode mergeLists(ListNode currA, ListNode currB) {
58 | ListNode result = new ListNode(0); // dummy/placeholder ListNode
59 | ListNode n = result;
60 | while (currA != null && currB != null) {
61 | n.next = currA;
62 | currA = currA.next;
63 | n = n.next;
64 |
65 | n.next = currB;
66 | currB = currB.next;
67 | n = n.next;
68 | }
69 |
70 | // Attach the remaining element(s)
71 | if (currA == null) {
72 | n.next = currB;
73 | } else {
74 | n.next = currA;
75 | }
76 |
77 | return result.next;
78 | }
79 | }
80 | ```
81 |
82 | ### Time/Space Complexity
83 |
84 | - Time Complexity: O(n)
85 | - Space Complexity: O(1)
86 |
87 | ### Links
88 |
89 | - [github.com/RodneyShag](https://github.com/RodneyShag)
90 |
--------------------------------------------------------------------------------
/Solutions/Reverse Bits.md:
--------------------------------------------------------------------------------
1 | ### Notes
2 |
3 | Knowing how to code these 3 functions: [getBit()](https://github.com/RodneyShag/Interview_solutions/blob/master/Solutions/Cracking%20the%20Coding%20Interview/BitFunctions%20-%20getBit.md), [setBit()](https://github.com/RodneyShag/Interview_solutions/blob/master/Solutions/Cracking%20the%20Coding%20Interview/BitFunctions%20-%20setBit.md), and [clearBit()](https://github.com/RodneyShag/Interview_solutions/blob/master/Solutions/Cracking%20the%20Coding%20Interview/BitFunctions%20-%20clearBit.md) simplifies a lot of bit manipulation problems.
4 |
5 | ### Algorithm
6 |
7 | 1. Create a new `int result`.
8 | 1. Loop through the bits of the input `int n` and update `result` with the appropriate bits
9 |
10 | ### Solution
11 |
12 | ```java
13 | public class Solution {
14 | public int reverseBits(int n) {
15 | int result = 0;
16 | for (int i = 0; i < 32; i++) { // 32 bits in Java int
17 | if (getBit(n, i)) {
18 | result = setBit(result, 31 - i);
19 | }
20 | }
21 | return result;
22 | }
23 |
24 | private boolean getBit(int n, int bit) {
25 | return (n & (1 << bit)) != 0;
26 | }
27 |
28 | private int setBit(int n, int bit) {
29 | return n | (1 << bit);
30 | }
31 | }
32 | ```
33 |
34 | ### Time/Space Complexity
35 |
36 | - Time Complexity: O(1)
37 | - Space Complexity: O(1)
38 |
39 | ### Links
40 |
41 | - [github.com/RodneyShag](https://github.com/RodneyShag)
42 |
--------------------------------------------------------------------------------
/Solutions/Reverse Integer.md:
--------------------------------------------------------------------------------
1 | # Solution 1 - Using `long`
2 |
3 | ### Notes
4 |
5 | An `int` is 32 bits, so we can use a `long` to prevent integer overflow.
6 |
7 | ### Code
8 |
9 | ```java
10 | class Solution {
11 | public int reverse(int x) {
12 | long rev = 0;
13 | while (x != 0) {
14 | rev = 10 * rev + x % 10;
15 | x = x / 10;
16 | }
17 | return rev > Integer.MAX_VALUE || rev < Integer.MIN_VALUE
18 | ? 0
19 | : (int) rev;
20 | }
21 | }
22 | ```
23 |
24 | ### Examples
25 |
26 | Input: 19
27 |
28 | ```
29 | Initial: rev = 0, x = 19
30 | Iteration 1: rev = 9, x = 1
31 | Iteration 2: rev = 91, x = 0
32 | ```
33 |
34 | Input: -19
35 |
36 | ```
37 | Initial: rev = 0, x = -19
38 | Iteration 1: rev = -9, x = -1
39 | Iteration 2: rev = -91, x = 0
40 | ```
41 |
42 | The tricky part for negative numbers is that `-19 % 10 = -9`
43 |
44 | ### Time/Space Complexity
45 |
46 | - Time Complexity: O(1)
47 | - Space Complexity: O(1)
48 |
49 |
50 | # Solution 2 - Using a Math Trick
51 |
52 | ### Notes
53 |
54 | - The line `rev = 10 * rev + x % 10;` may cause overflow.
55 | - After executing the above line, we can immediately undo this line by running `(rev - x % 10) / 10`. If this doesn't give us our previous result of `rev`, we have overflow.
56 |
57 | ### Code
58 |
59 | ```java
60 | class Solution {
61 | public int reverse(int x) {
62 | int prevRev = 0;
63 | int rev = 0;
64 | while (x != 0) {
65 | rev = 10 * rev + x % 10;
66 | if ((rev - x % 10) / 10 != prevRev) { // check overflow
67 | return 0;
68 | }
69 | prevRev = rev;
70 | x = x / 10;
71 | }
72 | return rev;
73 | }
74 | }
75 | ```
76 |
77 | ### Time/Space Complexity
78 |
79 | - Time Complexity: O(1)
80 | - Space Complexity: O(1)
81 |
82 |
83 | # Links
84 |
85 | - [github.com/RodneyShag](https://github.com/RodneyShag)
86 |
--------------------------------------------------------------------------------
/Solutions/Reverse Linked List.md:
--------------------------------------------------------------------------------
1 | ### Notes
2 |
3 | Iterative solution using 3 pointers.
4 |
5 | ### Provided code
6 |
7 | ```java
8 | class ListNode {
9 | ListNode next;
10 | }
11 | ```
12 |
13 | ### Solution
14 |
15 | ```java
16 | class Solution {
17 | public ListNode reverseList(ListNode head) {
18 | if (head == null || head.next == null) {
19 | return head;
20 | }
21 | ListNode prev = null;
22 | ListNode curr = head;
23 | ListNode next = null;
24 | while (curr != null) {
25 | next = curr.next;
26 | curr.next = prev; // changes arrow direction
27 | prev = curr;
28 | curr = next;
29 | }
30 | return prev;
31 | }
32 | }
33 | ```
34 |
35 | ### Time/Space Complexity
36 |
37 | - Time Complexity: O(n)
38 | - Space Complexity: O(1)
39 |
40 | ### Links
41 |
42 | - [github.com/RodneyShag](https://github.com/RodneyShag)
43 |
--------------------------------------------------------------------------------
/Solutions/Reverse String.md:
--------------------------------------------------------------------------------
1 | ### Solution
2 |
3 | ```java
4 | class Solution {
5 | public void reverseString(char[] s) {
6 | if (s == null) {
7 | return;
8 | }
9 | for (int i = 0; i < s.length / 2; i++) {
10 | swap(s, i, s.length - 1 - i);
11 | }
12 | }
13 |
14 | private void swap(char[] array, int i, int j) {
15 | char ch = array[i];
16 | array[i] = array[j];
17 | array[j] = ch;
18 | }
19 | }
20 | ```
21 |
22 | ### Time/Space Complexity
23 |
24 | - Time Complexity: O(n)
25 | - Space Complexity: O(1)
26 |
27 | ### Links
28 |
29 | - [github.com/RodneyShag](https://github.com/RodneyShag)
30 |
--------------------------------------------------------------------------------
/Solutions/Reverse Words in a String.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | 1. Since Java Strings are immutable, convert the String to a char[]
4 | 1. Reverse entire String
5 | 1. Reverse each word
6 |
7 | ### Solution
8 |
9 | ```java
10 | class Solution {
11 | public String reverseWords(String str) {
12 | if (str == null) {
13 | return null;
14 | }
15 |
16 | char[] sentence = str.trim().replaceAll(" +", " ").toCharArray();
17 | reverse(sentence, 0, sentence.length - 1);
18 |
19 | int startOfWord = 0;
20 | for (int i = 0; i < sentence.length; i++) {
21 | if (sentence[i] == ' ') {
22 | reverse(sentence, startOfWord, i - 1);
23 | startOfWord = i + 1;
24 | }
25 | }
26 | reverse(sentence, startOfWord, sentence.length - 1); // reverse last word
27 |
28 | return String.valueOf(sentence);
29 | }
30 |
31 | private void reverse(char[] array, int start, int end) {
32 | if (array == null || start < 0 || start >= array.length || end < 0 || end >= array.length) {
33 | return;
34 | }
35 | while (start < end) {
36 | swap(array, start++, end--);
37 | }
38 | }
39 |
40 | private void swap(char[] array, int i, int j) {
41 | char temp = array[i];
42 | array[i] = array[j];
43 | array[j] = temp;
44 | }
45 | }
46 | ```
47 |
48 | ### Time/Space Complexity
49 |
50 | - Time Complexity: O(n)
51 | - Space Complexity: O(n) - but would be O(1) if we were given a char[] (instead of a String) as input.
52 |
53 | ### Links
54 |
55 | - [github.com/RodneyShag](https://github.com/RodneyShag)
56 |
--------------------------------------------------------------------------------
/Solutions/Rising Temperature.md:
--------------------------------------------------------------------------------
1 | ### Hint
2 |
3 | - Use a [SELF JOIN](https://www.w3schools.com/sql/sql_join_self.asp)
4 | - Use the built-in [DATEDIFF](https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_datediff) function to find the number of days that 2 `Date`s differ by.
5 |
6 | ### MySQL Solution
7 |
8 | ```sql
9 | SELECT w1.Id
10 | FROM
11 | Weather as w1,
12 | Weather as w2
13 | WHERE
14 | DATEDIFF(w1.RecordDate, w2.RecordDate) = 1 AND
15 | w1.Temperature > w2.Temperature
16 | ```
17 |
18 | ### Links
19 |
20 | - [github.com/RodneyShag](https://github.com/RodneyShag)
21 |
--------------------------------------------------------------------------------
/Solutions/Roman to Integer.md:
--------------------------------------------------------------------------------
1 | ### Assumption
2 |
3 | We assume input is a valid Roman numeral. For example, we assume we will not get `IM` as a Roman numeral (since `I` cannot be placed immediately before `M`)
4 |
5 | ### Algorithm
6 |
7 | 1. Create a `Map` that maps Roman Numeral Characters to their values.
8 | 1. Initialize a running `sum` to 0.
9 | 1. Loop through all characters of the array except for the last character.
10 | - if current character's value is less than next character's value, subtract current character's value from `sum`
11 | - else, add current character's value to `sum`.
12 | 1. For the last character, add it's value to the running `sum`, and return `sum`.
13 |
14 |
15 | ### Solution
16 |
17 | ```java
18 | class Solution {
19 | public int romanToInt(String s) {
20 | if (s == null || s.length() == 0) {
21 | return 0;
22 | }
23 | Map map = new HashMap();
24 | map.put('I', 1);
25 | map.put('V', 5);
26 | map.put('X', 10);
27 | map.put('L', 50);
28 | map.put('C', 100);
29 | map.put('D', 500);
30 | map.put('M', 1000);
31 |
32 | int sum = 0;
33 | for (int i = 0; i < s.length() - 1; i++) {
34 | if (map.get(s.charAt(i)) < map.get(s.charAt(i + 1))) {
35 | sum -= map.get(s.charAt(i));
36 | } else {
37 | sum += map.get(s.charAt(i));
38 | }
39 | }
40 | return sum + map.get(s.charAt(s.length() - 1));
41 | }
42 | }
43 | ```
44 |
45 | ### Time/Space Complexity
46 |
47 | - Time Complexity: O(n)
48 | - Space Complexity: O(1)
49 |
50 | ### Links
51 |
52 | - [github.com/RodneyShag](https://github.com/RodneyShag)
53 |
--------------------------------------------------------------------------------
/Solutions/Rotate Array.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | Rotate array (in place) using 3 reverse operations
4 |
5 | ### Solution
6 |
7 | ```java
8 | class Solution {
9 | public void rotate(int[] nums, int k) {
10 | if (nums == null) {
11 | return;
12 | }
13 | k %= nums.length; // to account for k > length of array
14 | reverse(nums, 0, nums.length - 1);
15 | reverse(nums, 0, k - 1);
16 | reverse(nums, k, nums.length - 1);
17 | }
18 |
19 | private void reverse(int[] array, int start, int end) {
20 | if (array == null || start < 0 || start >= array.length || end < 0 || end >= array.length) {
21 | return;
22 | }
23 | while (start < end) {
24 | swap(array, start++, end--);
25 | }
26 | }
27 |
28 | private void swap(int[] array, int i, int j) {
29 | int temp = array[i];
30 | array[i] = array[j];
31 | array[j] = temp;
32 | }
33 | }
34 | ```
35 |
36 | ### Time/Space Complexity
37 |
38 | - Time Complexity: O(n)
39 | - Space Complexity: O(1) by doing an "in place" rotation
40 |
41 | ### Links
42 |
43 | - [github.com/RodneyShag](https://github.com/RodneyShag)
44 |
--------------------------------------------------------------------------------
/Solutions/Rotate Image.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | 1. Transpose the image
4 | 1. Flip the image horizontally (along a vertical line down middle of image)
5 |
6 | Example:
7 |
8 | ```
9 | Original Tranposed Flipped
10 | 1 2 3 1 4 7 7 4 1
11 | 4 5 6 --> 2 5 8 --> 8 5 2
12 | 7 8 9 3 6 9 9 6 3
13 | ```
14 |
15 | ### Solution
16 |
17 | ```java
18 | class Solution {
19 | private int n;
20 |
21 | public void rotate(int[][] image) {
22 | if (image == null || image.length != image[0].length) {
23 | return;
24 | }
25 | n = image.length;
26 | transpose(image);
27 | flipHorizontally(image);
28 | }
29 |
30 | private void transpose(int[][] image) {
31 | for (int row = 0; row < n; row++) {
32 | for (int col = row + 1; col < n; col++) {
33 | swap(image, row, col, col, row);
34 | }
35 | }
36 | }
37 |
38 | private void flipHorizontally(int[][] image) {
39 | for (int row = 0; row < n; row++) {
40 | for (int col = 0; col < n / 2; col++) {
41 | swap(image, row, col, row, n - 1 - col);
42 | }
43 | }
44 | }
45 |
46 | private void swap(int[][] image, int r1, int c1, int r2, int c2) {
47 | int temp = image[r1][c1];
48 | image[r1][c1] = image[r2][c2];
49 | image[r2][c2] = temp;
50 | }
51 | }
52 | ```
53 |
54 | ### Time/Space Complexity
55 |
56 | - Time Complexity: O(n2)
57 | - Space Complexity: O(1)
58 |
59 | ### Links
60 |
61 | - [github.com/RodneyShag](https://github.com/RodneyShag)
62 |
--------------------------------------------------------------------------------
/Solutions/Same Tree.md:
--------------------------------------------------------------------------------
1 | ### Provided Code
2 |
3 | ```java
4 | class TreeNode {
5 | int val;
6 | TreeNode left;
7 | TreeNode right;
8 | }
9 | ```
10 |
11 | ### Solution
12 |
13 | ```java
14 | class Solution {
15 | public boolean isSameTree(TreeNode p, TreeNode q) {
16 | if (p == null && q == null) {
17 | return true;
18 | } else if (p == null || q == null) {
19 | return false;
20 | }
21 | return p.val == q.val
22 | && isSameTree(p.left, q.left)
23 | && isSameTree(p.right, q.right);
24 | }
25 | }
26 | ```
27 |
28 | ### Time/Space Complexity
29 |
30 | Let `m` be number of `TreeNodes` in `p`. Let `n` be number of `TreeNodes` in `q`.
31 |
32 | - Time Complexity: O(min(m + n))
33 | - Space Complexity: O(min(m + n))
34 |
35 | ### Links
36 |
37 | - [github.com/RodneyShag](https://github.com/RodneyShag)
38 |
--------------------------------------------------------------------------------
/Solutions/Search Insert Position.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | We can use a modified version of [binary search](https://github.com/RodneyShag/LeetCode_solutions/blob/master/Solutions/Binary%20Search.md).
4 |
5 | Since it is possible that we want to insert at the end of the array, instead of searching from `0` to `nums.length - 1`, we will search from `0` to `nums.length`.
6 |
7 | ### Solution
8 |
9 | ```java
10 | class Solution {
11 | public int searchInsert(int[] nums, int target) {
12 | if (nums == null) {
13 | return 0;
14 | }
15 | int lo = 0;
16 | int hi = nums.length;
17 | while (lo < hi) {
18 | int mid = lo + (hi - lo) / 2;
19 | if (nums[mid] < target) {
20 | lo = mid + 1;
21 | } else {
22 | hi = mid;
23 | }
24 | }
25 | return lo;
26 | }
27 | }
28 | ```
29 |
30 | ### Implementation Details
31 |
32 | Instead of calculating the middle value as `mid = (lo + hi) / 2`, do `mid = lo + (hi - lo) / 2` to avoid integer overflow.
33 |
34 | ### Time/Space Complexity
35 |
36 | - Time Complexity: O(log n)
37 | - Space Complexity: O(1)
38 |
39 | ### Links
40 |
41 | - [github.com/RodneyShag](https://github.com/RodneyShag)
42 |
--------------------------------------------------------------------------------
/Solutions/Search a 2D Matrix II.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | - On every step, eliminate a row or a column.
4 | - Start in top right corner (since the numbers below it are bigger, and numbers to left are smaller)
5 | - Always either move down (eliminating current row), or move left (eliminating current col)
6 |
7 | ### Solution
8 |
9 | ```java
10 | class Solution {
11 | public boolean searchMatrix(int[][] grid, int target) {
12 | if (grid == null || grid.length == 0 || grid[0].length == 0) {
13 | return false;
14 | }
15 | int rows = grid.length;
16 | int cols = grid[0].length;
17 |
18 | // Start at top right corner
19 | int r = 0;
20 | int c = cols - 1;
21 |
22 | while (r < rows && c >= 0) {
23 | if (grid[r][c] == target) {
24 | return true;
25 | } else if (grid[r][c] > target) {
26 | c--;
27 | } else {
28 | r++;
29 | }
30 | }
31 | return false;
32 | }
33 | }
34 | ```
35 |
36 | ### Time/Space Complexity
37 |
38 | - Time Complexity: O(rows + cols)
39 | - Space Complexity: O(1)
40 |
41 | ### Alternative Solution 1
42 |
43 | Instead of starting from top-right and moving to bottom-left, do it the other way around: start from bottom-left and move to top-right.
44 |
45 | ### Alternative Solution 2
46 |
47 | Binary search every row. However, this solution is slower, as it's for O(rows * log(cols)) runtime.
48 |
49 | ### Links
50 |
51 | - [github.com/RodneyShag](https://github.com/RodneyShag)
52 |
--------------------------------------------------------------------------------
/Solutions/Search in Rotated Sorted Array.md:
--------------------------------------------------------------------------------
1 | ### Tips
2 |
3 | - Trick: Endpoints of array give us valuable information. We apply a modified binary search to this problem.
4 | - Although binary search compares the "middle value" to the "target value", we will break up the cases differently. We will compare middle value `A[mid]` to the start value `A[lo]`
5 | - Array can only have 1 inflection point, therefore it is either to the left or right of `mid`. That means 1/2 of the array is ordered normally (in increasing order) and the other half has the inflection point.
6 |
7 | ### Assumptions
8 |
9 | - Code assumes input array is:
10 | 1. Not null
11 | 1. Sorted then optionally rotated
12 | 1. Without duplicate integers.
13 |
14 | ### Solution
15 |
16 | ```java
17 | public class Solution {
18 | public int search(int[] A, int target) {
19 | int lo = 0;
20 | int hi = A.length - 1;
21 | while (lo <= hi) {
22 | int mid = (lo + hi) / 2;
23 | if (A[mid] == target) {
24 | return mid;
25 | }
26 | if (A[lo] < A[mid]) { // in this case, left side CANNOT have inflection point, and is increasing.
27 | if (A[lo] <= target && target < A[mid]) {
28 | hi = mid - 1;
29 | } else {
30 | lo = mid + 1;
31 | }
32 | } else if (A[lo] > A[mid]) {
33 | if (A[mid] < target && target <= A[hi]) {
34 | lo = mid + 1;
35 | } else {
36 | hi = mid - 1;
37 | }
38 | } else { // since no duplicates in input. Only happens when array is size <=2, so (lo == mid).
39 | lo = mid + 1; // search right, since A[lo] was already compared to 'target'.
40 | }
41 | }
42 | return -1;
43 | }
44 | }
45 | ```
46 |
47 | ### Time/Space Complexity
48 |
49 | - Time Complexity: O(log n) since no duplicates exist in array
50 | - Space Complexity: O(1)
51 |
52 | ### Links
53 |
54 | - [github.com/RodneyShag](https://github.com/RodneyShag)
55 |
--------------------------------------------------------------------------------
/Solutions/Second Highest Salary.md:
--------------------------------------------------------------------------------
1 | ### Initial thoughts
2 |
3 | ```sql
4 | SELECT DISTINCT Salary AS SecondHighestSalary
5 | FROM Employee
6 | ORDER BY Salary DESC
7 | LIMIT 1 OFFSET 1
8 | ```
9 |
10 | The above solution will fail if there is no 2nd-highest salary.
11 |
12 | ### MySQL Solution
13 |
14 | Since the 2nd-highest salary may not exist, we have to turn our original query into a subquery, and wrap it in a `Select`:
15 |
16 | ```sql
17 | SELECT
18 | (
19 | SELECT DISTINCT Salary FROM Employee
20 | ORDER BY Salary DESC
21 | LIMIT 1 OFFSET 1
22 | )
23 | AS SecondHighestSalary
24 | ```
25 |
26 | ### Links
27 |
28 | - [github.com/RodneyShag](https://github.com/RodneyShag)
29 |
--------------------------------------------------------------------------------
/Solutions/Shortest Unsorted Continuous Subarray.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | - Find these 2 indices
4 | - `endIndex`: index that, if we sort from 0 to endIndex, entire array is sorted
5 | - `startIndex`: index that, if we sort from startIndex to end, entire array is sorted
6 | - Sorting from `startIndex` to `endIndex` will make the entire array sorted
7 |
8 | ### Solution
9 |
10 | ```java
11 | class Solution {
12 | public int findUnsortedSubarray(int[] array) {
13 | if (array == null || array.length == 0) {
14 | return 0;
15 | }
16 |
17 | int startIndex = -1;
18 | int endIndex = -1;
19 |
20 | // find endIndex
21 | int maxSoFar = array[0];
22 | for (int i = 0; i < array.length; i++) {
23 | if (array[i] < maxSoFar) {
24 | endIndex = i;
25 | }
26 | maxSoFar = Math.max(maxSoFar, array[i]);
27 | }
28 |
29 | // find startIndex
30 | int minSoFar = array[array.length - 1];
31 | for (int i = array.length - 1; i >= 0; i--) {
32 | if (array[i] > minSoFar) {
33 | startIndex = i;
34 | }
35 | minSoFar = Math.min(minSoFar, array[i]);
36 | }
37 |
38 | if (startIndex == -1 || endIndex == -1) {
39 | return 0;
40 | }
41 | return endIndex - startIndex + 1;
42 | }
43 | }
44 | ```
45 |
46 | ### Time/Space Complexity
47 |
48 | - Time Complexity: O(n)
49 | - Space Complexity: O(1)
50 |
51 | ### Links
52 |
53 | - [github.com/RodneyShag](https://github.com/RodneyShag)
54 |
--------------------------------------------------------------------------------
/Solutions/Shuffle an Array.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | - Loop through the array. For each element at index `i`, swap it with a random element in interval `[0, i]` inclusive.
4 | - This swap ensures randomness in 2 ways:
5 | 1. That each element in the array from `[0, i]` has an equal chance of being the ith element.
6 | 1. That the original ith element has an equal chance of being anywhere in the array in `[0, i]`
7 | - At each iteration of our `for` loop, the array from `[0, i]` has elements in random order.
8 |
9 | ### Solution
10 |
11 | ```java
12 | class Solution {
13 | Random random = new Random();
14 | int[] original;
15 | int[] array;
16 |
17 | public Solution(int[] nums) {
18 | if (nums == null) {
19 | throw new IllegalArgumentException();
20 | }
21 | original = nums.clone();
22 | array = nums;
23 | }
24 |
25 | public int[] reset() {
26 | array = original.clone();
27 | return array;
28 | }
29 |
30 | public int[] shuffle() {
31 | for (int i = 1; i < array.length; i++) {
32 | int rand = random.nextInt(i + 1); // random int from [0, i+1) exclusive. Same as [0, i] inclusive
33 | swap(array, i, rand);
34 | }
35 | return array;
36 | }
37 |
38 | private void swap(int[] array, int i, int j) {
39 | int temp = array[i];
40 | array[i] = array[j];
41 | array[j] = temp;
42 | }
43 | }
44 | ```
45 |
46 | ### Time/Space Complexity
47 |
48 | - Time Complexity: O(n)
49 | - Space Complexity: O(n) to store our original array
50 |
51 | ### Links
52 |
53 | - [github.com/RodneyShag](https://github.com/RodneyShag)
54 |
--------------------------------------------------------------------------------
/Solutions/Single Number.md:
--------------------------------------------------------------------------------
1 | ### Notes
2 |
3 | uses XOR. Keep in mind:
4 |
5 | 1. x ^ x = 0
6 | 1. x ^ 0 = x
7 | 1. XOR is commutative and associative
8 |
9 | ### Solution
10 |
11 | ```java
12 | class Solution {
13 | public int singleNumber(int[] array) {
14 | int result = 0;
15 | for (int num : array) {
16 | result = result ^ num; // ^ is XOR operator
17 | }
18 | return result;
19 | }
20 | }
21 | ```
22 |
23 | ### Time/Space Complexity
24 |
25 | - Time Complexity: O(n)
26 | - Space Complexity: O(1)
27 |
28 | ### Links
29 |
30 | - [github.com/RodneyShag](https://github.com/RodneyShag)
31 |
--------------------------------------------------------------------------------
/Solutions/Sqrt(x).md:
--------------------------------------------------------------------------------
1 | # Solution 1 - Binary Search
2 |
3 | ### Assumptions
4 |
5 | We assume input `x` is non-negative (0 or more) as stated in the problem.
6 |
7 | ### Algorithm
8 |
9 | - If we find a number `m` where m2 <= x and (m + 1)2 > x, then `m` is `sqrt(x)` due to truncation. Example:
10 | - If `x` is 10, and `m` is 3, then we have
11 | - m2 = 9 which is less than x
12 | - (m + 1)2 = 16 which is greater than `x`
13 | - So sqrt(10) = 3 due to truncation of decimal digits.
14 |
15 | Use [binary search](https://github.com/RodneyShag/LeetCode_solutions/blob/master/Solutions/Binary%20Search.md) to find `m`
16 |
17 | ### Solution
18 |
19 | ```java
20 | class Solution {
21 | public int mySqrt(int x) {
22 | if (x == 0) {
23 | return 0;
24 | }
25 | int lo = 1;
26 | int hi = x;
27 | while (true) {
28 | int mid = lo + (hi - lo) / 2;
29 | if (mid <= x / mid && (mid + 1) > x / (mid + 1)) {
30 | return mid;
31 | } else if (mid < x / mid) {
32 | lo = mid + 1;
33 | } else {
34 | hi = mid - 1;
35 | }
36 | }
37 | }
38 | }
39 | ```
40 |
41 | ### Avoiding integer overflow
42 |
43 | - We rewrote `mid = (lo + hi) / 2` as `mid = lo + (hi - lo) / 2` to avoid integer overflow
44 | - We rewrote `mid * mid <= x` as `mid <= x / mid` to avoid integer overflow
45 |
46 | ### Time/Space Complexity
47 |
48 | - Time Complexity: O(log n)
49 | - Space Complexity: O(1)
50 |
51 |
52 | # Solution 2 - Newton's Method
53 |
54 | _Newton's Method_ is also an O(log n) solution, but is faster than binary search since it makes better guesses for the square root in each iteration of the `while` loop.
55 |
56 | ### Code
57 |
58 | ```java
59 | class Solution {
60 | public int mySqrt(int x) {
61 | if (x == 0) {
62 | return 0;
63 | }
64 | long r = x; // use `long` so r*r is calculated as a `long`
65 | while (r*r > x) {
66 | r = (r + x/r) / 2;
67 | }
68 | return (int) r;
69 | }
70 | }
71 | ```
72 |
73 | ### Time/Space Complexity
74 |
75 | - Time Complexity: O(log n)
76 | - Space Complexity: O(1)
77 |
78 |
79 | # Links
80 |
81 | - [github.com/RodneyShag](https://github.com/RodneyShag)
82 |
--------------------------------------------------------------------------------
/Solutions/String Compression.md:
--------------------------------------------------------------------------------
1 | ### Solution
2 |
3 | ```java
4 | class Solution {
5 | public int compress(char[] array) {
6 | if (array == null || array.length == 0) {
7 | return 0;
8 | }
9 | int i = 0; // for reading
10 | int j = 0; // for writing
11 |
12 | while (i < array.length) {
13 | char currentChar = array[i];
14 | int count = 0;
15 | while (i < array.length && array[i] == currentChar) {
16 | count++;
17 | i++;
18 | }
19 | array[j++] = currentChar;
20 | if (count > 1) {
21 | for (char ch : String.valueOf(count).toCharArray()) {
22 | array[j++] = ch;
23 | }
24 | }
25 | }
26 | return j;
27 | }
28 | }
29 | ```
30 |
31 | ### Time/Space Complexity
32 |
33 | - Time Complexity: O(n)
34 | - Space Complexity: O(log n) due to our `toCharArray()` call which uses O(log10 n) space, where the 10 represents the number of possible digits 0-9.
35 |
36 | ### Links
37 |
38 | - [github.com/RodneyShag](https://github.com/RodneyShag)
39 |
--------------------------------------------------------------------------------
/Solutions/Subarray Sum Equals K.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | 1. Use Dynamic Programming. For each element in array, save the sum from beginning of array until that element.
4 | - key: sum
5 | - value: number of contiguous arrays, starting at beginning of array, that sum to "key: sum"
6 | 1. Our `HashMap` tells us `SUM[0...i]`. Our current `sum` gives us `SUM[0...j]`. So subtraction gives us `SUM[0...j] - SUM[0...i] = SUM(i...j]` (the parenthesis is there since `i` is not included in that range). Each `SUM(i...j] == k` gives us 1 solution.
7 |
8 | ### Solution
9 |
10 | ```java
11 | class Solution {
12 | public int subarraySum(int[] nums, int k) {
13 | Map savedSum = new HashMap();
14 | savedSum.put(0, 1);
15 | int sum = 0;
16 | int result = 0;
17 | for (int num : nums) {
18 | sum += num;
19 | result += savedSum.getOrDefault(sum - k, 0);
20 | savedSum.merge(sum, 1, Integer::sum);
21 | }
22 | return result;
23 | }
24 | }
25 | ```
26 |
27 | ### Time/Space Complexity
28 |
29 | - Time Complexity: O(n)
30 | - Space Complexity: O(n)
31 |
32 | ### Similar Problems
33 |
34 | [Path Sum III](https://leetcode.com/problems/path-sum-iii)
35 |
36 | ### Links
37 |
38 | - [github.com/RodneyShag](https://github.com/RodneyShag)
39 |
--------------------------------------------------------------------------------
/Solutions/Subsets II.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | - This is the same question as [the "Subsets" problem](https://leetcode.com/problems/subsets) - Here's [my solution to that problem](https://github.com/RodneyShag/LeetCode_solutions/blob/master/Solutions/LeetCode/Subsets.md)
4 | - We will make 2 changes to the solution above to account for removing duplicates
5 | 1. Use a `Set` to remove duplicates. For input [1,1,4] we don't want subset [1,4] to exist twice in our solution
6 | 1. Since we are using a `Set>`, we will run into a problem if our input set is [1,4,1], as our code will create lists: [1,4] and [4,1]. To prevent this, we will sort our input set [1,4,1] to [1,1,4]. Now our code will create lists [1,4] and [1,4] where one of them will be removed by our `Set`
7 |
8 | ### Solution
9 |
10 | ```java
11 | class Solution {
12 | public List> subsetsWithDup(int[] array) {
13 | if (array == null || array.length == 0) {
14 | return new ArrayList();
15 | }
16 | Arrays.sort(array);
17 | Set> solutions = new HashSet();
18 | makeSubsets(array, 0, solutions, new ArrayList());
19 | return new ArrayList(solutions);
20 | }
21 |
22 | private void makeSubsets(int[] array, int i, Set> solutions, List list) {
23 | if (i == array.length) {
24 | solutions.add(new ArrayList(list));
25 | return;
26 | }
27 |
28 | // don't use array[i]
29 | makeSubsets(array, i + 1, solutions, list);
30 |
31 | // use array[i]
32 | list.add(array[i]);
33 | makeSubsets(array, i + 1, solutions, list);
34 | list.remove(list.size() - 1);
35 | }
36 | }
37 | ```
38 |
39 | ### Time/Space Complexity
40 |
41 | There are 2n subsets to generate, and each one takes `O(n)` time to copy the `list` into our `solutions`
42 |
43 | - Time Complexity: O(n * 2n)
44 | - Space Complexity: O(n * 2n)
45 |
46 | ### Links
47 |
48 | - [github.com/RodneyShag](https://github.com/RodneyShag)
49 |
--------------------------------------------------------------------------------
/Solutions/Subsets.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | - Use "Backtracking" - an algorithm for finding all solutions by exploring all potential candidates.
4 | - Loop through the array, for each index, we have 2 possible "paths" to take.
5 | 1. Don't use the number (and recursively continue)
6 | 1. Use the number (and recursively continue).
7 |
8 | ### Solution
9 |
10 | ```java
11 | class Solution {
12 | public List> subsets(int[] array) {
13 | if (array == null || array.length == 0) {
14 | return new ArrayList();
15 | }
16 | List> solutions = new ArrayList();
17 | makeSubsets(array, 0, solutions, new ArrayList());
18 | return solutions;
19 | }
20 |
21 | private void makeSubsets(int[] array, int i, List> solutions, List list) {
22 | if (i == array.length) {
23 | solutions.add(new ArrayList(list));
24 | return;
25 | }
26 |
27 | // don't use array[i]
28 | makeSubsets(array, i + 1, solutions, list);
29 |
30 | // use array[i]
31 | list.add(array[i]);
32 | makeSubsets(array, i + 1, solutions, list);
33 | list.remove(list.size() - 1);
34 | }
35 | }
36 | ```
37 |
38 | ### Time/Space Complexity
39 |
40 | There are 2n subsets to generate, and each one takes `O(n)` time to copy the `list` into our `solutions`
41 |
42 | - Time Complexity: O(n * 2n)
43 | - Space Complexity: O(n * 2n)
44 |
45 | ### Similar BackTracking Problems
46 |
47 | - [Subsets II](https://leetcode.com/problems/subsets-ii)
48 | - [Letter Combinations of a Phone Number](https://leetcode.com/problems/letter-combinations-of-a-phone-number)
49 | - [N-Queens](https://leetcode.com/problems/n-queens)
50 | - [Permutations](https://leetcode.com/problems/permutations) and [Permutations II](https://leetcode.com/problems/permutations-ii)
51 |
52 | ### Links
53 |
54 | - [github.com/RodneyShag](https://github.com/RodneyShag)
55 |
--------------------------------------------------------------------------------
/Solutions/Sum of Two Integers.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | - We can represent addition by using the AND operator (`&`) and XOR (`^`) operator.
4 | - AND will give us the 'carry', and XOR will give us the 'sum'. The 'carry' and 'sum' together will give us our result.
5 | - This solution works for negative numbers as well.
6 |
7 | ### Solution
8 |
9 | ```java
10 | class Solution {
11 | public int getSum(int a, int b) {
12 | if (b == 0) {
13 | return a;
14 | }
15 | int sum = a ^ b;
16 | int carry = (a & b) << 1;
17 | return getSum(sum, carry);
18 | }
19 | }
20 | ```
21 |
22 | ### Example
23 |
24 | ```
25 | a = 001
26 | b = 011
27 |
28 | a ^ b = 010 // 'sum'
29 | (a & b) << 1 = 010 // 'carry'
30 | ```
31 |
32 | ```
33 | Now we add the 'sum' (shown as 'a') and 'carry' (shown as 'b')
34 |
35 | a = 010
36 | b = 010
37 |
38 | a ^ b = 000 // 'sum'
39 | (a & b) << 1 = 100 // 'carry'
40 | ```
41 |
42 | ```
43 | Again, we add 'sum' and 'carry'
44 |
45 | a ^ b = 100 // 'sum'
46 | (a & b) << 1 = 000 // 'carry'
47 |
48 | Now that we no longer have a carry, our algorithm finishes, and we return 'sum' of 100
49 | ```
50 |
51 | ### Time/Space Complexity
52 |
53 | - Time Complexity: O(1)
54 | - Space Complexity: O(1)
55 |
56 | ### Additional Notes
57 |
58 | Using AND and XOR operators is literally how addition is done in circuits, using a [Half Adder](https://en.wikipedia.org/wiki/Adder_%28electronics%29#Half_adder)
59 |
60 | ### Links
61 |
62 | - [github.com/RodneyShag](https://github.com/RodneyShag)
63 |
--------------------------------------------------------------------------------
/Solutions/Swap Salary.md:
--------------------------------------------------------------------------------
1 | ### MySQL Solution
2 |
3 | ```sql
4 | UPDATE salary
5 | SET sex = IF(sex = 'm', 'f', 'm');
6 | ```
7 |
8 | ### Links
9 |
10 | - [github.com/RodneyShag](https://github.com/RodneyShag)
11 |
--------------------------------------------------------------------------------
/Solutions/Symmetric Tree.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | - A tree is a mirror image of itself if its left and right subtrees are mirror images of each other.
4 | - Two trees are mirror images of each other if:
5 | 1. Their roots are equal
6 | 1. The left subtree of `tree1` is a mirror image of the right subtree of `tree2`
7 | 1. The right subtree of `tree1` is a mirror image of the left subtree of `tree2`
8 |
9 | ### Provided Code
10 |
11 | ```java
12 | class TreeNode {
13 | int val;
14 | TreeNode left;
15 | TreeNode right;
16 | }
17 | ```
18 |
19 | ### Solution
20 |
21 | ```java
22 | class Solution {
23 | public boolean isSymmetric(TreeNode root) {
24 | return isMirror(root, root);
25 | }
26 |
27 | private boolean isMirror(TreeNode t1, TreeNode t2) {
28 | if (t1 == null && t2 == null) {
29 | return true;
30 | } else if (t1 == null || t2 == null) {
31 | return false;
32 | } else {
33 | return t1.val == t2.val &&
34 | isMirror(t1.left, t2.right) &&
35 | isMirror(t1.right, t2.left);
36 | }
37 | }
38 | }
39 | ```
40 |
41 | ### Time/Space Complexity
42 |
43 | - Time Complexity: O(n) since we visit each `TreeNode` once
44 | - Space Complexity: O(log n) for a balanced tree, O(n) otherwise. The space complexity is due to recursion.
45 |
46 | ### Links
47 |
48 | - [github.com/RodneyShag](https://github.com/RodneyShag)
49 |
--------------------------------------------------------------------------------
/Solutions/Third Maximum Number.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | - Use a `TreeSet`, as it is kind of like a `Set` and `PriorityQueue` combined
4 | - the `Set` part will remove duplicates for us
5 | - the `PriorityQueue` part will keep our elements in sorted order
6 | - If `TreeSet` size grows beyond 3, remove the first (smallest) element in it, so that the 3rd element is always our third maximum number.
7 |
8 | ### Solution
9 |
10 | ```java
11 | class Solution {
12 | public int thirdMax(int[] nums) { // assumes `nums` size is 1 or more
13 | TreeSet ts = new TreeSet();
14 | for (int n : nums) {
15 | ts.add(n);
16 | if (ts.size() > 3) {
17 | ts.pollFirst();
18 | }
19 | }
20 | return ts.size() < 3 ? ts.last() : ts.first();
21 | }
22 | }
23 | ```
24 |
25 | ### Time/Space Complexity
26 |
27 | - Time Complexity: O(n) since `TreeSet` has a fixed size of 3.
28 | - Space Complexity: O(1)
29 |
30 | ### Links
31 |
32 | - [github.com/RodneyShag](https://github.com/RodneyShag)
33 |
--------------------------------------------------------------------------------
/Solutions/To Lower Case.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | This problem forbids us from using `str.toLowerCase()` which is a simple working solution. We will code a similar function below
4 |
5 | - We assume only English letters (A to Z) need to be lowercased
6 | - Uppercase letters are numbers 65 to 90 in an [ASCII table](http://www.asciitable.com)
7 | - Lowercase letters are numbers 97 to 122 in the same table
8 | - Notice uppercase letters and lowercase letters differ by 32 in the ASCII table:
9 | - 'A' + 32 = 65 + 32 = 97 = 'a'
10 | - 'Z' + 32 = 97 + 32 = 122 = 'z'
11 |
12 | ### Solution
13 |
14 | ```java
15 | class Solution {
16 | public String toLowerCase(String s) {
17 | if (s == null) {
18 | return s;
19 | }
20 | char[] arr = s.toCharArray();
21 | for (int i = 0; i < arr.length; i++) {
22 | if (arr[i] >= 'A' && arr[i] <= 'Z') {
23 | arr[i] += 32;
24 | }
25 | }
26 | return new String(arr);
27 | }
28 | }
29 | ```
30 |
31 | ### Time/Space Complexity
32 |
33 | - Time Complexity: O(s)
34 | - Space Complexity: O(s)
35 |
36 | ### Links
37 |
38 | - [github.com/RodneyShag](https://github.com/RodneyShag)
39 |
--------------------------------------------------------------------------------
/Solutions/Top K Frequent Elements.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | 1. Create `HashMap` of number frequencies. Frequency = # of times a number appears in array.
4 | 1. Create buckets, 1 for each possible frequency. Fill buckets with numbers from input, based on their frequency.
5 | 1. To get the most frequent elements, loop through the buckets in descending order.
6 |
7 | Edge case: Two numbers can be tied for more frequent element. The problem doesn't say what to do in this case, so you should ask the interviewer about this.
8 |
9 | ### Solution
10 |
11 | ```java
12 | class Solution {
13 | public List topKFrequent(int[] nums, int k) {
14 | if (nums == null || nums.length == 0) {
15 | return Collections.emptyList();
16 | }
17 |
18 | Map map = new HashMap();
19 | for (int num : nums) {
20 | map.merge(num, 1, Integer::sum);
21 | }
22 |
23 | List> buckets = new ArrayList(nums.length + 1); // wont use 0th bucket
24 | for (int i = 0; i < nums.length + 1; i++) {
25 | buckets.add(new ArrayList());
26 | }
27 |
28 | for (Integer num : map.keySet()) {
29 | int frequency = map.get(num);
30 | List bucket = buckets.get(frequency);
31 | bucket.add(num);
32 | }
33 |
34 | List solution = new ArrayList();
35 | for (int i = buckets.size() - 1; i >= 0 && solution.size() < k; i--) {
36 | List bucket = buckets.get(i);
37 | solution.addAll(bucket);
38 | }
39 | return solution.subList(0, k); // needed since above loop can add more than k elements into list
40 | }
41 | }
42 | ```
43 |
44 | ### Time/Space Complexity
45 |
46 | - Time Complexity: O(n)
47 | - Space Complexity: O(n)
48 |
49 | ### Links
50 |
51 | - [github.com/RodneyShag](https://github.com/RodneyShag)
52 |
--------------------------------------------------------------------------------
/Solutions/Total Hamming Distance.md:
--------------------------------------------------------------------------------
1 | ### Algorithm + Example
2 |
3 | Solve [LeetCode #461 - Hamming Distance](https://leetcode.com/problems/hamming-distance) first before solving this problem. [Here is that problem's solution](https://github.com/RodneyShag/LeetCode_solutions/blob/master/Solutions/Hamming%20Distance.md).
4 |
5 | If there are `n` integers in the array and `k` of them have a particular bit set and `n-k` do not, then that bit contributes `k * (n - k)` hamming distance to the total.
6 |
7 | ```
8 | a = 0 1 0
9 | b = 0 1 1
10 | c = 0 0 1
11 | d = 0 1 0
12 | e = 1 1 0
13 | ↑
14 | ```
15 |
16 | - Let's calculate the Hamming Distance for the last digit of all the numbers
17 | - There are 5 numbers above. For the last digit, we have 3 ones and 2 zeros
18 | - This gives us `total hamming distance = ones * zeros = 3 * 2 = 6`. Let's doublecheck this by examining every pair we can make using the last digits in the numbers:
19 |
20 | ```
21 | (0, 0) (0, 1) (0, 0) (0, 0)
22 | (1, 1) (1, 0) (1, 0)
23 | (1, 0) (1, 0)
24 | (0, 0)
25 | ```
26 |
27 | Notice only 6 of the above 10 pairs have both a `0` and a `1`, so only 6 of them contribute to the hamming distance.
28 |
29 | To get the total hamming distance, use this idea on all 32 digits, which is the size of a Java `int`
30 |
31 | ### Solution
32 |
33 | ```java
34 | class Solution {
35 | public int totalHammingDistance(int[] nums) {
36 | if (nums == null) {
37 | return 0;
38 | }
39 | int total = 0;
40 | for (int i = 0; i < 32; i++) {
41 | int ones = 0;
42 | for (int j = 0; j < nums.length; j++) {
43 | ones += (nums[j] >> i) & 1;
44 | }
45 | total += ones * (nums.length - ones);
46 | }
47 | return total;
48 | }
49 | }
50 | ```
51 |
52 | ### Time/Space Complexity
53 |
54 | - Time Complexity: O(n)
55 | - Space Complexity: O(1)
56 |
57 | ### Links
58 |
59 | - [github.com/RodneyShag](https://github.com/RodneyShag)
60 |
--------------------------------------------------------------------------------
/Solutions/Trips and Users.md:
--------------------------------------------------------------------------------
1 | ### MySQL Solution
2 |
3 | ```sql
4 | SELECT Request_at AS Day,
5 | ROUND(SUM(Status != "completed") / COUNT(*), 2) AS 'Cancellation Rate'
6 | FROM Trips AS t
7 | INNER JOIN Users AS c ON t.Client_Id = c.Users_Id AND c.Banned = 'No'
8 | INNER JOIN Users AS d ON t.Driver_Id = d.Users_Id AND d.Banned = 'No'
9 | WHERE Request_at BETWEEN '2013-10-01' AND '2013-10-03'
10 | GROUP BY Request_at;
11 | ```
12 |
13 | ### Alternate Solution
14 |
15 | Instead of `INNER JOIN`, we can use separate `SELECT` queries:
16 |
17 | ```sql
18 | SELECT Request_at AS Day,
19 | ROUND(SUM(Status != "completed") / COUNT(*), 2) AS 'Cancellation Rate'
20 | FROM Trips
21 | WHERE (Request_at BETWEEN '2013-10-01' AND '2013-10-03') AND
22 | Client_Id IN (SELECT Users_Id FROM Users WHERE Banned = 'No') AND
23 | Driver_Id IN (SELECT Users_Id FROM Users WHERE Banned = 'No')
24 | GROUP BY Request_at;
25 | ```
26 |
27 | ### Links
28 |
29 | - [github.com/RodneyShag](https://github.com/RodneyShag)
30 |
--------------------------------------------------------------------------------
/Solutions/Two Sum II - Input array is sorted.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | - Use 2 pointers. let `i` point to 0th element in array, and `j` to point to last element in array.
4 | - Sum the values at the 2 indexes.
5 | - If the sum is too small, increment `i` (so we can look at larger values)
6 | - If the sum is too big, decrement `j` (so we can look at smaller values)
7 | - If the sum equals `target`, we found a solution
8 |
9 | ### Example
10 |
11 | ```
12 | target = 9
13 |
14 | i j
15 | [2 7 11 15] 2 + 15 = 17. Sum is bigger than 9. Decrement j.
16 |
17 | i j
18 | [2 7 11 15] 2 + 11 = 13. Sum is bigger than 9. Decrement j.
19 |
20 | i j
21 | [2 7 11 15] 2 + 7 = 9 = target. We found a solution.
22 | ```
23 |
24 | ### Solution
25 |
26 | ```java
27 | class Solution {
28 | public int[] twoSum(int[] nums, int target) {
29 | if (nums == null || nums.length < 2) {
30 | return null;
31 | }
32 | int i = 0;
33 | int j = nums.length - 1;
34 | while (i < j) {
35 | int sum = nums[i] + nums[j];
36 | if (sum < target) {
37 | i++;
38 | } else if (sum > target) {
39 | j--;
40 | } else {
41 | break;
42 | }
43 | }
44 | // Problem's output counts indexes starting at [1, 2...]
45 | return new int[]{i + 1, j + 1};
46 | }
47 | }
48 | ```
49 |
50 | ### Time/Space Complexity
51 |
52 | - Time Complexity: O(n)
53 | - Space Complexity: O(1)
54 |
55 | ### Links
56 |
57 | - [github.com/RodneyShag](https://github.com/RodneyShag)
58 |
--------------------------------------------------------------------------------
/Solutions/Two Sum.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | 1. We are given an array of numbers. Given an index, this array returns a number in O(1) time.
4 | 1. However, we want something different. We would rather have a data structure that, when provided a _value_, gives us the _index_ in O(1) time. `HashMap` to the rescue!
5 | 1. Create a `HashMap`. As we loop through the array, populate the `HashMap` with each number, where the `HashMap` "key" is the number, and the `HashMap` "value" is the index of the number in the array.
6 | 1. For each number, we check our `HashMap` to see if the complement exists in it. If so, we've found a pair of numbers that create our solution.
7 |
8 | Implementation Detail: First check the `HashMap` for the complement before putting the current number in it.
9 |
10 | ### Solution
11 |
12 | ```java
13 | class Solution {
14 | public int[] twoSum(int[] array, int target) throws IllegalArgumentException {
15 | Map map = new HashMap();
16 | for (int i = 0; i < array.length; i++) {
17 | int complement = target - array[i];
18 | if (map.containsKey(complement)) {
19 | return new int[]{ map.get(complement), i };
20 | }
21 | map.put(array[i], i);
22 | }
23 | throw new IllegalArgumentException("No two sum solution");
24 | }
25 | }
26 | ```
27 |
28 | ### Time/Space Complexity
29 |
30 | - Time Complexity: O(n)
31 | - Space Complexity: O(n)
32 |
33 | ### Links
34 |
35 | - [github.com/RodneyShag](https://github.com/RodneyShag)
36 |
--------------------------------------------------------------------------------
/Solutions/Ugly Number II.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | This can be viewed as a dynamic programming problem, where the n-th ugly number depends on previous ugly numbers in range [0,n)
4 |
5 | If the problem had instead asked for "numbers that have either 2, 3, or 5" as a factor (instead of "__only__ be divided by 2,3,5"), we could create 3 lists (see below) and return the elements in these lists in ascending order.
6 |
7 | ```
8 | (List 1) Multiples of 2: 1*2, 2*2, 3*2, 4*2, ...
9 | (List 2) Multiples of 3: 1*3, 2*3, 3*3, 4*3, ...
10 | (List 3) Multiples of 5: 1*5, 2*5, 3*5, 4*5, ...
11 | ```
12 |
13 | For illustration purposes, let's take a look at the ugly numbers:
14 | ```
15 | 1, 2, 3, 4, 5, 6, 8, 9, 10, 12... (notice that numbers 7, 11 are missing)
16 | ```
17 |
18 | Since ugly numbers can __only__ be divided by 2, 3, 5, the sequence can be split into 3 groups:
19 | ```
20 | (List 1) ugly number sequence * 2: 1*2, 2*2, 3*2, 4*2, 5*2, 6*2, 8*2 ...
21 | (List 2) ugly number sequence * 3: 1*3, 2*3, 3*3, 4*3, 5*3, 6*3, 8*3 ...
22 | (List 3) ugly number sequence * 5: 1*5, 2*5, 3*5, 4*5, 5*5, 6*5, 8*5 ...
23 | ```
24 |
25 | Use variable `i2`, `i3`, and `i5` to represent which index we are at in each of the above lists, and return the elements in these lists in ascending order
26 |
27 | ### Solution
28 |
29 | ```java
30 | class Solution {
31 | public int nthUglyNumber(int n) {
32 | if (n < 0) {
33 | return -1;
34 | }
35 | int[] ugly = new int[n];
36 | ugly[0] = 1;
37 |
38 | int i2 = 0;
39 | int i3 = 0;
40 | int i5 = 0;
41 |
42 | for (int i = 1; i < n; i++) {
43 | ugly[i] = Math.min(ugly[i2] * 2, Math.min(ugly[i3] * 3, ugly[i5] * 5));
44 | if (ugly[i] == ugly[i2] * 2) {
45 | i2++;
46 | }
47 | if (ugly[i] == ugly[i3] * 3) {
48 | i3++;
49 | }
50 | if (ugly[i] == ugly[i5] * 5) {
51 | i5++;
52 | }
53 | }
54 | return ugly[n-1];
55 | }
56 | }
57 | ```
58 |
59 | ### Time/Space Complexity
60 |
61 | - Time Complexity: O(n)
62 | - Space Complexity: O(n)
63 |
64 | ### References
65 |
66 | - Solution is from [Geek for Geeks - Ugly Numbers](https://www.geeksforgeeks.org/ugly-numbers/) Method 2, which is also the solution most liked on LeetCode
67 |
68 | ### Links
69 |
70 | - [github.com/RodneyShag](https://github.com/RodneyShag)
71 |
--------------------------------------------------------------------------------
/Solutions/Ugly Number.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | Sample ugly numbers are 1, 2, 3, 4, 5, 6, 8, 9, 10, 12...
4 |
5 | For a number to be an ugly number, it's prime factorization should only include 2, 3, and 5:
6 |
7 | ```
8 | 2
9 | 2 * 2
10 | 2 * 3
11 | 2 * 3 * 5
12 | 2 * 2 * 3 * 3 * 5 * 5 * 5
13 | ```
14 |
15 | To find ugly numbers, we remove all factors of 2, 3, and 5 using division. If the end result is 1, then the original input was an ugly number.
16 |
17 | ### Solution
18 |
19 | ```java
20 | class Solution {
21 | public boolean isUgly(int n) {
22 | if (n < 1) {
23 | return false;
24 | }
25 | int[] divisors = {2, 3, 5};
26 | for (int d : divisors) {
27 | while (n % d == 0) {
28 | n = n / d;
29 | }
30 | }
31 | return n == 1;
32 | }
33 | }
34 | ```
35 |
36 | ### Time/Space Complexity
37 |
38 | Max size of an `int` in Java is a constant 32 bits, and we usually don't take number of bits into consideration for complexity analysis.
39 |
40 | - Time Complexity: O(1)
41 | - Space Complexity: O(1)
42 |
43 | ### Links
44 |
45 | - [github.com/RodneyShag](https://github.com/RodneyShag)
46 |
--------------------------------------------------------------------------------
/Solutions/Unique Number of Occurrences.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | 1. Count the number of occurrences of each number in the array. Save these counts in a `Map`.
4 | 1. Check if any of the "values" in the `Map` are repeated:
5 | - put all the `Map` values in a `Set`
6 | - compare the sizes of the `Map` and `Set`. If they're the same size, then the `Map` has all unique values.
7 |
8 | ### Solution
9 |
10 | ```java
11 | class Solution {
12 | public boolean uniqueOccurrences(int[] nums) {
13 | if (nums == null) {
14 | return true;
15 | }
16 |
17 | Map map = new HashMap();
18 | for (int n : nums) {
19 | map.merge(n, 1, Integer::sum);
20 | }
21 |
22 | Set set = new HashSet(map.values());
23 | return map.size() == set.size();
24 | }
25 | }
26 | ```
27 |
28 | ### Time/Space Complexity
29 |
30 | - Time Complexity: O(n)
31 | - Space Complexity: O(n)
32 |
33 | ### Links
34 |
35 | - [github.com/RodneyShag](https://github.com/RodneyShag)
36 |
--------------------------------------------------------------------------------
/Solutions/Unique Paths II.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | This is a dynamic programming problem.
4 |
5 | Our robot can only move down and right. So for each cell, there are 2 ways to get to it. In most cases this gives us `maze[r][c] = maze[r][c - 1] + maze[r - 1][c]`. The rest of the code accounts for edge cases:
6 | 1. If a cell has a "1" in it
7 | 1. Top-Left corner cell
8 | 1. Top Row
9 | 1. Left Column
10 |
11 | ### Solution
12 |
13 | ```java
14 | class Solution {
15 | int count = 0;
16 | public int uniquePathsWithObstacles(int[][] maze) {
17 | if (maze == null || maze[0][0] == 1) {
18 | return 0;
19 | }
20 | int rows = maze.length;
21 | int cols = maze[0].length;
22 |
23 | for (int r = 0; r < rows; r++) {
24 | for (int c = 0; c < cols; c++) {
25 | if (maze[r][c] == 1) {
26 | maze[r][c] = 0;
27 | } else if (r == 0 && c == 0) {
28 | maze[r][c] = 1;
29 | } else if (r == 0) {
30 | maze[r][c] = maze[r][c - 1];
31 | } else if (c == 0) {
32 | maze[r][c] = maze[r - 1][c];
33 | } else {
34 | maze[r][c] = maze[r][c - 1] + maze[r - 1][c];
35 | }
36 | }
37 | }
38 |
39 | return maze[rows - 1][cols - 1];
40 | }
41 | }
42 | ```
43 |
44 | ### Time/Space Complexity
45 |
46 | - Time Complexity: O(rows * cols)
47 | - Space Complexity: O(1), assuming we're allowed to alter the original maze
48 |
49 | ### Links
50 |
51 | - [github.com/RodneyShag](https://github.com/RodneyShag)
52 |
--------------------------------------------------------------------------------
/Solutions/Unique Paths.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | We can solve this problem mathematically using the "Combinations" formula:
4 |
5 | - Let x = number of moves to go from left side of grid to right side of grid
6 | - Let y = number of moves to go from top of grid to bottom of grid (assuming no obstacles)
7 |
8 | ```
9 | (x + y)!
10 | --------
11 | (x!)(y!)
12 | ```
13 |
14 | - There are (x+y) moves total. Choose x of them to go right, (and the remaining y moves will pick themselves)
15 |
16 | Example: For a 3x3 maze, we get x = 2, y = 2. Our formula gives (2+2)!((2!)(2!)) = 6.
17 |
18 | ### Efficient calculation
19 |
20 | Instead of calculating the above formula directly, we can cancel factors before calculating the product. For example:
21 |
22 | ```
23 | (5 + 3)! 8*7*6*5*4*3*2*1 8*7*6
24 | -------- = ------------------ = -----
25 | (5!)(3!) (5*4*3*2*1)(3*2*1) 3*2*1
26 | ```
27 |
28 | The code below shows implements this approach
29 |
30 | ### Solution
31 |
32 | ```java
33 | class Solution {
34 | public int uniquePaths(int m, int n) throws IllegalArgumentException {
35 | if (m > n) {
36 | return uniquePaths(n, m); // so that 1st argument is smaller, to improve runtime.
37 | }
38 | if (m < 1 || n < 1) {
39 | throw new IllegalArgumentException();
40 | }
41 |
42 | int downSteps = m - 1;
43 | int rightSteps = n - 1;
44 | int totalSteps = downSteps + rightSteps;
45 |
46 | long product = 1; // use long instead of int to avoid integer overflow
47 | int numBot = 1;
48 | for (int numTop = rightSteps + 1; numTop <= totalSteps; numTop++, numBot++) {
49 | product *= numTop;
50 | product /= numBot;
51 | }
52 | return (int) product;
53 | }
54 | }
55 | ```
56 |
57 | ### Time/Space Complexity
58 |
59 | - Time Complexity: O(min(m + n))
60 | - Space Complexity: O(1)
61 |
62 | ### Links
63 |
64 | - [github.com/RodneyShag](https://github.com/RodneyShag)
65 |
--------------------------------------------------------------------------------
/Solutions/Valid Anagram.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | - Do a quick check on string lengths. If the lengths differ, the strings can't be anagrams
4 | - Save `String s` as `HashMap` of character counts
5 | - For `String t`, see if it can be made up of the characters of the previous `HashMap`
6 |
7 | ### Solution
8 |
9 | ```java
10 | class Solution {
11 | public boolean isAnagram(String s, String t) {
12 | if (s.length() != t.length()) {
13 | return false;
14 | }
15 | Map map = new HashMap();
16 | for (int i = 0; i < s.length(); i++) {
17 | char ch = s.charAt(i);
18 | map.merge(ch, 1, Integer::sum);
19 | }
20 | for (int i = 0; i < t.length(); i++) {
21 | char ch = t.charAt(i);
22 | if (!map.containsKey(ch) || map.get(ch) == 0) {
23 | return false;
24 | }
25 | map.merge(ch, -1, Integer::sum);
26 | }
27 | return true;
28 | }
29 | }
30 | ```
31 |
32 | ### Time/Space Complexity
33 |
34 | - Time Complexity: O(n)
35 | - Space Complexity: O(1), since our HashMap has a maximum size corresponding either to 256 ASCII characters, or to about 1 million Unicode characters.
36 |
37 | ### Links
38 |
39 | - [github.com/RodneyShag](https://github.com/RodneyShag)
40 |
--------------------------------------------------------------------------------
/Solutions/Valid Palindrome.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | 1. Create 2 pointers, setting 1 to point to head of list, and 1 to point to tail of list.
4 | 1. Skip over any character that's not a letter or digit. Lowercase all characters.
5 | 1. If the 2 pointers don't point to equivalent characters, we don't have a palindrome. Otherwise, move the pointers closer to the center of the `String` and repeat steps 2-3 until all characters are checked.
6 | 1. If all pairs we checked are equivalent, we have a palindrome.
7 |
8 | ### Solution
9 |
10 | ```java
11 | class Solution {
12 | public boolean isPalindrome(String s) {
13 | if (s == null || s.length() == 0) {
14 | return true;
15 | }
16 | int i = 0;
17 | int j = s.length() - 1;
18 | while (i < j) {
19 | if (!Character.isLetterOrDigit(s.charAt(i))) {
20 | i++;
21 | } else if (!Character.isLetterOrDigit(s.charAt(j))) {
22 | j--;
23 | } else {
24 | if (Character.toLowerCase(s.charAt(i)) !=
25 | Character.toLowerCase(s.charAt(j))) {
26 | return false;
27 | }
28 | i++;
29 | j--;
30 | }
31 | }
32 | return true;
33 | }
34 | }
35 | ```
36 |
37 | ### Time/Space Complexity
38 |
39 | - Time Complexity: O(n)
40 | - Space Complexity: O(1)
41 |
42 | ### Links
43 |
44 | - [github.com/RodneyShag](https://github.com/RodneyShag)
45 |
--------------------------------------------------------------------------------
/Solutions/Valid Parentheses.md:
--------------------------------------------------------------------------------
1 | ### Notes
2 |
3 | - Create `HashMap` to match opening brackets with closing brackets.
4 | - `ArrayDeque` is "likely to be faster than Stack when used as a stack" - [Java documentation](https://docs.oracle.com/javase/8/docs/api/java/util/ArrayDeque.html)
5 |
6 | ### Solution
7 |
8 | ```java
9 | class Solution {
10 | public boolean isValid(String str) {
11 | if ((str.length() % 2) != 0) {
12 | return false; // odd length Strings are not balanced
13 | }
14 |
15 | Map map = new HashMap();
16 | map.put('(', ')');
17 | map.put('[', ']');
18 | map.put('{', '}');
19 |
20 | Deque deque = new ArrayDeque(); // use deque as a stack
21 | for (int i = 0; i < str.length(); i++) {
22 | char ch = str.charAt(i);
23 | if (map.containsKey(ch)) {
24 | deque.push(ch);
25 | } else if (deque.isEmpty() || ch != map.get(deque.pop())) {
26 | return false;
27 | }
28 | }
29 | return deque.isEmpty();
30 | }
31 | }
32 | ```
33 |
34 | ### Time/Space Complexity
35 |
36 | - Time Complexity: O(n)
37 | - Space Complexity: O(n)
38 |
39 | ### Links
40 |
41 | - [github.com/RodneyShag](https://github.com/RodneyShag)
42 |
--------------------------------------------------------------------------------
/Solutions/Valid Perfect Square.md:
--------------------------------------------------------------------------------
1 | # Solution 1 - Binary Search
2 |
3 | Use [binary search](https://github.com/RodneyShag/LeetCode_solutions/blob/master/Solutions/Binary%20Search.md) to keep guessing different `int` values that may qualify as the square root of `n`
4 |
5 | ### Code
6 |
7 | ```java
8 | class Solution {
9 | public boolean isPerfectSquare(int n) {
10 | if (n < 0) {
11 | return false;
12 | }
13 | int lo = 0;
14 | int hi = n;
15 | while (lo <= hi) {
16 | int mid = lo + (hi - lo) / 2;
17 | long squared = (long) mid * mid; // use `long` to avoid integer overflow
18 | if (squared == n) {
19 | return true;
20 | } else if (squared < n) {
21 | lo = mid + 1;
22 | } else {
23 | hi = mid - 1;
24 | }
25 | }
26 | return false;
27 | }
28 | }
29 | ```
30 |
31 | ### Time/Space Complexity
32 |
33 | - Time Complexity: O(log n)
34 | - Space Complexity: O(1)
35 |
36 |
37 | # Solution 2 - Newton's Method
38 |
39 | _Newton's Method_ is also an O(log n) solution, but is faster than binary search since it makes better guesses for the square root in each iteration of the `while` loop. [This LeetCode post](https://leetcode.com/problems/valid-perfect-square/discuss/130010/Python-4-Methods-with-time-testing) compares the actual runtimes of _binary search_ and _Newton's method_.
40 |
41 | ### Code
42 |
43 | ```java
44 | class Solution {
45 | public boolean isPerfectSquare(int x) {
46 | if (x < 0) {
47 | return false;
48 | }
49 | long r = x; // use `long` so r*r is calculated as a `long`
50 | while (r*r > x) {
51 | r = (r + x/r) / 2;
52 | }
53 | return r*r == x;
54 | }
55 | }
56 | ```
57 |
58 | ### Time/Space Complexity
59 |
60 | - Time Complexity: O(log n)
61 | - Space Complexity: O(1)
62 |
63 |
64 | # Links
65 |
66 | - [github.com/RodneyShag](https://github.com/RodneyShag)
67 |
--------------------------------------------------------------------------------
/Solutions/Validate Binary Search Tree.md:
--------------------------------------------------------------------------------
1 | ### Provided code
2 |
3 | ```java
4 | class TreeNode {
5 | int val;
6 | TreeNode left;
7 | TreeNode right;
8 | }
9 | ```
10 |
11 | ### Solution
12 |
13 | ```java
14 | class Solution {
15 | public boolean isValidBST(TreeNode root) {
16 | return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);
17 | }
18 |
19 | private boolean isValidBST(TreeNode node, long min, long max) {
20 | if (node == null) {
21 | return true;
22 | } else if (node.val <= min || node.val >= max) {
23 | return false;
24 | }
25 | return isValidBST(node.left, min, node.val) && isValidBST(node.right, node.val, max);
26 | }
27 | }
28 | ```
29 |
30 | ### Time/Space Complexity
31 |
32 | - Time Complexity: O(n)
33 | - Space Complexity: O(log n) if balanced tree. O(n) if not balanced.
34 |
35 | ### Links
36 |
37 | - [github.com/RodneyShag](https://github.com/RodneyShag)
38 |
--------------------------------------------------------------------------------
/Solutions/Word Pattern.md:
--------------------------------------------------------------------------------
1 | ### Algorithm
2 |
3 | 1. Since spaces are not part of the pattern, we split our string on spaces and save it as an array of words.
4 | 1. Loop through each ith character in `pattern`, and compare it with ith word.
5 | - Save these `Character` to `String` mappings in `map1`.
6 | - Due to "bijection" requirement in problem, where 2 Characters can't map to same word, we will store `String` to `Character` mappings in `map2`.
7 | - If at any time during the loop we violate any pattern-matching or bijection principles, return false.
8 |
9 | ### Solution
10 |
11 | ```java
12 | class Solution {
13 | public boolean wordPattern(String pattern, String str) {
14 | if (pattern == null || str == null || pattern.length() == 0 || str.length() == 0) {
15 | return false;
16 | }
17 | String[] words = str.split(" ");
18 | if (words.length != pattern.length()) {
19 | return false;
20 | }
21 |
22 | Map map1 = new HashMap();
23 | Map map2 = new HashMap();
24 |
25 | for (int i = 0; i < pattern.length(); i++) {
26 | char ch = pattern.charAt(i);
27 | if (map1.containsKey(ch) && !map1.get(ch).equals(words[i])) {
28 | return false;
29 | } else if (map2.containsKey(words[i]) && map2.get(words[i]) != ch) {
30 | return false; // due to "bijection" requirement in problem
31 | }
32 | map1.put(ch, words[i]);
33 | map2.put(words[i], ch);
34 | }
35 | return true;
36 | }
37 | }
38 | ```
39 |
40 | ### Time/Space Complexity
41 |
42 | - Time Complexity: O(n)
43 | - Space Complexity: O(n)
44 |
45 | ### Links
46 |
47 | - [github.com/RodneyShag](https://github.com/RodneyShag)
48 |
--------------------------------------------------------------------------------
/Solutions/images/BidirectionalSearch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RodneyShag/LeetCode_solutions/b56b664100baa180c6c30bf546112a115418f017/Solutions/images/BidirectionalSearch.png
--------------------------------------------------------------------------------
/Solutions/images/sieveOfEratosthenes.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RodneyShag/LeetCode_solutions/b56b664100baa180c6c30bf546112a115418f017/Solutions/images/sieveOfEratosthenes.gif
--------------------------------------------------------------------------------