├── .gitignore ├── 000-099 ├── 001-Two-Sum.cpp ├── 001-Two-Sum.java ├── 002-Add-Two-Numbers.cpp ├── 003-Longest-Substring-Without-Repeating-Characters.cpp ├── 005-Longest-Palindromic-Substring.md ├── 006-ZigZag-Conversion.cpp ├── 007-Reverse-Integer.cpp ├── 008-String-to-Integer-(atoi).cpp ├── 009-Palindrome-Number.cpp ├── 010-Regular-Expression-Matching.md ├── 011-Container-With-Most-Water.java ├── 011-Container-With-Most-Water.md ├── 012-Integer-to-Roman.cpp ├── 013-Roman-to-Integer.java ├── 014-Longest-Common-Prefix.cpp ├── 015-3Sum.cpp ├── 016-3Sum-Closest.cpp ├── 017-Letter-Combinations-of-a-Phone-Number.cpp ├── 018-4Sum.cpp ├── 019-Remove-Nth-Node-From-End-of-List.cpp ├── 019-Remove-Nth-Node-From-End-of-List.java ├── 020-Valid-Parentheses.java ├── 021-Merge-Two-Sorted-List.cpp ├── 021-Merge-Two-Sorted-Lists.java ├── 022-Generate-Parentheses.cpp ├── 023-Merge-k-Sorted-Lists.cpp ├── 024-Swap-Nodes-in-Pairs.java ├── 025-Reverse-Nodes-in-k-Group.md ├── 026-Remove-Duplicates-from-Sorted-Array.cpp ├── 026-Remove-Duplicates-from-Sorted-Array.java ├── 027-Remove-Element.java ├── 028-Implement-strStr().java ├── 033-Search-in-Rotated-Sorted-Array.md ├── 034-Find-First-and-Last-Position-of-Element-in-Sorted-Array.cpp ├── 034-Find-First-and-Last-Position-of-Element-in-Sorted-Array.java ├── 035-Search-Insert-Position.cpp ├── 035-Search-Insert-Position.java ├── 038-Count-and-Say.cpp ├── 041-First-Missing-Positive.md ├── 042-Trapping-Rain-Water.md ├── 043-Multiply-Strings.cpp ├── 044-Wildcard-Matching.md ├── 045-Jump-Game-II.md ├── 046-Permutations.cpp ├── 047-Permutations-II.cpp ├── 048-Rotate-Image.cpp ├── 048-Rotate-Image.java ├── 049-Group-Anagrams.cpp ├── 050-Pow(x,n).md ├── 051-N-Queens.cpp ├── 052-N-Queens-II.cpp ├── 053-Maximum-Subarray.java ├── 053-Maximum-Subarray.md ├── 054-Spiral-Matrix.java ├── 055-Jump-Game.java ├── 055-Jump-Game.md ├── 056-Merge-Intervals.md ├── 057-Insert-Interval.cpp ├── 058-Length-of-Last-Word.java ├── 059-Sprial-Matrix-II.java ├── 061-Rotate-List.java ├── 062-Unique-Paths.java ├── 063-Unique-Paths-II.java ├── 064-Minimum-Path-Sum.java ├── 066-Plus-One.java ├── 067-Add-Binary.cpp ├── 069-Sqrt(x).java ├── 070-Climbing-Stairs.java ├── 071-Simplify-Path.cpp ├── 072-Edit-Distance.md ├── 073-Set-Matrix-Zeroes.md ├── 074-Search-a-2D-Matrix.cpp ├── 075-Sort-Colors.java ├── 076-Minimum-Window-Substring.md ├── 078-Subsets.md ├── 079-Word-Search.cpp ├── 080-Remove-Duplicates-from-Sorted-Array-II.md ├── 081-Search-in-Rotated-Sorted-Array-II.md ├── 082-Remove-Duplicates-from-Sorted-List-II.md ├── 083-Remove-Duplicates-from-Sorted-List.java ├── 083-Remove-Duplicates-from-Sorted-List.md ├── 084-Largest-Rectangle-in-Histogram.md ├── 085-Maximal-Rectangle.md ├── 086-Partition-List.md ├── 088-Merge-Sorted-Array.java ├── 091-Decode-Ways.md ├── 092-Reverse-Linked-List-II.cpp ├── 094-Binary-Tree-Inorder-Traversal.cpp ├── 094-Binary-Tree-Inorder-Traversal.java ├── 095-Unique-Binary-Search-Trees-II.md ├── 096-Unique-Binary-Search-Trees.md ├── 097-Interleaving-String.md └── 098-Validate-Binary-Search-Tree.cpp ├── 100-199 ├── 100-Same-Tree.java ├── 101-Symmetric-Tree.java ├── 102-Binary-Tree-Level-Order-Traversal.cpp ├── 103-Binary-Tree-Zigzag-Level-Order-Traversal.cpp ├── 104-Maximum-Depth-of-Binary-Tree.java ├── 105-Construct-Binary-Tree-from-Preorder-and-Inorder-Traversal.md ├── 106-Construct-Binary-Tree-from-Inorder-and-Postorder-Traversal.cpp ├── 107-Binary-Tree-Level-Order-Traversal-II.cpp ├── 108-Convert-Sorted-Array-to-Binary-Search-Tree.cpp ├── 109-Convert-Sorted-List-to-Binary-Search Tree.md ├── 110-Balanced-Binary-Tree.cpp ├── 111-Minimum-Depth-of-Binary-Tree.md ├── 112-Path-Sum.cpp ├── 112-Path-Sum.java ├── 113-Path-Sum-II.cpp ├── 115-Distinct-Subsequences.md ├── 116-Populating-Next-Right-Pointers-in-Each-Node.cpp ├── 117-Populating-Next-Right-Pointers-in-Each-Node-II.cpp ├── 118-Pascal's-Triangle.cpp ├── 119-Pascal's-Triangle-II.cpp ├── 120-Triangle.java ├── 121-Best-Time-to-Buy-and-Sell-Stock.md ├── 122-Best-Time-to-Buy-and-Sell-Stock-II.md ├── 123-Best-Time-to-Buy-and-Sell-Stock-III.md ├── 124-Binary-Tree-Maximum-Path-Sum.md ├── 125-Valid-Palindrome.cpp ├── 128-Longest-Consecutive-Sequence.md ├── 129-Sum-Root-to-Leaf-Numbers.cpp ├── 130-Surrounded-Regions.cpp ├── 133-Clone-Graph.md ├── 134-Gas-Station.java ├── 136-Single-Number.md ├── 137-Single-Number-II.md ├── 138-Copy-List-with-Random-Pointer.md ├── 141-Linked-List-Cycle.md ├── 142-Linked-List-Cycle-II.md ├── 143-Reorder-List.java ├── 144-Binary-Tree-Preorder-Traversal.cpp ├── 145-Binary-Tree-Postorder-Traversal.md ├── 146-LRU-Cache.cpp ├── 147-Insertion-Sort-List.java ├── 150-Evaluate-Reverse-Polish-Notation.cpp ├── 152-Maximum-Product-Subarray.md ├── 153-Find-Minimum-in-Rotated-Sorted-Array.cpp ├── 154-Find-Minimum-in-Rotated-Sorted-Array-II.cpp ├── 155-Min-Stack.md ├── 159-Longest-Substring-with-At-Most-Two-Distinct-Characters.cpp ├── 160-Intersection-of-Two-Linked-Lists.md ├── 161-One-Edit-Distance.cpp ├── 162-Find-Peak-Element.cpp ├── 167-Two-Sum-II---Input-array-is-sorted.java ├── 170-Two-Sum-III---Data-structure-design.cpp ├── 173-Binary-Search-Tree-Iterator.md ├── 179-Largest-Number.cpp ├── 182-Duplicate-Emails.sql ├── 188-Best-Time-to-Buy-and-Sell-Stock-IV.md ├── 198-House-Robber.md └── 199-Binary-Tree-Right-Side-View.md ├── 1000-1099 ├── 1019-Next-Greater-Node-In-Linked-List.md ├── 1023-Camelcase-Matching.cpp ├── 1029-Two-City-Scheduling.cpp ├── 1032-Stream-of-Characters.md ├── 1047-Remove-All-Adjacent-Duplicates-In-String.cpp ├── 1053-Previous-Permutation-With-One-Swap.md ├── 1059-All-Paths-from-Source-Lead-to-Destination.md ├── 1060-Missing-Element-in-Sorted-Array.cpp ├── 1095-Find-in-Mountain-Array.cpp └── 1099-Two-Sum-Less-Than-K.cpp ├── 1100-1199 ├── 1101-The-Earliest-Moment-When-Everyone-Become-Friends.cpp ├── 1136-Parallel-Courses.md ├── 1143-Longest-Common-Subsequence.md ├── 1184-Distance-Between-Bus-Stops.cpp ├── 1185-Day-of-the-Week.cpp ├── 1186-Maximum-Subarray-Sum-with-One-Deletion.md └── 1189-Maximum-Number-of-Balloons.cpp ├── 1200-1299 ├── 1214-Two-Sum-BSTs.cpp ├── 1216-Valid-Palindrome-III.md ├── 1256-Encode-Number.cpp ├── 1281-Subtract-the-Product-and-Sum-of-Digits-of-an-Integer.cpp ├── 1289-Minimum-Falling-Path-Sum-II.cpp └── 1295-Find-Numbers-with-Even-Number-of-Digits.cpp ├── 1300-1399 ├── 1325-Delete-Leaves-With-a-Given-Value.cpp ├── 1329-Sort-the-Matrix-Diagonally.md ├── 1354-Construct-Target-Array-With-Multiple-Sums.md ├── 1367-Linked-List-in-Binary-Tree.md └── 1396-Design-Underground-System.cpp ├── 1400-1499 ├── 1474-Delete-N-Nodes-After-M-Nodes-of-a-Linked-List.cpp ├── 1480-Running-Sum-of-1d-Array.cpp ├── 1491-Average-Salary-Excluding-the-Minimum-and-Maximum-Salary.cpp ├── 1492-The-kth-Factor-of-n.md ├── 1493-Longest-Subarray-of-1's-After-Deleting-One-Element.md └── 1494-Parallel-Courses-II.md ├── 200-299 ├── 200-Number-of-Islands.cpp ├── 202-Happy-Number.cpp ├── 203-Remove-Linked-List-Elements.java ├── 206-Reverse-Linked-List.md ├── 207-Course-Schedule.md ├── 208-Implement-Trie-(Prefix-Tree).cpp ├── 210-Course-Schedule-II.md ├── 211-Add-and-Search-Word---Data-structure-design.cpp ├── 213-House-Robber-II.md ├── 215-Kth-Largest-Element-in-an-Array.md ├── 217-Contains-Duplicate.cpp ├── 219-Contains-Duplicate-II.cpp ├── 221-Maximal-Square.md ├── 223-Rectangle-Area.cpp ├── 224-Basic-Calculator.md ├── 225-Implement-Stack-using-Queues.md ├── 228-Summary-Ranges.cpp ├── 234-Palindrome-Linked-List.cpp ├── 235-Lowest-Common-Ancestor-of-a-Binary-Search-Tree.cpp ├── 236-Lowest-Common-Ancestor-of-a-Binary-Tree.cpp ├── 237-Delete-Node-in-a-Linked-List.md ├── 238-Product-of-Array-Except-Self.md ├── 240-Search-a-2D-Matrix-II.java ├── 242-Valid-Anagram.cpp ├── 243-Shortest-Word-Distance.cpp ├── 244-Shortest-Word-Distance-II.cpp ├── 245-Shortest-Word-Distance-III.cpp ├── 246-Strobogrammatic-Number.cpp ├── 247-Strobogrammatic-Number-II.cpp ├── 249-Group-Shifted-Strings.cpp ├── 250-Count-Univalue-Subtrees.cpp ├── 252-Meeting-Rooms.cpp ├── 253-Meeting-Rooms-II.cpp ├── 256-Paint-House.cpp ├── 257-Binary-Tree-Paths.cpp ├── 258-Add-Digits.cpp ├── 259-3Sum-Smaller.cpp ├── 263-Ugly-Number.cpp ├── 264-Ugly-Number-II.cpp ├── 265-Paint-House-II.cpp ├── 266-Palindrome-Permutation.cpp ├── 268-Missing-Number.cpp ├── 269-Alien-Dictionary.md ├── 270-Closest-Binary-Search-Tree-Value.cpp ├── 272-Closest-Binary-Search-Tree-Value-II.cpp ├── 276-Paint-Fence.cpp ├── 278-First-Bad-Version.cpp ├── 279-Perfect-Squares.md ├── 283-Move-Zeroes.md ├── 285-Inorder-Successor-in-BST.md ├── 286-Walls-and-Gates.cpp ├── 295-Find-Median-from-Data-Stream.md ├── 297-Serialize-and-Deserialize-Binary-Tree.cpp └── 298-Binary-Tree-Longest-Consecutive-Sequence.cpp ├── 300-399 ├── 300-Longest-Increasing-Subsequence.md ├── 303-Range-Sum-Query---Immutable.cpp ├── 304-Range-Sum-Query-2D---Immutable.cpp ├── 310-Minimum-Height-Tree.md ├── 314-Binary-Tree-Vertical-Order-Traversal.cpp ├── 319-Bulb-Switcher.cpp ├── 322-Coin-Change.md ├── 326-Power-of-Three.cpp ├── 328-Odd-Even-Linked-List.md ├── 333-Largest-BST-Subtree.cpp ├── 337-House-Robber-III.md ├── 338-Counting-Bits.cpp ├── 339-Nested-List-Weight-Sum.cpp ├── 340-Longest-Substring-with-At-Most-K-Distinct-Characters.cpp ├── 342-Power-of-Four.cpp ├── 344-Reverse-String.cpp ├── 345-Reverse-Vowels-of-a-String.md ├── 346-Moving-Average-from-Data-Stream.cpp ├── 347-Top-K-Frequent-Elements.md ├── 349-Intersection-of-Two-Arrays.cpp ├── 366-Find-Leaves-of-Binary-Tree.cpp ├── 369-Plus-One-Linked-List.md ├── 374-Guess-Number-Higher-or-Lower.cpp ├── 376-Valid-Perfect-Square.cpp ├── 380-Insert-Delete-GetRandom-O(1).cpp ├── 383-Ransom-Note.cpp ├── 387-First-Unique-Character-in-a-String.cpp ├── 389-Find-the-Difference.md └── 392-Is-Subsequence.cpp ├── 400-499 ├── 404-Sum-of-Left-Leaves.cpp ├── 412-Fizz-Buzz.cpp ├── 415-Add-String.cpp ├── 421-Maximum-XOR-of-Two-Numbers-in-an-Array.md ├── 429-N-ary-Tree-Level-Order-Traversal.cpp ├── 430-Flatten-a-Multilevel-Doubly-Linked-List.md ├── 437-Path-Sum-III.md ├── 445-Add-Two-Numbers-II.md ├── 448-Find-All-Numbers-Disappeared-in-an-Array.md ├── 449-Serialize-and-Deserialize-BST.cpp ├── 451-Sort-Characters-By-Frequency.cpp ├── 452-Minimum-Number-of-Arrows-to-Burst-Balloons.md ├── 485-Max-Consecutive-Ones.cpp ├── 489-Robot-Room-Cleaner.cpp ├── 490-The-Maze.cpp ├── 496-Next-Greater-Element-I.cpp └── 498-Diagonal-Traverse.cpp ├── 500-599 ├── 500-Keyboard-Row.cpp ├── 501-Find-Mode-in-Binary-Search-Tree.md ├── 503-Next-Greater-Element-II.cpp ├── 513-Find-Bottom-Left-Tree-Value.md ├── 515-Find-Largest-Value-in-Each-Tree-Row.cpp ├── 523-Continuous-Subarray-Sum.md ├── 525-Contiguous-Array.md ├── 529-Minesweeper.cpp ├── 547-Friend-Circles.md ├── 559-Maximum-Depth-of-N-ary-Tree.cpp ├── 560-Subarray-Sum-Equals-K.md ├── 563-Binary-Tree-Tilt.cpp ├── 589-N-ary-Tree-Preorder-Traversal.cpp └── 590-N-ary-Tree-Postorder-Traversal.cpp ├── 600-699 ├── 617-Merge-Two-Binary-Trees.cpp ├── 637-Average-of-Levels-in-Binary-Tree.cpp ├── 653-Two-Sum-IV---Input-is-a-BST.md ├── 665-Non-decreasing-Array.java ├── 673-Number-of-Longest-Increasing-Subsequence.md ├── 674-Longest-Continuous-Increasing-Subsequence.cpp ├── 676-Implement-Magic-Dictionary.md ├── 677-Map-Sum-Pairs.md ├── 680-Valid-Palindrome-II.cpp ├── 684-Redundant-Connection.cpp ├── 687-Longest-Univalue-Path.cpp ├── 692-Top-K-Frequent-Words.cpp └── 695-Max-Area-of-Island.cpp ├── 700-799 ├── 700-Search-in-a-Binary-Search-Tree.cpp ├── 701-Insert-into-a-Binary-Search-Tree.cpp ├── 702-Search-in-a-Sorted-Array-of-Unknown-Size.cpp ├── 703-Kth-Largest-Element-in-a-Stream.md ├── 704-Binary-Search.cpp ├── 707-Design-Linked-List.cpp ├── 708-Insert-into-a-Sorted-Circular-Linked-List.cpp ├── 717-1-bit-and-2-bit-Characters.cpp ├── 720-Longest-Word-in-Dictionary.cpp ├── 723-Candy-Crush.cpp ├── 725-Split-Linked-List-in-Parts.cpp ├── 733-Flood-Fill.cpp ├── 744-Find-Smallest-Letter-Greater-Than-Target.cpp ├── 746-Min-Cost-Climbing-Stairs.cpp ├── 754-Reach-a-Number.cpp ├── 771-Jewels-and-Stones.cpp ├── 780-Reaching-Points.md ├── 785-Is-Graph-Bipartite.cpp └── 792-Number-of-Matching-Subsequences.md ├── 800-899 ├── 811-Subdomain-Visit-Count.cpp ├── 829-Consecutive-Numbers-Sum.md ├── 852-Peak-Index-in-a-Mountain-Array.cpp ├── 855-Exam-Room.md ├── 876-Middle-of-the-Linked-Lists.md ├── 881-Boats-to-Save-People.md └── 896-Monotonic-Array.cpp ├── 900-999 ├── 923-3Sum-With-Multiplicity.md ├── 931-Minimum-Falling-Path-Sum.cpp ├── 938-Range-Sum-of-BST.cpp ├── 965-Univalued-Binary-Tree.cpp ├── 977-Squares-of-a-Sorted-Array.cpp ├── 979-Distribute-Coins-in-Binary-Tree.md └── 987-Vertical-Order-Traversal-of-a-Binary-Tree.cpp ├── README.md ├── Topics ├── Binary-Search.md ├── Bit-Manipulation.md ├── C++-Memo.md ├── Disjoint-Set.md ├── Divide-and-Conquer.md ├── Dynamic-Programming.md ├── Graph.md ├── Heap-&-Priority-Queue.md ├── K-Palindrome.md ├── K-Sum.md ├── Linked-List.md ├── Monotonic-Stack-&-Queue.md ├── Path-Sum.md ├── Segment-Tree.md ├── Topological-Sort.md ├── Tree.md └── Trie.md ├── _config.yml └── img ├── 142.jpg ├── 160_1.jpg ├── 160_2.jpg ├── 421.png ├── tree_traverse.png └── trie.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode -------------------------------------------------------------------------------- /000-099/001-Two-Sum.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public int[] twoSum(int[] nums, int target) { 3 | Map map = new HashMap<>(); 4 | for (int i = 0; i < nums.length; i++) { 5 | int complement = target - nums[i]; 6 | if (map.containsKey(complement)) { 7 | return new int[] { map.get(complement), i }; 8 | } 9 | map.put(nums[i], i); 10 | } 11 | throw new IllegalArgumentException("No two sum solution"); 12 | } 13 | } -------------------------------------------------------------------------------- /000-099/002-Add-Two-Numbers.cpp: -------------------------------------------------------------------------------- 1 | // len(l1) = m, len(l2) = n. 2 | // Time complexity: O(max(m, n)). 3 | // Space complexity: O(max(m, n)). 4 | 5 | /** 6 | * Definition for singly-linked list. 7 | * struct ListNode { 8 | * int val; 9 | * ListNode *next; 10 | * ListNode(int x) : val(x), next(NULL) {} 11 | * }; 12 | */ 13 | class Solution { 14 | public: 15 | ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { 16 | ListNode *dummy_head{new ListNode{0}}; 17 | ListNode *p{l1}, *q{l2}, *curr{dummy_head}; 18 | int carry{0}; 19 | 20 | while (p || q) { 21 | int x{(p) ? p->val : 0}; 22 | int y{(q) ? q->val : 0}; 23 | int sum{carry + x + y}; 24 | carry = sum / 10; 25 | curr->next = new ListNode{sum % 10}; 26 | curr = curr->next; 27 | if (p) p = p->next; 28 | if (q) q = q->next; 29 | } 30 | if (carry > 0) { 31 | curr->next = new ListNode{carry}; 32 | } 33 | 34 | return dummy_head->next; 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /000-099/003-Longest-Substring-Without-Repeating-Characters.cpp: -------------------------------------------------------------------------------- 1 | // Sliding Window 2 | 3 | // Time complexity: O(N). 4 | // Extra space complexity: O(N). 5 | 6 | class Solution { 7 | public: 8 | int lengthOfLongestSubstring(string s) { 9 | unordered_set lookup; 10 | int max_len = 0; 11 | int left = 0; 12 | int right = 0; 13 | while (right < s.size()) { 14 | if (lookup.find(s[right]) == lookup.end()) { 15 | lookup.insert(s[right]); 16 | } else { 17 | while (s[left] != s[right]) { 18 | lookup.erase(s[left]); 19 | ++left; 20 | } 21 | ++left; 22 | } 23 | ++right; 24 | max_len = max(right - left, max_len); 25 | } 26 | return max_len; 27 | } 28 | }; 29 | 30 | // Number of chars limited: simpler solution 31 | class Solution2 { 32 | public: 33 | int lengthOfLongestSubstring(string s) { 34 | int ans = 0; 35 | int left = 0; 36 | int right = 0; 37 | unordered_map m; 38 | 39 | while (right < s.size()) { 40 | m[s[right]]++; 41 | while (m[s[right]] > 1) { 42 | m[s[left]]--; 43 | left++; 44 | } 45 | ans = max(right - left + 1, ans); 46 | right++; 47 | } 48 | 49 | return ans; 50 | } 51 | }; 52 | -------------------------------------------------------------------------------- /000-099/006-ZigZag-Conversion.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(n). 3 | 4 | class Solution { 5 | public: 6 | string convert(string s, int numRows) { 7 | if (numRows == 1) return s; 8 | 9 | vector rows(min(numRows, int(s.size()))); 10 | int curRow = 0; 11 | bool goingDown = false; 12 | for (char c : s) { 13 | rows[curRow] += c; 14 | if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown; 15 | curRow += goingDown ? 1 : -1; 16 | } 17 | 18 | string ans; 19 | for (string& row : rows) ans += row; 20 | return ans; 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /000-099/007-Reverse-Integer.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(logn) 2 | // Space complexity: O(1) 3 | 4 | class Solution { 5 | public: 6 | int reverse(int x) { 7 | int rev = 0; 8 | while (x != 0) { 9 | int pop = x % 10; 10 | x /= 10; 11 | if (rev > numeric_limits::max() / 10 || 12 | (rev == numeric_limits::max() / 10 && pop > 7)) return 0; 13 | if (rev < numeric_limits::min() / 10 || 14 | (rev == numeric_limits::min() / 10 && pop < -8)) return 0; 15 | rev = rev * 10 + pop; 16 | } 17 | return rev; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /000-099/009-Palindrome-Number.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(logn) 2 | // Space complexity: O(1) 3 | 4 | class Solution { 5 | public: 6 | bool isPalindrome(int x) { 7 | // if x is neg or x ends with 0 but is not 0, it can't be palindrome 8 | if (x < 0 || (x % 10 == 0 && x != 0)) { 9 | return false; 10 | } 11 | 12 | int rev = 0; 13 | while(x > rev) { // terminates when rev has more digits than x 14 | rev = rev * 10 + x % 10; 15 | x /= 10; 16 | } 17 | 18 | return x == rev // if the palindrome number has even number of digits 19 | || x == rev / 10; // if the palindrome number has odd number of digits 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /000-099/011-Container-With-Most-Water.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public int maxArea(int[] height) { 3 | if (height == null || height.length < 2) 4 | return -1; 5 | 6 | int left = 0, right = height.length - 1; 7 | int maxArea = (right - left) * Math.min(height[left], height[right]); 8 | while (left < right) { 9 | maxArea = Math.max(maxArea, (right - left) * Math.min(height[left], height[right])); 10 | if (height[left] < height[right]) { 11 | left++; 12 | } else { 13 | right--; 14 | } 15 | } 16 | 17 | return maxArea; 18 | } 19 | } -------------------------------------------------------------------------------- /000-099/011-Container-With-Most-Water.md: -------------------------------------------------------------------------------- 1 | # 011-Container With Most Water 2 | 3 | ## Approach: Two Pointers 4 | 5 | The volume of the container is determined by the shorter bar. Use two pointers to get two bars. After we evaluate the area of a specific container, we should move the shorter bar, because if we change the higher bar, the volume will either decrease or remain the same as we are moving inward. However, if we move the shorter bar, we might get a volume that is larger than the previous one. 6 | 7 | Time complexity: O(n). 8 | 9 | Space complexity: O(1) extra space. 10 | 11 | ```c++ 12 | class Solution { 13 | public: 14 | int maxArea(vector& height) { 15 | int left = 0; 16 | int right = height.size() - 1; 17 | 18 | int max_area = 0; 19 | while (left < right) { 20 | int left_height = height[left]; 21 | int right_height = height[right]; 22 | 23 | int area = min(left_height, right_height) * (right - left); 24 | max_area = max(area, max_area); 25 | 26 | if (left_height >= right_height) { 27 | --right; 28 | } else { 29 | ++left; 30 | } 31 | } 32 | 33 | return max_area; 34 | } 35 | }; 36 | ``` 37 | -------------------------------------------------------------------------------- /000-099/013-Roman-to-Integer.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public int romanToInt(String s) { 3 | int total = 0; 4 | int num = 0; 5 | int prev = 0; 6 | 7 | for (int i = 0; i < s.length(); i++) { 8 | switch (s.charAt(i)) { 9 | case 'I': 10 | num = 1; 11 | break; 12 | case 'V': 13 | num = 5; 14 | break; 15 | case 'X': 16 | num = 10; 17 | break; 18 | case 'L': 19 | num = 50; 20 | break; 21 | case 'C': 22 | num = 100; 23 | break; 24 | case 'D': 25 | num = 500; 26 | break; 27 | case 'M': 28 | num = 1000; 29 | break; 30 | default: 31 | throw new IllegalArgumentException("Illegal Input"); 32 | } 33 | total += num; 34 | 35 | // subtraction 36 | if (num > prev) { 37 | total -= 2 * prev; 38 | } 39 | 40 | prev = num; 41 | } 42 | 43 | return total; 44 | } 45 | } -------------------------------------------------------------------------------- /000-099/014-Longest-Common-Prefix.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n) 2 | // Space complexity: O(1) 3 | 4 | class Solution { 5 | public: 6 | string longestCommonPrefix(vector& strs) { 7 | if (strs.empty() || strs[0].empty()) return ""; 8 | 9 | for (auto i = 0; i < strs[0].size(); ++i) { 10 | char c = strs[0][i]; 11 | for (auto j = 1; j < strs.size(); ++j) { 12 | if (i == strs[j].size() || strs[j][i] != c) 13 | return strs[0].substr(0, i); 14 | } 15 | } 16 | 17 | return strs[0]; // when strs.size() == 1 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /000-099/015-3Sum.cpp: -------------------------------------------------------------------------------- 1 | // Convert to 2Sum case 2 | // Notice the handling of duplicated elements 3 | 4 | // Time complexity: O(n^2). 5 | // Space complexity: O(1). 6 | 7 | class Solution { 8 | public: 9 | vector> threeSum(vector& nums) { 10 | const int N = nums.size(); 11 | if (N < 3) return {}; 12 | 13 | vector> ans; 14 | sort(nums.begin(), nums.end()); 15 | 16 | int i = 0; 17 | while (i < N - 2) { 18 | int num_1 = nums[i]; 19 | 20 | int left = i + 1; 21 | int right = nums.size() - 1; 22 | while (left < right) { 23 | int num_2 = nums[left]; 24 | int num_3 = nums[right]; 25 | int sum = num_1 + num_2 + num_3; 26 | if (sum == 0) { 27 | ans.push_back({num_1, num_2, num_3}); 28 | while (left < right && nums[left] == num_2) ++left; 29 | while (left < right && nums[right] == num_3) --right; 30 | } else if (sum < 0) { 31 | while (left < right && nums[left] == num_2) ++left; 32 | } else { 33 | while (left < right && nums[right] == num_3) --right; 34 | } 35 | } 36 | 37 | while (i < N - 2 && nums[i] == num_1) ++i; 38 | } 39 | 40 | return ans; 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /000-099/016-3Sum-Closest.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n^2). 2 | // Space complexity: O(1). 3 | 4 | class Solution { 5 | public: 6 | int threeSumClosest(vector& nums, int target) { 7 | const int N = nums.size(); 8 | assert(N >= 3); 9 | 10 | sort(nums.begin(), nums.end()); 11 | int closest_diff = numeric_limits::max(); 12 | 13 | for (auto i = 0; i < N - 2; ++i) { 14 | int left = i + 1; 15 | int right = N - 1; 16 | while (left < right) { 17 | int sum = nums[i] + nums[left] + nums[right]; 18 | int diff = sum - target; 19 | 20 | if (abs(diff) < abs(closest_diff)) { 21 | closest_diff = diff; 22 | } 23 | 24 | if (diff == 0) { 25 | return target; 26 | } else if (diff < 0) { 27 | ++left; 28 | } else { 29 | --right; 30 | } 31 | } 32 | } 33 | 34 | return target + closest_diff; 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /000-099/017-Letter-Combinations-of-a-Phone-Number.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | using size_type = string::size_type; 4 | 5 | vector letterCombinations(string digits) { 6 | if (digits.size() != 0) 7 | backtrack("", digits, 0); 8 | return output; 9 | } 10 | private: 11 | vector output; 12 | vector phone = {"abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}; 13 | 14 | void backtrack(const string& combination, const string& digits, size_type i) { 15 | if (i == digits.size()) { 16 | output.push_back(combination); 17 | } else { 18 | char digit = digits[i]; 19 | string letters = phone[size_type{digit - '2'}]; 20 | for (auto letter : letters) { 21 | backtrack(combination + letter, digits, i + 1); 22 | } 23 | } 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /000-099/019-Remove-Nth-Node-From-End-of-List.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n) 2 | // Space complexity: O(1) 3 | 4 | /** 5 | * Definition for singly-linked list. 6 | * struct ListNode { 7 | * int val; 8 | * ListNode *next; 9 | * ListNode() : val(0), next(nullptr) {} 10 | * ListNode(int x) : val(x), next(nullptr) {} 11 | * ListNode(int x, ListNode *next) : val(x), next(next) {} 12 | * }; 13 | */ 14 | class Solution { 15 | public: 16 | ListNode* removeNthFromEnd(ListNode* head, int n) { 17 | auto dummy_head = ListNode(-1, head); 18 | auto slow = &dummy_head; 19 | auto fast = head; 20 | for (int i = 0; i < n; i++) { 21 | fast = fast->next; 22 | } 23 | 24 | while (fast) { 25 | fast = fast->next; 26 | slow = slow->next; 27 | } 28 | 29 | auto to_delete = slow->next; 30 | slow->next = to_delete->next; 31 | delete to_delete; 32 | 33 | return dummy_head.next; 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /000-099/019-Remove-Nth-Node-From-End-of-List.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * public class ListNode { 4 | * int val; 5 | * ListNode next; 6 | * ListNode(int x) { val = x; } 7 | * } 8 | */ 9 | class Solution { 10 | public ListNode removeNthFromEnd(ListNode head, int n) { 11 | ListNode dummyHead = new ListNode(-1); 12 | dummyHead.next = head; 13 | ListNode current = dummyHead; 14 | for (int i = -1; i < n; i++) { 15 | current = current.next; 16 | } 17 | ListNode nPlusOneDelayed = dummyHead; 18 | 19 | while (current != null) { 20 | current = current.next; 21 | nPlusOneDelayed = nPlusOneDelayed.next; 22 | } 23 | nPlusOneDelayed.next = nPlusOneDelayed.next.next; 24 | 25 | return dummyHead.next; 26 | } 27 | } -------------------------------------------------------------------------------- /000-099/020-Valid-Parentheses.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public boolean isValid(String s) { 3 | if (s == null) 4 | return true; 5 | 6 | Stack stack = new Stack(); 7 | for (int i = 0; i < s.length(); i++) { 8 | Character ch = s.charAt(i); 9 | switch (ch) { 10 | case '(': case '{': case '[': 11 | stack.push(ch); 12 | break; 13 | case ')': 14 | if (stack.empty() || (stack.pop() != '(')) { 15 | return false; 16 | } 17 | break; 18 | case '}': 19 | if (stack.empty() || (stack.pop() != '{')) { 20 | return false; 21 | } 22 | break; 23 | case ']': 24 | if (stack.empty() || (stack.pop() != '[')) { 25 | return false; 26 | } 27 | break; 28 | } 29 | } 30 | 31 | return stack.empty(); 32 | } 33 | } -------------------------------------------------------------------------------- /000-099/021-Merge-Two-Sorted-List.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(l1.length + l2.length). 2 | // Space complexity: O(1) auxiliary space. 3 | 4 | /* 5 | * struct ListNode { 6 | * int val; 7 | * ListNode *next; 8 | * ListNode() : val(0), next(nullptr) {} 9 | * ListNode(int x) : val(x), next(nullptr) {} 10 | * ListNode(int x, ListNode *next) : val(x), next(next) {} 11 | * }; 12 | */ 13 | class Solution { 14 | public: 15 | ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { 16 | ListNode dummy{}; 17 | ListNode* prev = &dummy; 18 | ListNode* curr = nullptr; 19 | while (l1 && l2) { 20 | if (l1->val < l2->val) { 21 | curr = new ListNode{l1->val}; 22 | l1 = l1->next; 23 | } else { 24 | curr = new ListNode{l2->val}; 25 | l2 = l2->next; 26 | } 27 | prev->next = curr; 28 | prev = curr; 29 | } 30 | while (l1) { 31 | curr = new ListNode{l1->val}; 32 | l1 = l1->next; 33 | prev->next = curr; 34 | prev = curr; 35 | } 36 | while (l2) { 37 | curr = new ListNode{l2->val}; 38 | l2 = l2->next; 39 | prev->next = curr; 40 | prev = curr; 41 | } 42 | 43 | return dummy.next; 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /000-099/021-Merge-Two-Sorted-Lists.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * public class ListNode { 4 | * int val; 5 | * ListNode next; 6 | * ListNode(int x) { val = x; } 7 | * } 8 | */ 9 | class Solution { 10 | public ListNode mergeTwoLists(ListNode l1, ListNode l2) { 11 | ListNode helpNode = new ListNode(-1); 12 | ListNode headNode = helpNode; 13 | 14 | while (l1 != null && l2 != null) { 15 | if (l1.val <= l2.val) { 16 | helpNode.next = l1; 17 | l1 = l1.next; 18 | } else { 19 | helpNode.next = l2; 20 | l2 = l2.next; 21 | } 22 | helpNode = helpNode.next; 23 | } 24 | 25 | if (l1 == null) 26 | helpNode.next = l2; 27 | else 28 | helpNode.next = l1; 29 | 30 | return headNode.next; 31 | } 32 | } -------------------------------------------------------------------------------- /000-099/022-Generate-Parentheses.cpp: -------------------------------------------------------------------------------- 1 | """ 2 | We can start an opening bracket if we still have one (of n) left to place. 3 | We can start a closing bracket if it would not exceed the number of opening brackets. 4 | """ 5 | 6 | class Solution { 7 | public: 8 | vector generateParenthesis(int n) { 9 | vector ans; 10 | backtrack(ans, "", 0, 0, n); 11 | return ans; 12 | } 13 | private: 14 | void backtrack(vector& ans, string curr, int open, int close, int n) { 15 | if (curr.size() == n * 2) { 16 | ans.push_back(curr); 17 | return; 18 | } 19 | 20 | if (open < n) 21 | backtrack(ans, curr + "(", open+1, close, n); 22 | if (close < open) 23 | backtrack(ans, curr + ")", open, close+1, n); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /000-099/023-Merge-k-Sorted-Lists.cpp: -------------------------------------------------------------------------------- 1 | // Compare every k nodes (head of every linked list) and get the node with the smallest value using heap. 2 | // Extend the final sorted linked list with the selected nodes. 3 | 4 | // Time complexity: O(nlogk). 5 | // Space complexity: O(k) for in-place solution here. 6 | 7 | /** 8 | * Definition for singly-linked list. 9 | * struct ListNode { 10 | * int val; 11 | * ListNode *next; 12 | * ListNode() : val(0), next(nullptr) {} 13 | * ListNode(int x) : val(x), next(nullptr) {} 14 | * ListNode(int x, ListNode *next) : val(x), next(next) {} 15 | * }; 16 | */ 17 | class Solution { 18 | public: 19 | ListNode* mergeKLists(vector& lists) { 20 | auto cmp = [](ListNode* a, ListNode* b) { return a->val > b->val; }; 21 | priority_queue, decltype(cmp)> heap(cmp); 22 | for (auto node : lists) { 23 | if (node) { 24 | heap.push(node); 25 | } 26 | } 27 | 28 | auto dummy_head = ListNode{-1}; 29 | auto curr = &dummy_head; 30 | while (!heap.empty()) { 31 | auto node = heap.top(); 32 | heap.pop(); 33 | curr->next = node; 34 | if (node->next) { 35 | heap.push(node->next); 36 | } 37 | curr = curr->next; 38 | } 39 | 40 | return dummy_head.next; 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /000-099/024-Swap-Nodes-in-Pairs.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * public class ListNode { 4 | * int val; 5 | * ListNode next; 6 | * ListNode(int x) { val = x; } 7 | * } 8 | */ 9 | class Solution { 10 | public ListNode swapPairs(ListNode head) { 11 | ListNode dummy = new ListNode(-1); 12 | dummy.next = head; 13 | ListNode prev = dummy; 14 | 15 | while (head != null && head.next != null) { 16 | ListNode second = head.next; 17 | 18 | // swap head and second 19 | prev.next = second; 20 | head.next = second.next; 21 | second.next = head; 22 | 23 | // iterate 24 | prev = head; 25 | head = head.next; 26 | } 27 | 28 | return dummy.next; 29 | } 30 | } -------------------------------------------------------------------------------- /000-099/026-Remove-Duplicates-from-Sorted-Array.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(1) extra memory. 3 | 4 | class Solution { 5 | public: 6 | int removeDuplicates(vector& nums) { 7 | int i = 0; 8 | for (auto num : nums) { 9 | if (i < 1 || nums[i - 1] != num) { 10 | nums[i++] = num; 11 | } 12 | } 13 | return i; 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /000-099/026-Remove-Duplicates-from-Sorted-Array.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public int removeDuplicates(int[] nums) { 3 | if (nums == null) 4 | throw new NullPointerException("Array is null!"); 5 | 6 | int i = 0; 7 | for (int j = 1; j < nums.length; j++) { 8 | if (nums[j] != nums[i]) { 9 | i++; 10 | nums[i] = nums[j]; 11 | } 12 | } 13 | return i + 1; 14 | } 15 | } -------------------------------------------------------------------------------- /000-099/027-Remove-Element.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public int removeElement(int[] nums, int val) { 3 | if (nums == null) 4 | throw new NullPointerException("Array is null!"); 5 | 6 | int count = 0; 7 | for (int i = 0; i < nums.length; i++) { 8 | if(nums[i] != val) { 9 | nums[count] = nums[i]; 10 | count++; 11 | } 12 | } 13 | return count; 14 | } 15 | } -------------------------------------------------------------------------------- /000-099/028-Implement-strStr().java: -------------------------------------------------------------------------------- 1 | // 1. You can directly use haystack.indexOf(needle) 2 | // 2. Converting to char array improves performance 3 | 4 | class Solution { 5 | public int strStr(String haystack, String needle) { 6 | char[] haystack_arr = haystack.toCharArray(); 7 | char[] needle_arr = needle.toCharArray(); 8 | 9 | for (int i = 0; ; i++) { 10 | for (int j = 0; ; j++) { 11 | if (j == needle_arr.length) return i; 12 | if (i + j >= haystack_arr.length) return -1; 13 | if (needle_arr[j] != haystack_arr[i + j]) break; 14 | } 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /000-099/034-Find-First-and-Last-Position-of-Element-in-Sorted-Array.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(logn). 2 | // Space complexity: O(1). 3 | class Solution { 4 | public: 5 | vector searchRange(vector& nums, int target) { 6 | int first = -1; 7 | int last = -1; 8 | 9 | int lo = 0; 10 | int hi = nums.size() - 1; 11 | while (lo <= hi) { 12 | int mid = lo + (hi - lo) / 2; 13 | if (nums[mid] == target) { 14 | first = mid; 15 | hi = mid - 1; 16 | } else if (nums[mid] < target) { 17 | lo = mid + 1; 18 | } else { 19 | hi = mid - 1; 20 | } 21 | } 22 | if (first == -1) { 23 | return {-1, -1}; 24 | } 25 | 26 | lo = first; 27 | hi = nums.size() - 1; 28 | while (lo <= hi) { 29 | int mid = lo + (hi - lo) / 2; 30 | if (nums[mid] == target) { 31 | last = mid; 32 | lo = mid + 1; 33 | } else if (nums[mid] < target) { 34 | lo = mid + 1; 35 | } else { 36 | hi = mid - 1; 37 | } 38 | } 39 | return {first, last}; 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /000-099/034-Find-First-and-Last-Position-of-Element-in-Sorted-Array.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public int[] searchRange(int[] nums, int target) { 3 | int first = 0; 4 | int last = 0; 5 | int mid = 0; 6 | int n = nums.length; 7 | 8 | int left = 0; 9 | int right = n - 1; 10 | while (left <= right) { 11 | mid = left + (right - left) / 2; 12 | if (nums[mid] >= target) 13 | right = mid - 1; 14 | else 15 | left = mid + 1; 16 | } 17 | if (right + 1 < n) 18 | first = nums[right + 1] == target ? right + 1 : -1; 19 | else 20 | first = -1; 21 | 22 | left = 0; 23 | right = n - 1; 24 | while (left <= right) { 25 | mid = left + (right - left) / 2; 26 | if (nums[mid] <= target) 27 | left = mid + 1; 28 | else 29 | right = mid - 1; 30 | } 31 | if (left > 0) 32 | last = nums[left - 1] == target ? left - 1 : -1; 33 | else 34 | last = -1; 35 | 36 | return new int[]{first, last}; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /000-099/035-Search-Insert-Position.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(logn). 2 | // Space complexity: O(1) 3 | class Solution { 4 | public: 5 | int searchInsert(vector& nums, int target) { 6 | int idx = -1; 7 | 8 | int lo = 0; 9 | int hi = nums.size() - 1; 10 | while (lo <= hi) { 11 | int mid = lo + (hi - lo) / 2; 12 | if (nums[mid] == target) { 13 | return mid; 14 | } else if (nums[mid] < target) { 15 | idx = mid; 16 | lo = mid + 1; 17 | } else { 18 | hi = mid - 1; 19 | } 20 | } 21 | 22 | return idx + 1; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /000-099/035-Search-Insert-Position.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public int searchInsert(int[] nums, int target) { 3 | int mid = 0; 4 | int left = 0; 5 | int right = nums.length - 1; 6 | 7 | while (left <= right) { 8 | mid = (left + right) / 2; 9 | if (nums[mid] == target) 10 | return mid; 11 | else if (nums[mid] > target) 12 | right = mid - 1; 13 | else 14 | left = mid + 1; 15 | } 16 | 17 | if (nums[mid] > target) 18 | return mid; 19 | else 20 | return mid + 1; 21 | } 22 | } -------------------------------------------------------------------------------- /000-099/038-Count-and-Say.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n * 2^n) for each digit can be expanded to at most two digits in the next count_and_say seq 2 | // Space complexity: O(2^n) 3 | 4 | class Solution { 5 | public: 6 | string countAndSay(int n) { 7 | assert(n >= 1 && n <= 30); 8 | 9 | string str = "1"; 10 | for (auto i = 1; i < n; ++i) { 11 | string tmp; 12 | int j = 0; 13 | while (j < str.size()) { 14 | int cnt = 1; 15 | while (j + 1 < str.size() && str[j] == str[j + 1]) { 16 | ++cnt; 17 | ++j; 18 | } 19 | tmp += to_string(cnt) + str[j]; 20 | ++j; 21 | } 22 | str = move(tmp); 23 | } 24 | 25 | return str; 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /000-099/043-Multiply-Strings.cpp: -------------------------------------------------------------------------------- 1 | // Use normal multiplication algorithm. 2 | // Time complexity: O(n * m). 3 | // Space complexity: O(n + m). 4 | 5 | class Solution { 6 | public: 7 | string multiply(string num1, string num2) { 8 | string mul(num1.size() + num2.size(), '0'); 9 | 10 | for (int i = num1.size() - 1; i >= 0; i--) { 11 | int carry = 0; 12 | for (int j = num2.size() - 1; j >= 0; j--) { 13 | int tmp = (mul[i + j + 1] - '0') + (num1[i] - '0') * (num2[j] - '0') + carry; 14 | mul[i + j + 1] = tmp % 10 + '0'; 15 | carry = tmp / 10; 16 | } 17 | mul[i] += carry; 18 | } 19 | 20 | size_t startpos = mul.find_first_not_of("0"); 21 | if (startpos != string::npos) { 22 | return mul.substr(startpos); 23 | } 24 | return "0"; 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /000-099/046-Permutations.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity : O(Sum_{k = 1 to N} P(N, k)}) 2 | // Space complexity: O(N!) 3 | 4 | class Solution { 5 | public: 6 | vector> permute(vector& num) { 7 | vector> result; 8 | permuteRec(num, 0, result); 9 | return result; 10 | } 11 | private: 12 | // permute num[begin..end] 13 | // invariant: num[0..begin-1] is fixed 14 | void permuteRec(vector& num, int begin, vector>& result) { 15 | if (begin == num.size()) { 16 | result.push_back(num); 17 | return; 18 | } 19 | 20 | for (int i = begin; i < num.size(); i++) { 21 | swap(num[begin], num[i]); 22 | permuteRec(num, begin + 1, result); 23 | swap(num[begin], num[i]); 24 | } 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /000-099/047-Permutations-II.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity : O(Sum_{k = 1 to N} P(N, k)}) 2 | // Space complexity: O(N!) 3 | 4 | class Solution { 5 | public: 6 | vector > permuteUnique(vector& num) { 7 | vector> result; 8 | permuteRec(num, 0, result); 9 | return result; 10 | } 11 | private: 12 | // permute num[begin..end] 13 | // invariant: num[0..begin-1] is fixed 14 | void permuteRec(vector& num, int begin, vector>& result) { 15 | if (begin == num.size()) { 16 | result.push_back(num); 17 | return; 18 | } 19 | 20 | unordered_set s; 21 | for (int i = begin; i < num.size(); i++) { 22 | // if already fixed this number, skip 23 | if (s.find(num[i]) != s.end()) 24 | continue; 25 | s.insert(num[i]); 26 | swap(num[begin], num[i]); 27 | permuteRec(num, begin + 1, result); 28 | swap(num[begin], num[i]); 29 | } 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /000-099/048-Rotate-Image.cpp: -------------------------------------------------------------------------------- 1 | // Transpose and Reverse 2 | // Time complexity: O(n^2). 3 | // Space complexity: O(1) in place. 4 | 5 | class Solution { 6 | public: 7 | void rotate(vector>& matrix) { 8 | const int n = matrix.size(); 9 | 10 | // transpose 11 | for (int i = 0; i < n; i++) { 12 | for (int j = i + 1; j < n; j++) { 13 | swap(matrix[i][j], matrix[j][i]); 14 | } 15 | } 16 | 17 | // reserve 18 | for (int i = 0; i < n; i++) { 19 | for (int j = 0; j < n / 2; j++) { 20 | swap(matrix[i][j], matrix[i][n - 1 - j]); 21 | } 22 | } 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /000-099/048-Rotate-Image.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public void rotate(int[][] matrix) { 3 | if (matrix == null) 4 | return; 5 | 6 | int n = matrix.length; 7 | 8 | for (int i = 0; i < n / 2; i++) { // ith ring 9 | for (int j = 0; j < n - 1 - 2 * i; j++) { // jth element on the ring 10 | 11 | // save top 12 | int tmp = matrix[i][i + j]; 13 | 14 | // left to top 15 | matrix[i][i + j] = matrix[n - 1 - i - j][i]; 16 | 17 | // bottom to left 18 | matrix[n - 1 - i - j][i] = matrix[n - 1 - i][n - 1 - i - j]; 19 | 20 | // right to bottom 21 | matrix[n - 1 - i][n - 1 - i - j] = matrix[i + j][n - 1 - i]; 22 | 23 | // top to right 24 | matrix[i + j][n - 1 - i] = tmp; 25 | 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /000-099/049-Group-Anagrams.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n * k log(k)). 2 | // n is the length of strs, and k is the maximum length of a string in strs 3 | // Space complexity: O(n k). 4 | 5 | // Intuition: 6 | // Two strings are anagrams if and only if their sorted strings are equal. 7 | // could use counts as well. 8 | 9 | class Solution { 10 | public: 11 | vector> groupAnagrams(vector& strs) { 12 | vector> res; 13 | 14 | unordered_map> group; 15 | for (string& s : strs) { 16 | string key = s; 17 | sort(key.begin(), key.end()); 18 | group[key].push_back(s); 19 | } 20 | 21 | for (auto& elem : group) { 22 | res.push_back(elem.second); 23 | } 24 | return res; 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /000-099/051-N-Queens.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n!) 2 | // Space complexity: O(n) 3 | 4 | class Solution { 5 | public: 6 | vector> solveNQueens(int n) { 7 | vector> result; 8 | vector config(n, 0); 9 | placeQueen(result, config, 0, n); 10 | return result; 11 | } 12 | private: 13 | void placeQueen(vector>& result, vector& config, int r, int n) { 14 | if (r == n) { 15 | vector config_str; 16 | for (auto queen_col : config) { 17 | string str(n, '.'); 18 | str[queen_col] = 'Q'; 19 | config_str.push_back(str); 20 | } 21 | result.push_back(config_str); 22 | } else { 23 | for (auto j = 0; j < n; ++j) { 24 | bool legal = true; 25 | for (auto i = 0; i < r; ++i) { 26 | if (config[i] == j || 27 | config[i] + (r - i) == j || 28 | config[i] - (r - i) == j) { 29 | legal = false; 30 | break; 31 | } 32 | } 33 | if (legal) { 34 | config[r] = j; 35 | placeQueen(result, config, r + 1, n); 36 | } 37 | } 38 | } 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /000-099/052-N-Queens-II.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n!) 2 | // Space complexity: O(n) 3 | 4 | class Solution { 5 | public: 6 | int totalNQueens(int n) { 7 | vector config(n, 0); 8 | return placeQueen(config, 0, n); 9 | } 10 | private: 11 | int placeQueen(vector& config, int r, int n) { 12 | int result = 0; 13 | 14 | if (r == n) { 15 | result = 1; 16 | } else { 17 | for (auto j = 0; j < n; ++j) { 18 | bool legal = true; 19 | for (auto i = 0; i < r; ++i) { 20 | if (config[i] == j || 21 | config[i] + (r - i) == j || 22 | config[i] - (r - i) == j) { 23 | legal = false; 24 | break; 25 | } 26 | } 27 | if (legal) { 28 | config[r] = j; 29 | result += placeQueen(config, r + 1, n); 30 | } 31 | } 32 | } 33 | 34 | return result; 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /000-099/053-Maximum-Subarray.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public int maxSubArray(int[] nums) { 3 | if (nums == null) 4 | return -1; 5 | 6 | int maxSum = Integer.MIN_VALUE, currentSum = Integer.MIN_VALUE; 7 | for (int num: nums) { 8 | currentSum = (currentSum < 0) ? num : currentSum + num; 9 | maxSum = (maxSum < currentSum) ? currentSum : maxSum; 10 | } 11 | return maxSum; 12 | } 13 | } -------------------------------------------------------------------------------- /000-099/054-Spiral-Matrix.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public List spiralOrder(int[][] matrix) { 3 | List lst = new ArrayList(); 4 | int m = matrix.length; 5 | int n = 0; 6 | if (m > 0) 7 | n = matrix[0].length; 8 | if (m * n == 0) // empty matrix 9 | return lst; 10 | 11 | int i = 0; 12 | int j = -1; 13 | int step = 1; 14 | 15 | while (m > 0 && n > 0) { 16 | for (int k = 0; k < n; k++) { 17 | j += step; 18 | lst.add(matrix[i][j]); 19 | } 20 | for (int k = 1; k < m; k++) { 21 | i += step; 22 | lst.add(matrix[i][j]); 23 | } 24 | n--; 25 | m--; 26 | step *= -1; 27 | } 28 | 29 | return lst; 30 | } 31 | } -------------------------------------------------------------------------------- /000-099/055-Jump-Game.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Key observation: 3 | * We won't get stuck if we do not encounter any zero along the way. 4 | * Idea: 5 | * Based on the key observation, we just need to check whether we can jump 6 | * over the zeroes along the way. 7 | * Solution: 8 | * Iterate through the array, maintain a variable that records the farthest 9 | * position we can get to so far. Whenever we encounter a zero, check if 10 | * the farthest reacheable position so far is beyond this zero. If yes, 11 | * continue iterating; if no, we jump out of the loop. Finally, check 12 | * whether the last position is within our reachable range. 13 | */ 14 | class Solution { 15 | public boolean canJump(int[] nums) { 16 | int max_reachable = 0; 17 | for (int i = 0; i < nums.length; i++) { 18 | if (nums[i] == 0 && max_reachable == i) 19 | break; 20 | max_reachable = Math.max(i + nums[i], max_reachable); 21 | } 22 | return (max_reachable >= nums.length - 1); 23 | } 24 | } -------------------------------------------------------------------------------- /000-099/056-Merge-Intervals.md: -------------------------------------------------------------------------------- 1 | # 056-Merge Intervals 2 | 3 | [Problem](https://leetcode.com/problems/merge-intervals/) 4 | 5 | ## Approach 1: Sorting 6 | 7 | Intution: If we sort the intervals by their start value, then each set of intervals that can be merged will appear as a contiguous "run" in the sorted list. 8 | 9 | Time complexity: O(nlogn). 10 | 11 | Space complexity: O(1) (in-place) or O(n) (modification prohibited). 12 | 13 | ```c++ 14 | class Solution { 15 | public: 16 | vector> merge(vector>& intervals) { 17 | if (intervals.empty()) return intervals; 18 | 19 | sort(intervals.begin(), intervals.end(), [](vector x, vector y) 20 | { return x.front() < y.front(); }); 21 | 22 | vector> merged{intervals.front()}; 23 | for (const auto& interval : intervals) { 24 | if (merged.back().back() < interval.front()) { 25 | merged.push_back(interval); 26 | } else { 27 | merged.back().back() = max(merged.back().back(), interval.back()); 28 | } 29 | } 30 | 31 | return merged; 32 | } 33 | }; 34 | ``` 35 | -------------------------------------------------------------------------------- /000-099/058-Length-of-Last-Word.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public int lengthOfLastWord(String s) { 3 | s = s.trim(); 4 | if (s.isEmpty()) return 0; 5 | for (int i = s.length() - 1; i >= 0; i--) { 6 | if (s.charAt(i) == ' ') return s.length() - i - 1; 7 | } 8 | return s.length(); 9 | } 10 | } -------------------------------------------------------------------------------- /000-099/059-Sprial-Matrix-II.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public int[][] generateMatrix(int n) { 3 | assert(n > 0); 4 | int[][] matrix = new int[n][n]; 5 | 6 | int num = 1; 7 | int i = 0; 8 | int j = -1; 9 | int step = 1; 10 | for (int level = n; level > 0; level--) { 11 | for (int k = 0; k < level; k++) { 12 | j += step; 13 | matrix[i][j] = num++; 14 | } 15 | for (int k = 1; k < level; k++) { 16 | i += step; 17 | matrix[i][j] = num++; 18 | } 19 | step *= -1; 20 | } 21 | 22 | return matrix; 23 | } 24 | } -------------------------------------------------------------------------------- /000-099/061-Rotate-List.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * public class ListNode { 4 | * int val; 5 | * ListNode next; 6 | * ListNode(int x) { val = x; } 7 | * } 8 | */ 9 | class Solution { 10 | public ListNode rotateRight(ListNode head, int k) { 11 | ListNode previous = null; 12 | ListNode current = head; 13 | ListNode last; 14 | 15 | int length = 0; 16 | while (current != null) { 17 | previous = current; 18 | current = current.next; 19 | length++; 20 | } 21 | last = previous; 22 | if (length == 0 || k % length == 0) { 23 | return head; 24 | } 25 | 26 | current = head; 27 | for (int i = 0; i < length - k % length; i++) { 28 | previous = current; 29 | current = current.next; 30 | } 31 | last.next = head; 32 | previous.next = null; 33 | 34 | return current; 35 | } 36 | } -------------------------------------------------------------------------------- /000-099/062-Unique-Paths.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public int uniquePaths(int m, int n) { 3 | int[][] paths = new int[m][n]; 4 | for (int i = 0; i < m; i++) { 5 | paths[i][0] = 1; 6 | } 7 | for (int j = 0; j < n; j++) { 8 | paths[0][j] = 1; 9 | } 10 | for (int i = 1; i < m; i++) { 11 | for (int j = 1; j < n; j++) { 12 | paths[i][j] = paths[i - 1][j] + paths[i][j - 1]; 13 | } 14 | } 15 | return paths[m - 1][n - 1]; 16 | } 17 | } -------------------------------------------------------------------------------- /000-099/063-Unique-Paths-II.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public int uniquePathsWithObstacles(int[][] obstacleGrid) { 3 | if (obstacleGrid == null) 4 | return -1; 5 | 6 | int m = obstacleGrid.length; 7 | int n = obstacleGrid[0].length; 8 | int[][] num_paths_mem = new int[m][n]; 9 | 10 | for (int i = 0, num_paths = 1; i < m; i++) { 11 | if (obstacleGrid[i][0] == 1) 12 | num_paths = 0; 13 | num_paths_mem[i][0] = num_paths; 14 | } 15 | for (int j = 0, num_paths = 1; j < n; j++) { 16 | if (obstacleGrid[0][j] == 1) 17 | num_paths = 0; 18 | num_paths_mem[0][j] = num_paths; 19 | } 20 | for (int i = 1; i < m; i++) { 21 | for (int j = 1; j < n; j++) { 22 | if (obstacleGrid[i][j] == 0) 23 | num_paths_mem[i][j] = num_paths_mem[i - 1][j] + 24 | num_paths_mem[i][j - 1]; 25 | else 26 | num_paths_mem[i][j] = 0; 27 | } 28 | } 29 | 30 | return num_paths_mem[m - 1][n - 1]; 31 | } 32 | } -------------------------------------------------------------------------------- /000-099/064-Minimum-Path-Sum.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public int minPathSum(int[][] grid) { 3 | if (grid == null || grid.length == 0 || grid[0].length == 0) 4 | return -1; 5 | 6 | int m = grid.length; 7 | int n = grid[0].length; 8 | int[][] grid_mem = new int[m][n]; 9 | grid_mem[0][0] = grid[0][0]; 10 | for (int i = 1; i < m; i++) { 11 | grid_mem[i][0] = grid_mem[i - 1][0] + grid[i][0]; 12 | } 13 | for (int j = 1; j < n; j++) { 14 | grid_mem[0][j] = grid_mem[0][j - 1] + grid[0][j]; 15 | } 16 | for (int i = 1; i < m; i++) { 17 | for (int j = 1; j < n; j++) { 18 | if (grid_mem[i][j - 1] < grid_mem[i - 1][j]) 19 | grid_mem[i][j] = grid_mem[i][j - 1] + grid[i][j]; 20 | else 21 | grid_mem[i][j] = grid_mem[i - 1][j] + grid[i][j]; 22 | } 23 | } 24 | 25 | return grid_mem[m - 1][n - 1]; 26 | } 27 | } -------------------------------------------------------------------------------- /000-099/066-Plus-One.java: -------------------------------------------------------------------------------- 1 | // My original solution 2 | class Solution { 3 | public int[] plusOne(int[] digits) { 4 | int n = digits.length; 5 | int tmp = digits[n - 1] + 1; 6 | int carry = tmp / 10; 7 | digits[n - 1] = tmp % 10; 8 | for (int i = n - 2; i > -1; i--) { 9 | tmp = digits[i] + carry; 10 | carry = tmp / 10; 11 | digits[i] = tmp % 10; 12 | } 13 | 14 | if (carry == 0) { 15 | return digits; 16 | } else { 17 | int[] result = new int[n + 1]; 18 | result[0] = 1; 19 | return result; 20 | } 21 | } 22 | } 23 | 24 | // A better solution without explicit carry 25 | class Solution { 26 | public int[] plusOne(int[] digits) { 27 | int n = digits.length; 28 | for(int i= n - 1; i > -1; i--) { 29 | if (digits[i] < 9) { 30 | digits[i]++; 31 | return digits; 32 | } 33 | digits[i] = 0; 34 | } 35 | 36 | int[] newNumber = new int[n + 1]; 37 | newNumber[0] = 1; 38 | 39 | return newNumber; 40 | } 41 | } -------------------------------------------------------------------------------- /000-099/067-Add-Binary.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(a.length + b.length). 2 | // Space complexity: O(1) auxiliary space. 3 | 4 | class Solution { 5 | public: 6 | string addBinary(string a, string b) { 7 | string res = ""; 8 | int m = a.size() - 1; 9 | int n = b.size() - 1; 10 | int carry = 0;; 11 | 12 | while (m >= 0 || n >= 0) { 13 | int p = (m >= 0) ? a[m--] - '0' : 0; 14 | int q = (n >= 0) ? b[n--] - '0' : 0; 15 | int sum = p + q + carry; 16 | res = to_string(sum % 2) + res; 17 | carry = sum / 2; 18 | } 19 | return (carry == 1) ? "1" + res : res; 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /000-099/069-Sqrt(x).java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public int mySqrt(int x) { 3 | if (x <= 1) 4 | return x; 5 | 6 | int mid = 1; 7 | int left = 1; 8 | int right = x; 9 | while (left <= right) { 10 | mid = left + (right - left) / 2; 11 | if (mid > x / mid) 12 | right = mid - 1; 13 | else if (mid < x / mid) 14 | left = mid + 1; 15 | else 16 | return mid; 17 | } 18 | return right; 19 | } 20 | } -------------------------------------------------------------------------------- /000-099/070-Climbing-Stairs.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Climbing Stairs 3 | * - Fibonacci Number problem 4 | * - Also a Dynamic Programming problem 5 | * Time Complexity: O(N) 6 | * Space Complexity: O(1) 7 | */ 8 | class Solution { 9 | public int climbStairs(int n) { 10 | // n should be positive 11 | if (n < 1) 12 | return -1; 13 | 14 | // base case 15 | if (n == 1) 16 | return 1; 17 | 18 | // num_ways[i] = num_ways[i-1] + num_ways[i-2] 19 | int result = 2; 20 | int prev_one_step = 2, prev_two_step = 1; 21 | for (int i = 2; i < n; i++) { 22 | result = prev_one_step + prev_two_step; 23 | prev_two_step = prev_one_step; 24 | prev_one_step = result; 25 | } 26 | return result; 27 | } 28 | } -------------------------------------------------------------------------------- /000-099/071-Simplify-Path.cpp: -------------------------------------------------------------------------------- 1 | // Stack 2 | // Time complexity: O(n). 3 | // Space complexity: O(n). 4 | 5 | vector toTokenVector(string str, char delim) { 6 | vector out; 7 | istringstream tokenStream(str); 8 | string token; 9 | while (getline(tokenStream, token, delim)) { 10 | out.push_back(token); 11 | } 12 | return out; 13 | } 14 | 15 | class Solution { 16 | public: 17 | string simplifyPath(string path) { 18 | if (path.empty()) { 19 | return ""; 20 | } 21 | 22 | vector stk; 23 | for (const auto& directory : toTokenVector(path, '/')) { 24 | if (directory.empty() || directory == ".") { 25 | continue; 26 | } else if (directory == "..") { 27 | if (!stk.empty()) { 28 | stk.pop_back(); 29 | } 30 | } else { 31 | stk.push_back(directory); 32 | } 33 | } 34 | 35 | string res; 36 | for (const auto& directory : stk) { 37 | res += "/"; 38 | res += directory; 39 | } 40 | 41 | return res.empty() ? "/" : res; 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /000-099/074-Search-a-2D-Matrix.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(log(m) + log(n)) = O(log(mn)) 2 | // Space complexity: O(1) 3 | 4 | class Solution { 5 | public: 6 | bool searchMatrix(vector>& matrix, int target) { 7 | if (matrix.empty() || matrix[0].empty()) return false; 8 | 9 | int row = -1; 10 | int lo = 0; 11 | int hi = matrix.size() - 1; 12 | while (lo <= hi) { 13 | int mid = lo + (hi - lo) / 2; 14 | if (matrix[mid][0] == target) { 15 | return true; 16 | } else if (matrix[mid][0] < target) { 17 | row = mid; 18 | lo = mid + 1; 19 | } else { 20 | hi = mid - 1; 21 | } 22 | } 23 | if (row == -1) return false; 24 | 25 | lo = 0; 26 | hi = matrix[0].size() - 1; 27 | while (lo <= hi) { 28 | int mid = lo + (hi - lo) / 2; 29 | if (matrix[row][mid] == target) { 30 | return true; 31 | } else if (matrix[row][mid] < target) { 32 | lo = mid + 1; 33 | } else { 34 | hi = mid - 1; 35 | } 36 | } 37 | return false; 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /000-099/075-Sort-Colors.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public void sortColors(int[] nums) { 3 | int i = 0, r = 0, b = nums.length - 1; 4 | int aux; 5 | while (i <= b) { 6 | switch (nums[i]) { 7 | case 0: 8 | aux = nums[r]; 9 | nums[r] = nums[i]; 10 | nums[i] = aux; 11 | r++; 12 | i++; 13 | break; 14 | case 1: 15 | i++; 16 | break; 17 | case 2: 18 | aux = nums[b]; 19 | nums[b] = nums[i]; 20 | nums[i] = aux; 21 | b--; 22 | break; 23 | } 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /000-099/083-Remove-Duplicates-from-Sorted-List.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * public class ListNode { 4 | * int val; 5 | * ListNode next; 6 | * ListNode(int x) { val = x; } 7 | * } 8 | */ 9 | class Solution { 10 | public ListNode deleteDuplicates(ListNode head) { 11 | ListNode current = head; 12 | while (current != null && current.next != null) { 13 | if (current.next.val == current.val) 14 | current.next = current.next.next; 15 | else 16 | current = current.next; 17 | } 18 | return head; 19 | } 20 | } -------------------------------------------------------------------------------- /000-099/083-Remove-Duplicates-from-Sorted-List.md: -------------------------------------------------------------------------------- 1 | # 083-Remove Duplicates from Sorted List 2 | 3 | [Problem](https://leetcode.com/problems/remove-duplicates-from-sorted-list/) 4 | 5 | ## Algorithm 6 | 7 | Iterate through the list. Whenever find an element having the same value as the next element, remove all the subsequent elements with the same value. Compare to Problem 082, we do not need a dummy_head, as the head of the list will be kept unchanged; we do not need to keep track of the previous node as well, as we will only be deleting the nodes after the currently visited node. 8 | 9 | Time complexity: O(n). 10 | 11 | Space complexity: O(1). 12 | 13 | ```c++ 14 | /** 15 | * Definition for singly-linked list. 16 | * struct ListNode { 17 | * int val; 18 | * ListNode *next; 19 | * ListNode(int x) : val(x), next(NULL) {} 20 | * }; 21 | */ 22 | class Solution { 23 | public: 24 | ListNode* deleteDuplicates(ListNode* head) { 25 | ListNode* curr{head}; 26 | 27 | while (curr && curr->next) { 28 | if (curr->val == curr->next->val) { 29 | curr->next = curr->next->next; 30 | } else { 31 | curr = curr->next; 32 | } 33 | } 34 | 35 | return head; 36 | } 37 | }; 38 | ``` 39 | -------------------------------------------------------------------------------- /000-099/085-Maximal-Rectangle.md: -------------------------------------------------------------------------------- 1 | # 085-Maximal Rectangle 2 | 3 | [Problem](https://leetcode.com/problems/maximal-rectangle/) 4 | 5 | ## Approach 1: Brute Force 6 | 7 | Time complexity: O(m * n^2). 8 | 9 | Space complexity: O(m * n). 10 | 11 | ```c++ 12 | class Solution { 13 | public: 14 | int maximalRectangle(vector>& matrix) { 15 | if (matrix.empty() || matrix[0].empty()) return 0; 16 | int height = matrix.size(); 17 | int width = matrix[0].size(); 18 | 19 | vector> num_left_ones(height, vector(width, 0)); 20 | for (auto i = 0; i < height; ++i) { 21 | if (matrix[i][0] == '1') { 22 | num_left_ones[i][0] = 1; 23 | } 24 | for (auto j = 1; j < width; ++j) { 25 | if (matrix[i][j] == '1') { 26 | num_left_ones[i][j] = num_left_ones[i][j - 1] + 1; 27 | } 28 | } 29 | } 30 | 31 | int max_area = 0; 32 | for (auto j = 0; j < width; ++j) { 33 | for (auto i_top = 0; i_top < height; ++i_top) { 34 | int min_left_ones = width; 35 | for (auto i_bottom = i_top; i_bottom < height; ++i_bottom) { 36 | min_left_ones = min(num_left_ones[i_bottom][j], min_left_ones); 37 | int area = min_left_ones * (i_bottom - i_top + 1); 38 | max_area = max(area, max_area); 39 | } 40 | } 41 | } 42 | 43 | return max_area; 44 | } 45 | }; 46 | ``` 47 | -------------------------------------------------------------------------------- /000-099/088-Merge-Sorted-Array.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public void merge(int[] nums1, int m, int[] nums2, int n) { 3 | if (nums1.length < m + n) 4 | throw new Error("Space not enough in array nums1!"); 5 | 6 | int i = m - 1, j = n - 1; 7 | while (i >= 0 && j >= 0) { 8 | if (nums1[i] > nums2[j]) { 9 | nums1[i + j + 1] = nums1[i]; 10 | i--; 11 | } else { 12 | nums1[i + j + 1] = nums2[j]; 13 | j--; 14 | } 15 | } 16 | while (j >= 0) { 17 | nums1[j] = nums2[j]; 18 | j--; 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /000-099/092-Reverse-Linked-List-II.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(1). 3 | 4 | /** 5 | * Definition for singly-linked list. 6 | * struct ListNode { 7 | * int val; 8 | * ListNode *next; 9 | * ListNode(int x) : val(x), next(NULL) {} 10 | * }; 11 | */ 12 | class Solution { 13 | public: 14 | ListNode* reverseBetween(ListNode* head, int m, int n) { 15 | ListNode dummy{-1}; 16 | dummy.next = head; 17 | ListNode* prev{&dummy}; 18 | ListNode* curr{head}; 19 | 20 | // Iterate to position m 21 | for (int i{1}; i < m; ++i) { 22 | prev = curr; 23 | curr = curr->next; 24 | } 25 | ListNode* pred_node_m{prev}; 26 | ListNode* node_m{curr}; 27 | 28 | // Reverse list between position m and n 29 | for (int i{0}; i < n - m + 1; ++i) { 30 | ListNode* next_temp{curr->next}; 31 | curr->next = prev; 32 | prev = curr; 33 | curr = next_temp; 34 | } 35 | ListNode* node_n{prev}; 36 | ListNode* succ_node_n{curr}; 37 | 38 | // Combine lists 39 | pred_node_m->next = node_n; 40 | node_m->next = succ_node_n; 41 | 42 | return dummy.next; 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /000-099/094-Binary-Tree-Inorder-Traversal.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * public class TreeNode { 4 | * int val; 5 | * TreeNode left; 6 | * TreeNode right; 7 | * TreeNode(int x) { val = x; } 8 | * } 9 | */ 10 | class Solution { 11 | public List inorderTraversal(TreeNode root) { 12 | List result = new ArrayList(); 13 | if (root != null) { 14 | result.addAll(inorderTraversal(root.left)); 15 | result.add(root.val); 16 | result.addAll(inorderTraversal(root.right)); 17 | } 18 | return result; 19 | } 20 | } -------------------------------------------------------------------------------- /000-099/098-Validate-Binary-Search-Tree.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n) 2 | // Space complexity: O(n) 3 | 4 | /** 5 | * Definition for a binary tree node. 6 | * struct TreeNode { 7 | * int val; 8 | * TreeNode *left; 9 | * TreeNode *right; 10 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 11 | * }; 12 | */ 13 | class Solution { 14 | public: 15 | bool isValidBST(TreeNode* root) { 16 | return isValidBSTHelper(root, numeric_limits::min(), numeric_limits::max()); 17 | } 18 | private: 19 | bool isValidBSTHelper(TreeNode* root, long lower, long upper) { 20 | if (!root) return true; 21 | 22 | int val = root->val; 23 | return (val > lower && val < upper && 24 | isValidBSTHelper(root->left, lower, val) && 25 | isValidBSTHelper(root->right, val, upper)); 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /100-199/100-Same-Tree.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * public class TreeNode { 4 | * int val; 5 | * TreeNode left; 6 | * TreeNode right; 7 | * TreeNode(int x) { val = x; } 8 | * } 9 | */ 10 | class Solution { 11 | public boolean isSameTree(TreeNode p, TreeNode q) { 12 | if (p == null && q == null) return true; 13 | if (p == null || q == null) return false; 14 | return p.val == q.val && isSameTree(p.left, q.left) && isSameTree(p.right, q.right); 15 | } 16 | } -------------------------------------------------------------------------------- /100-199/101-Symmetric-Tree.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * public class TreeNode { 4 | * int val; 5 | * TreeNode left; 6 | * TreeNode right; 7 | * TreeNode(int x) { val = x; } 8 | * } 9 | */ 10 | class Solution { 11 | public boolean isSymmetric(TreeNode root) { 12 | return isMirror(root, root); 13 | } 14 | 15 | public boolean isMirror(TreeNode t1, TreeNode t2) { 16 | if (t1 == null && t2 == null) return true; 17 | if (t1 == null || t2 == null) return false; 18 | return (t1.val == t2.val) 19 | && isMirror(t1.right, t2.left) 20 | && isMirror(t1.left, t2.right); 21 | } 22 | } -------------------------------------------------------------------------------- /100-199/104-Maximum-Depth-of-Binary-Tree.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * public class TreeNode { 4 | * int val; 5 | * TreeNode left; 6 | * TreeNode right; 7 | * TreeNode(int x) { val = x; } 8 | * } 9 | */ 10 | class Solution { 11 | public int maxDepth(TreeNode root) { 12 | if (root == null) 13 | return 0; 14 | else 15 | return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1; 16 | } 17 | } -------------------------------------------------------------------------------- /100-199/108-Convert-Sorted-Array-to-Binary-Search-Tree.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(logn) extra space due to recursion. 3 | 4 | /** 5 | * Definition for a binary tree node. 6 | * struct TreeNode { 7 | * int val; 8 | * TreeNode *left; 9 | * TreeNode *right; 10 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 11 | * }; 12 | */ 13 | class Solution { 14 | public: 15 | TreeNode* sortedArrayToBST(vector& nums) { 16 | return sortedArrayToBSTRecu(nums, 0, nums.size()); 17 | } 18 | private: 19 | TreeNode* sortedArrayToBSTRecu(const vector& nums, int start, int end) { 20 | if (start == end) { 21 | return nullptr; 22 | } else { 23 | int mid = start + (end - start) / 2; 24 | TreeNode* root = new TreeNode{nums[mid]}; 25 | root->left = sortedArrayToBSTRecu(nums, start, mid); 26 | root->right = sortedArrayToBSTRecu(nums, mid + 1, end); 27 | return root; 28 | } 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /100-199/110-Balanced-Binary-Tree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * struct TreeNode { 4 | * int val; 5 | * TreeNode *left; 6 | * TreeNode *right; 7 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 | * }; 9 | */ 10 | class Solution { 11 | public: 12 | bool isBalanced(TreeNode* root) { 13 | if (!root) return true; 14 | return isBalanced(root->left) && isBalanced(root->right) 15 | && abs(height(root->left) - height(root->right)) <= 1; 16 | } 17 | 18 | int height(TreeNode* root) { 19 | if (!root) return 0; 20 | return max(height(root->left), height(root->right)) + 1; 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /100-199/111-Minimum-Depth-of-Binary-Tree.md: -------------------------------------------------------------------------------- 1 | # 111-Minimum Depth of Binary Tree 2 | 3 | [Problem](https://leetcode.com/problems/minimum-depth-of-binary-tree/) 4 | 5 | ## Algorithm 6 | 7 | This may look like getting min depth. But the trap is NULL node. Depth for NULL node is short but it's not the LEAF node. So we should ignore NULL node. 8 | 9 | Time complexity: O(n). 10 | 11 | Space complexity: O(n) due to recursion. 12 | 13 | ```c++ 14 | /** 15 | * Definition for a binary tree node. 16 | * struct TreeNode { 17 | * int val; 18 | * TreeNode *left; 19 | * TreeNode *right; 20 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 21 | * }; 22 | */ 23 | class Solution { 24 | public: 25 | int minDepth(TreeNode* root) { 26 | if (!root) return 0; 27 | 28 | int left = minDepth(root->left); 29 | int right = minDepth(root->right); 30 | 31 | if (left > 0 && right > 0) { 32 | return 1 + min(left, right); 33 | } else { 34 | return 1 + (left + right); 35 | } 36 | } 37 | }; 38 | ``` 39 | -------------------------------------------------------------------------------- /100-199/112-Path-Sum.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n) 2 | // Space complexity: O(1) 3 | 4 | /** 5 | * Definition for a binary tree node. 6 | * struct TreeNode { 7 | * int val; 8 | * TreeNode *left; 9 | * TreeNode *right; 10 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 11 | * }; 12 | */ 13 | class Solution { 14 | public: 15 | bool hasPathSum(TreeNode* root, int sum) { 16 | if (!root) return false; 17 | 18 | if (!root->left && !root->right) return (sum == root->val); 19 | 20 | return hasPathSum(root->left, sum - root->val) || hasPathSum(root->right, sum - root->val); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /100-199/112-Path-Sum.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * public class TreeNode { 4 | * int val; 5 | * TreeNode left; 6 | * TreeNode right; 7 | * TreeNode(int x) { val = x; } 8 | * } 9 | */ 10 | class Solution { 11 | public boolean hasPathSum(TreeNode root, int sum) { 12 | if (root == null) 13 | return false; 14 | 15 | if (root.left == null && root.right == null) { // leaf node 16 | return sum == root.val; 17 | } else { // non-leaf node 18 | return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /100-199/115-Distinct-Subsequences.md: -------------------------------------------------------------------------------- 1 | # 115-Distinct Subsequences 2 | 3 | [Problem](https://leetcode.com/problems/distinct-subsequences/) 4 | 5 | ## Approach 1: Dynamic Programming 6 | 7 | Similar to 072-Edit Distance, recurrence structure to count s[1..i] as subsequences of t[1..j]: 8 | 9 | 1. s[i] = t[j]: num_distincts(i, j) = num_distincts(i, j - 1) (do not use t[j] to match s[i]) + num_distincts(i - 1, j - 1) (use t[j] to match s[i]), 10 | 11 | 2. s[i] != t[j]: num_distincts(i, j) = num_distincts(i, j - 1) (t[j] is redundant). 12 | 13 | We then apply dynamic programming for smarter recursion. 14 | 15 | Time complexity: O(M * N). 16 | 17 | Space complexity: O(M * N). 18 | 19 | ```c++ 20 | class Solution { 21 | public: 22 | int numDistinct(string s, string t) { 23 | const int M = t.size(); 24 | const int N = s.size(); 25 | if (N < M) return 0; 26 | 27 | vector> num_distincts(M + 1, vector(N + 1, 0)); 28 | 29 | for (int j = 0; j <= N; ++j) { 30 | num_distincts[0][j] = 1; 31 | } 32 | 33 | for (int i = 1; i <= M; ++i) { 34 | for (int j = i; j <= N; ++j) { 35 | int indicator = (t[i - 1] == s[j - 1]) ? 1 : 0; 36 | num_distincts[i][j] = num_distincts[i - 1][j - 1] * indicator + 37 | num_distincts[i][j - 1]; 38 | } 39 | } 40 | 41 | return num_distincts[M][N]; 42 | } 43 | }; 44 | ``` 45 | -------------------------------------------------------------------------------- /100-199/116-Populating-Next-Right-Pointers-in-Each-Node.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(n). 3 | 4 | /* 5 | // Definition for a Node. 6 | class Node { 7 | public: 8 | int val; 9 | Node* left; 10 | Node* right; 11 | Node* next; 12 | 13 | Node() {} 14 | 15 | Node(int _val, Node* _left, Node* _right, Node* _next) { 16 | val = _val; 17 | left = _left; 18 | right = _right; 19 | next = _next; 20 | } 21 | }; 22 | */ 23 | class Solution { 24 | public: 25 | Node* connect(Node* root) { 26 | if (!root) return root; 27 | 28 | queue q; 29 | unordered_map depth; 30 | 31 | Node* prev = nullptr; 32 | q.push(root); 33 | depth[root] = 0; 34 | 35 | while (!q.empty()) { 36 | Node* curr = q.front(); 37 | q.pop(); 38 | 39 | Node* left = curr->left; 40 | Node* right = curr->right; 41 | if (left) { 42 | q.push(left); 43 | depth[left] = depth[curr] + 1; 44 | } 45 | if (right) { 46 | q.push(right); 47 | depth[right] = depth[curr] + 1; 48 | } 49 | 50 | // update next 51 | if (prev && depth[prev] == depth[curr]) { 52 | prev->next = curr; 53 | } 54 | prev = curr; 55 | } 56 | 57 | return root; 58 | } 59 | }; -------------------------------------------------------------------------------- /100-199/117-Populating-Next-Right-Pointers-in-Each-Node-II.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(n). 3 | 4 | /* 5 | // Definition for a Node. 6 | class Node { 7 | public: 8 | int val; 9 | Node* left; 10 | Node* right; 11 | Node* next; 12 | 13 | Node() {} 14 | 15 | Node(int _val, Node* _left, Node* _right, Node* _next) { 16 | val = _val; 17 | left = _left; 18 | right = _right; 19 | next = _next; 20 | } 21 | }; 22 | */ 23 | class Solution { 24 | public: 25 | Node* connect(Node* root) { 26 | if (!root) return root; 27 | 28 | queue q; 29 | unordered_map depth; 30 | 31 | Node* prev = nullptr; 32 | q.push(root); 33 | depth[root] = 0; 34 | 35 | while (!q.empty()) { 36 | Node* curr = q.front(); 37 | q.pop(); 38 | 39 | Node* left = curr->left; 40 | Node* right = curr->right; 41 | if (left) { 42 | q.push(left); 43 | depth[left] = depth[curr] + 1; 44 | } 45 | if (right) { 46 | q.push(right); 47 | depth[right] = depth[curr] + 1; 48 | } 49 | 50 | // update next 51 | if (prev && depth[prev] == depth[curr]) { 52 | prev->next = curr; 53 | } 54 | prev = curr; 55 | } 56 | 57 | return root; 58 | } 59 | }; 60 | -------------------------------------------------------------------------------- /100-199/118-Pascal's-Triangle.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(numRows^2) 2 | // Space complexity: O(numRows^2) 3 | 4 | class Solution { 5 | public: 6 | vector> generate(int numRows) { 7 | vector> triangle; 8 | 9 | for (auto i = 0; i < numRows; ++i) { 10 | vector row{1}; 11 | for (auto j = 1; j < i; ++j) { 12 | row.push_back(triangle[i - 1][j - 1] + triangle[i - 1][j]); 13 | } 14 | if (i > 0) { 15 | row.push_back(1); 16 | } 17 | triangle.push_back(row); 18 | } 19 | 20 | return triangle; 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /100-199/119-Pascal's-Triangle-II.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n^2) 2 | // Space complexity: O(n) 3 | 4 | class Solution { 5 | public: 6 | vector getRow(int rowIndex) { 7 | vector row(rowIndex + 1, 1); 8 | 9 | for (auto i = 1; i < rowIndex + 1; ++i) { 10 | for (auto j = i - 1; j > 0; --j) { 11 | row[j] += row[j - 1]; // Key: backward processing for memory saving 12 | } 13 | } 14 | 15 | return row; 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /100-199/120-Triangle.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public int minimumTotal(List> triangle) { 3 | if (triangle == null || triangle.get(0) == null || 4 | triangle.get(0).size() == 0) 5 | return -1; 6 | 7 | int size = triangle.size(); 8 | int[] triangle_mem = new int[size]; 9 | triangle_mem[0] = triangle.get(0).get(0); 10 | for (int i = 1; i < size; i++) { 11 | List row = triangle.get(i); 12 | triangle_mem[i] = triangle_mem[i - 1] + row.get(i); 13 | for (int j = i - 1; j > 0; j--) { 14 | if (triangle_mem[j - 1] > triangle_mem[j]) 15 | triangle_mem[j] = triangle_mem[j] + row.get(j); 16 | else 17 | triangle_mem[j] = triangle_mem[j - 1] + row.get(j); 18 | } 19 | triangle_mem[0] += row.get(0); 20 | } 21 | 22 | int min = triangle_mem[0]; 23 | for (int i = 1; i < size; i++) { 24 | if (triangle_mem[i] < min) 25 | min = triangle_mem[i]; 26 | } 27 | 28 | return min; 29 | } 30 | } -------------------------------------------------------------------------------- /100-199/125-Valid-Palindrome.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(1) extra space. 3 | 4 | class Solution { 5 | public: 6 | bool isPalindrome(string s) { 7 | int cnt_alnum = 0; 8 | for (char ch : s) { 9 | if (isalnum(ch)) cnt_alnum++; 10 | } 11 | 12 | int forward = 0; 13 | int backward = s.size() - 1; 14 | for (int i = 0; i < cnt_alnum / 2; ++i, ++forward, --backward) { 15 | while (!isalnum(s[forward])) ++forward; 16 | while (!isalnum(s[backward])) --backward; 17 | if (tolower(s[forward]) != tolower(s[backward])) { 18 | return false; 19 | } 20 | } 21 | return true; 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /100-199/129-Sum-Root-to-Leaf-Numbers.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). Visited each node once. 2 | // Space complexity: O(n) due to recursion. 3 | 4 | /** 5 | * Definition for a binary tree node. 6 | * struct TreeNode { 7 | * int val; 8 | * TreeNode *left; 9 | * TreeNode *right; 10 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 11 | * }; 12 | */ 13 | class Solution { 14 | public: 15 | int sumNumbers(TreeNode* root) { 16 | if (!root) { 17 | return 0; 18 | } 19 | 20 | int intermediate = 0, sum = 0; 21 | sumNumbersRecu(root, intermediate, &sum); 22 | return sum; 23 | } 24 | private: 25 | void sumNumbersRecu(TreeNode* root, int intermediate, int* sum) { 26 | int new_intermediate = intermediate * 10 + root->val; 27 | if (!root->left && !root->right) { 28 | (*sum) += new_intermediate; 29 | } else { 30 | if (root->left) { 31 | sumNumbersRecu(root->left, new_intermediate, sum); 32 | } 33 | if (root->right) { 34 | sumNumbersRecu(root->right, new_intermediate, sum); 35 | } 36 | } 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /100-199/130-Surrounded-Regions.cpp: -------------------------------------------------------------------------------- 1 | // DFS 2 | // Time complexity: O(M * N). 3 | // Space complexity: O(M * N). 4 | 5 | class Solution { 6 | public: 7 | void solve(vector>& board) { 8 | int M = board.size(); 9 | if (M == 0) return; 10 | int N = board[0].size(); 11 | 12 | for (int i = 0; i < M; i++) { 13 | if (board[i][0] == 'O') 14 | dfs(i, 0, board); 15 | if (board[i][N - 1] == 'O') 16 | dfs(i, N - 1, board); 17 | } 18 | for (int j = 1; j < N - 1; j++) { 19 | if (board[0][j] == 'O') 20 | dfs(0, j, board); 21 | if (board[M - 1][j] == 'O') 22 | dfs(M - 1, j, board); 23 | } 24 | 25 | for (int i = 0; i < M; i++) { 26 | for (int j = 0; j < N; j++) { 27 | if (board[i][j] == 'R') 28 | board[i][j] = 'O'; 29 | else if (board[i][j] == 'O') 30 | board[i][j] = 'X'; 31 | } 32 | } 33 | } 34 | private: 35 | void dfs(int i, int j, vector>& board) { 36 | board[i][j] = 'R'; // reserved 37 | if (i - 1 >= 0 && board[i - 1][j] == 'O') 38 | dfs(i - 1, j, board); 39 | if (j + 1 < board[0].size() && board[i][j + 1] == 'O') 40 | dfs(i, j + 1, board); 41 | if (i + 1 < board.size() && board[i + 1][j] == 'O') 42 | dfs(i + 1, j, board); 43 | if (j - 1 >= 0 && board[i][j - 1] == 'O') 44 | dfs(i, j - 1, board); 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /100-199/134-Gas-Station.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public int canCompleteCircuit(int[] gas, int[] cost) { 3 | int N = gas.length; 4 | 5 | for (int i = 0; i < N; i++) { 6 | int gas_amount = 0; 7 | boolean flag = true; 8 | for (int j = 0; j < N; j++) { 9 | int loc = (i + j) % N; 10 | gas_amount += gas[loc]; 11 | if (gas_amount < cost[loc]) { 12 | flag = false; 13 | break; 14 | } else { 15 | gas_amount -= cost[loc]; 16 | } 17 | } 18 | if (flag) { 19 | return i; 20 | } 21 | } 22 | 23 | return -1; 24 | } 25 | } -------------------------------------------------------------------------------- /100-199/136-Single-Number.md: -------------------------------------------------------------------------------- 1 | # 136-Single Number 2 | 3 | [Problem](https://leetcode.com/problems/single-number/) 4 | 5 | ## Approach 1: Hash Table 6 | 7 | Time complexity: O(n). 8 | 9 | Space complexity: O(n). 10 | 11 | ```c++ 12 | class Solution { 13 | public: 14 | int singleNumber(vector& nums) { 15 | unordered_map m; 16 | for (auto num : nums) { 17 | if (m.find(num) == m.end()) { 18 | m.insert({num, 1}); 19 | } else { 20 | m[num]++; 21 | } 22 | } 23 | 24 | int output = 0; 25 | for (const auto& p : m) { 26 | if (p.second == 1) { 27 | output = p.first; 28 | break; 29 | } 30 | } 31 | return output; 32 | } 33 | }; 34 | ``` 35 | 36 | ## Approach 2: Bit Manipulation 37 | 38 | Utilize XOR(^). 0^a = a, a^0 = a, a^a = 0. So, a^a^b = b. 39 | 40 | Time complexity: O(n). 41 | 42 | Space complexity: O(1). 43 | 44 | ```c++ 45 | class Solution { 46 | public: 47 | int singleNumber(vector& nums) { 48 | int result {0}; 49 | for (int num : nums) { 50 | result ^= num; 51 | } 52 | return result; 53 | } 54 | }; 55 | ``` 56 | -------------------------------------------------------------------------------- /100-199/137-Single-Number-II.md: -------------------------------------------------------------------------------- 1 | # 137-Single Number II 2 | 3 | [Problem](https://leetcode.com/problems/single-number-ii/) 4 | 5 | ## Approach 1: Hash Table 6 | 7 | Time complexity: O(n). 8 | 9 | Space complexity: O(n). 10 | 11 | ```c++ 12 | class Solution { 13 | public: 14 | int singleNumber(vector& nums) { 15 | unordered_map m; 16 | for (int num : nums) { 17 | m[num]++; 18 | } 19 | 20 | for (auto& p : m) { 21 | if (p.second == 1) { 22 | return p.first; 23 | } 24 | } 25 | return -1; 26 | } 27 | }; 28 | ``` 29 | 30 | ## Approach 2: Bit Manipulation 31 | 32 | To separate number that appears once from a number that appears three times let's use two bitmasks instead of one: seen_once and seen_twice. 33 | 34 | The idea is to 35 | 36 | * change seen_once only if seen_twice is unchanged 37 | 38 | * change seen_twice only if seen_once is unchanged 39 | 40 | Time complexity: O(n). 41 | 42 | Space complexity: O(1). 43 | 44 | ```c++ 45 | class Solution { 46 | public: 47 | int singleNumber(vector& nums) { 48 | int seenOnce = 0, seenTwice = 0; 49 | 50 | for (int num : nums) { 51 | seenOnce = ~seenTwice & (seenOnce ^ num); 52 | seenTwice = ~seenOnce & (seenTwice ^ num); 53 | } 54 | 55 | return seenOnce; 56 | } 57 | }; 58 | ``` 59 | -------------------------------------------------------------------------------- /100-199/141-Linked-List-Cycle.md: -------------------------------------------------------------------------------- 1 | # 141-Linked List Cycle 2 | 3 | [Problem](https://leetcode.com/problems/linked-list-cycle/) 4 | 5 | ## Approach 1: Hash Table 6 | 7 | Time complexity: O(n). 8 | 9 | Space complexity: O(n). 10 | 11 | ## Approach 2: Two Pointers: Floyd's Tortoise and Hare 12 | 13 | Imagine there are two people A and B start from the same point, A is twice fast as B. If they are chasing along a cyclic route, they are sure to meet again, otherwise not. Here, we use two pointers, one fast, one slow, chasing each other. The algorithm was credited to Robert W. Floyd by Donald Knuth (a potential misattribution), and is also called the "tortoise and the hare algorithm". 14 | 15 | Time complexity: O(n). 16 | 17 | Space complexity: O(1). 18 | 19 | ```c++ 20 | /** 21 | * Definition for singly-linked list. 22 | * struct ListNode { 23 | * int val; 24 | * ListNode *next; 25 | * ListNode(int x) : val(x), next(NULL) {} 26 | * }; 27 | */ 28 | class Solution { 29 | public: 30 | bool hasCycle(ListNode *head) { 31 | ListNode* slow = head; 32 | ListNode* fast = head; 33 | 34 | while (fast && fast->next) { 35 | slow = slow->next; 36 | fast = fast->next->next; 37 | if (slow == fast) { 38 | return true; 39 | } 40 | } 41 | 42 | return false; 43 | } 44 | }; 45 | ``` 46 | -------------------------------------------------------------------------------- /100-199/143-Reorder-List.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * public class ListNode { 4 | * int val; 5 | * ListNode next; 6 | * ListNode(int x) { val = x; } 7 | * } 8 | */ 9 | 10 | /** 11 | * Naive Recursive Solution 12 | * Time Complexity: O(N^2) 13 | * Space Complexity: O(N) 14 | */ 15 | class Solution1 { 16 | public void reorderList(ListNode head) { 17 | if (head == null) 18 | return; 19 | 20 | ListNode tail = head, tailPred = head; 21 | while (tail.next != null) { 22 | tailPred = tail; 23 | tail = tail.next; 24 | } 25 | if (head != tail && head != tailPred) { 26 | tailPred.next = null; 27 | tail.next = head.next; 28 | head.next = tail; 29 | reorderList(tail.next); 30 | } 31 | } 32 | } 33 | 34 | /** 35 | * Iterative Version of the Naive Recursive Solution 36 | */ 37 | class Solution2 { 38 | public void reorderList(ListNode head) { 39 | while (head != null) { 40 | ListNode tail = head, tailPred = head; 41 | while (tail.next != null) { 42 | tailPred = tail; 43 | tail = tail.next; 44 | } 45 | if (head != tail && head != tailPred) { 46 | tailPred.next = null; 47 | tail.next = head.next; 48 | head.next = tail; 49 | } 50 | head = tail.next; 51 | } 52 | } 53 | } 54 | 55 | /** 56 | * Two Pointers 57 | */ 58 | -------------------------------------------------------------------------------- /100-199/147-Insertion-Sort-List.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * public class ListNode { 4 | * int val; 5 | * ListNode next; 6 | * ListNode(int x) { val = x; } 7 | * } 8 | */ 9 | class Solution { 10 | public ListNode insertionSortList(ListNode head) { 11 | if (head == null) // empty list 12 | return head; 13 | 14 | ListNode dummy = new ListNode(-1); 15 | 16 | while (head != null) { 17 | // find insertion position 18 | ListNode insert_pos = dummy; 19 | while (insert_pos.next != null && insert_pos.next.val < head.val) { 20 | insert_pos = insert_pos.next; 21 | } 22 | 23 | // insert 24 | ListNode temp = insert_pos.next; 25 | insert_pos.next = head; 26 | head = head.next; 27 | insert_pos.next.next = temp; 28 | } 29 | return dummy.next; 30 | } 31 | } -------------------------------------------------------------------------------- /100-199/150-Evaluate-Reverse-Polish-Notation.cpp: -------------------------------------------------------------------------------- 1 | // Use a stack. Stack only holds numbers, when an operator is encountered, 2 | // pop two oprands, apply operation, and push reduced result back to stack. 3 | 4 | // Time complexity: O(n). 5 | // Space complexity: O(n). 6 | 7 | class Solution { 8 | public: 9 | int evalRPN(vector& tokens) { 10 | stack s; 11 | for (auto& token : tokens) { 12 | if (token == "+" || token == "-" || token == "*" || token == "/") { 13 | int oprand2 = s.top(); s.pop(); 14 | int oprand1 = s.top(); s.pop(); 15 | 16 | if (token == "+") 17 | s.push(oprand1 + oprand2); 18 | else if (token == "-") 19 | s.push(oprand1 - oprand2); 20 | else if (token == "*") 21 | s.push(oprand1 * oprand2); 22 | else 23 | s.push(oprand1 / oprand2); 24 | } else { 25 | s.push(stoi(token)); 26 | } 27 | } 28 | return s.top(); 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /100-199/152-Maximum-Product-Subarray.md: -------------------------------------------------------------------------------- 1 | # 152-Maximum Product Subarray 2 | 3 | [Problem](https://leetcode.com/problems/maximum-product-subarray/) 4 | 5 | ## Approach 1: Dynamic Programming 6 | 7 | Time complexity: O(n). 8 | 9 | Space complexity: O(n). 10 | 11 | ```c++ 12 | class Solution { 13 | public: 14 | int maxProduct(vector& nums) { 15 | auto N = nums.size(); 16 | assert(N > 0); 17 | 18 | int max_product = 0; 19 | vector mem_max{nums}; 20 | vector mem_min{nums}; 21 | 22 | for (auto i = 1; i < N; ++i) { 23 | int product_1 = mem_max[i - 1] * nums[i]; 24 | int product_2 = mem_min[i - 1] * nums[i]; 25 | int max_product = max(product_1, product_2); 26 | int min_product = min(product_1, product_2); 27 | if (max_product > mem_max[i]) { 28 | mem_max[i] = max_product; 29 | } 30 | if (min_product < mem_min[i]) { 31 | mem_min[i] = min_product; 32 | } 33 | } 34 | 35 | return *max_element(mem_max.begin(), mem_max.end()); 36 | } 37 | }; 38 | ``` 39 | -------------------------------------------------------------------------------- /100-199/153-Find-Minimum-in-Rotated-Sorted-Array.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(logn). 2 | // Space complexity: O(1). 3 | 4 | class Solution { 5 | public: 6 | int findMin(vector& nums) { 7 | // find the pivot of rotation (where nums[p - 1] < nums[p]) and return 8 | int lo = 0; 9 | int hi = nums.size() - 1; 10 | while (lo <= hi) { 11 | int mid = lo + (hi - lo) / 2; 12 | if (nums[mid] >= nums[lo]) { 13 | if (mid < nums.size() - 1 && nums[mid] > nums[mid + 1]) { 14 | return nums[mid + 1]; 15 | } 16 | lo = mid + 1; 17 | } else { 18 | if (mid > 0 && nums[mid] < nums[mid - 1]) { 19 | return nums[mid]; 20 | } 21 | hi = mid - 1; 22 | } 23 | } 24 | 25 | // if no pivot found, then the array is sorted, return the first element 26 | return nums.front(); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /100-199/154-Find-Minimum-in-Rotated-Sorted-Array-II.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(logn). 2 | // Space complexity: O(1). 3 | 4 | class Solution { 5 | public: 6 | int findMin(vector& nums) { 7 | // find the pivot of rotation (where nums[p - 1] < nums[p]) and return 8 | int lo = 0; 9 | int hi = nums.size() - 1; 10 | while (lo <= hi) { 11 | int mid = lo + (hi - lo) / 2; 12 | if (nums[mid] == nums[lo]) { 13 | // deal with duplicates 14 | if (lo < nums.size() - 1 && nums[lo] > nums[lo + 1]) { 15 | return nums[lo + 1]; 16 | } 17 | lo++; 18 | } else if (nums[mid] > nums[lo]) { 19 | if (mid < nums.size() - 1 && nums[mid] > nums[mid + 1]) { 20 | return nums[mid + 1]; 21 | } 22 | lo = mid + 1; 23 | } else { 24 | if (mid > 0 && nums[mid] < nums[mid - 1]) { 25 | return nums[mid]; 26 | } 27 | hi = mid - 1; 28 | } 29 | } 30 | 31 | // if no pivot found, then the array is sorted, return the first element 32 | return nums.front(); 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /100-199/159-Longest-Substring-with-At-Most-Two-Distinct-Characters.cpp: -------------------------------------------------------------------------------- 1 | // Sliding Window 2 | 3 | // Time complexity: O(N). 4 | // Extra space complexity: O(1) if we erase the element when shrinking the sliding window, otherwise O(N) 5 | 6 | class Solution { 7 | public: 8 | int lengthOfLongestSubstringTwoDistinct(string s) { 9 | int n = s.size(); 10 | if (n == 0) return 0; 11 | 12 | int max_len = 0; 13 | int cnt_distinct = 0; 14 | int left = 0, right = 0; 15 | unordered_map m; 16 | 17 | while (right < n) { 18 | if (++m[s[right]] == 1) ++cnt_distinct; 19 | ++right; 20 | 21 | while (cnt_distinct > 2) { 22 | if (--m[s[left]] == 0) --cnt_distinct; 23 | ++left; 24 | } 25 | 26 | max_len = max(right - left, max_len); 27 | } 28 | 29 | return max_len; 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /100-199/161-One-Edit-Distance.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(1). 3 | 4 | class Solution { 5 | public: 6 | bool isOneEditDistance(string s, string t) { 7 | const int NS = s.size(); 8 | const int NT = t.size(); 9 | 10 | if (NS > NT) { 11 | return isOneEditDistance(t, s); 12 | } 13 | 14 | if (NS - NT > 1) { 15 | return false; 16 | } 17 | 18 | for (int i = 0; i < NS; i++) { 19 | if (s[i] != t[i]) { 20 | if (NS == NT) { 21 | return s.substr(i + 1) == t.substr(i + 1); 22 | } else { 23 | return s.substr(i) == t.substr(i + 1); 24 | } 25 | } 26 | } 27 | 28 | // If there is no diffs on ns distance 29 | // the strings are one edit away only if 30 | // t has one more character. 31 | return (NS + 1 == NT); 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /100-199/162-Find-Peak-Element.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(logn) 2 | // Space complexity: O(1) 3 | 4 | class Solution { 5 | public: 6 | int findPeakElement(vector& nums) { 7 | int left {0}; 8 | int right {nums.size() - 1}; 9 | 10 | while (left < right) { 11 | int mid {left + (right - left) / 2}; 12 | if (nums[mid] > nums[mid + 1]) { 13 | right = mid; 14 | } else { 15 | left = mid + 1; 16 | } 17 | } 18 | 19 | return left; 20 | } 21 | }; 22 | 23 | // Alternative implementation 24 | class Solution2 { 25 | public: 26 | int findPeakElement(vector& nums) { 27 | int lo = 0; 28 | int hi = nums.size() - 1; 29 | while (lo <= hi) { 30 | int mid = lo + (hi - lo) / 2; 31 | if ((mid == 0 || nums[mid - 1] < nums[mid]) && 32 | (mid == nums.size() - 1 || nums[mid] > nums[mid + 1])) 33 | return mid; 34 | if (nums[mid] > nums[mid + 1]) { 35 | hi = mid - 1; 36 | } else { 37 | lo = mid + 1; 38 | } 39 | } 40 | return 0; 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /100-199/167-Two-Sum-II---Input-array-is-sorted.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public int[] twoSum(int[] numbers, int target) { 3 | int sum; 4 | int left = 0; 5 | int right = numbers.length - 1; 6 | 7 | while (left < right) { 8 | sum = numbers[left] + numbers[right]; 9 | if (sum == target) 10 | return new int[] {left + 1, right + 1}; 11 | else if (sum > target) 12 | right--; 13 | else 14 | left++; 15 | } 16 | 17 | throw new IllegalArgumentException("No two sum solution"); 18 | } 19 | } -------------------------------------------------------------------------------- /100-199/170-Two-Sum-III---Data-structure-design.cpp: -------------------------------------------------------------------------------- 1 | // Hash Map 2 | // Time Complexity: 3 | // add(number): O(1) 4 | // find(value): O(N) (if use sort + two pointer, then O(NlogN)) 5 | // Space Complexity: O(N) 6 | 7 | class TwoSum { 8 | public: 9 | /** Initialize your data structure here. */ 10 | TwoSum() { 11 | 12 | } 13 | 14 | /** Add the number to an internal data structure.. */ 15 | void add(int number) { 16 | freq_map[number]++; 17 | } 18 | 19 | /** Find if there exists any pair of numbers which sum is equal to the value. */ 20 | bool find(int value) { 21 | for (auto p : freq_map) { 22 | int complement = value - p.first; 23 | if (complement == p.first) { 24 | if (p.second >= 2) 25 | return true; 26 | } else { 27 | auto found = freq_map.find(complement); 28 | if (found != freq_map.end()) 29 | return true; 30 | } 31 | } 32 | return false; 33 | } 34 | private: 35 | unordered_map freq_map; 36 | }; 37 | 38 | /** 39 | * Your TwoSum object will be instantiated and called as such: 40 | * TwoSum* obj = new TwoSum(); 41 | * obj->add(number); 42 | * bool param_2 = obj->find(value); 43 | */ 44 | -------------------------------------------------------------------------------- /100-199/179-Largest-Number.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(nlogn) 2 | // Space complexity: O(n) 3 | 4 | class Solution { 5 | public: 6 | string largestNumber(vector& nums) { 7 | assert(nums.size() > 0); 8 | 9 | // convert num to string 10 | vector str_nums; 11 | for (auto i = 0; i < nums.size(); ++i) { 12 | str_nums.push_back(to_string(nums[i])); 13 | } 14 | 15 | // KEY: sort with custom comparator 16 | sort(str_nums.begin(), str_nums.end(), [](string x, string y) { 17 | return (x + y) > (y + x); // e.g. "3" + "30" > "30" + "3" 18 | }); 19 | 20 | // handle special case: all 0s 21 | if (str_nums.front() == "0") { 22 | return "0"; 23 | } 24 | 25 | // concatenate strings to return 26 | string s = ""; 27 | for (const auto& str_num : str_nums) { 28 | s += str_num; 29 | } 30 | return s; 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /100-199/182-Duplicate-Emails.sql: -------------------------------------------------------------------------------- 1 | # Write your MySQL query statement below 2 | select Email 3 | from Person 4 | group by Email 5 | having count(Email) > 1; 6 | -------------------------------------------------------------------------------- /100-199/188-Best-Time-to-Buy-and-Sell-Stock-IV.md: -------------------------------------------------------------------------------- 1 | # 188-Best Time to Buy and Sell Stock IV 2 | 3 | [Problem](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/) 4 | 5 | At most k transactions. 6 | 7 | ## Approach 1: Dynamic Programming 8 | 9 | This is an extension from 123-Best Time to Buy and Sell Stock II, Approach 2. 10 | 11 | Time complexity: O(n * k). 12 | 13 | Space complexity: O(k). 14 | 15 | ```c++ 16 | class Solution { 17 | public: 18 | int maxProfit(int k, vector& prices) { 19 | const int N = prices.size(); 20 | if (k == 0 || N <= 1) return 0; 21 | k = min(k, N / 2); 22 | 23 | vector buys(k, prices.front()); 24 | vector buy_and_sells(k, 0); 25 | 26 | for (int price : prices) { 27 | buys[0] = min(buys[0], price); 28 | buy_and_sells[0] = max(buy_and_sells[0], price - buys[0]); 29 | for (int i = 1; i < k; ++i) { 30 | buys[i] = min(buys[i], price - buy_and_sells[i - 1]); 31 | buy_and_sells[i] = max(buy_and_sells[i], price - buys[i]); 32 | } 33 | } 34 | 35 | return buy_and_sells.back(); 36 | } 37 | }; 38 | ``` 39 | -------------------------------------------------------------------------------- /1000-1099/1023-Camelcase-Matching.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n * m), where n is the number of queries, m is the max length of a query. 2 | // Space complexity: O(1) extra space. 3 | 4 | class Solution { 5 | public: 6 | vector camelMatch(vector& queries, string pattern) { 7 | vector answer; 8 | for (string &query : queries) { 9 | bool ans = true; 10 | int idx = 0; 11 | for (char ch : query) { 12 | if (idx < pattern.size() && ch == pattern[idx]) { 13 | idx++; 14 | } else if (isupper(ch)) { 15 | ans = false; 16 | break; 17 | } 18 | } 19 | if (idx < pattern.size()) { 20 | ans = false; 21 | } 22 | answer.push_back(ans); 23 | } 24 | return answer; 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /1000-1099/1029-Two-City-Scheduling.cpp: -------------------------------------------------------------------------------- 1 | // Greedy: sort by priceA - priceB. 2 | // Time complexity: O(nlogn). 3 | // Space complexity: O(1) extra space. 4 | 5 | class Solution { 6 | public: 7 | int twoCitySchedCost(vector>& costs) { 8 | int N = costs.size(); 9 | assert(N % 2 == 0); 10 | sort(costs.begin(), costs.end(), [](vector& a, vector& b) { 11 | return a.front() - a.back() < b.front() - b.back(); 12 | }); 13 | 14 | int cost = 0; 15 | for (int i = 0; i < N / 2; i++) { 16 | cost += costs[i].front(); 17 | } 18 | for (int i = N / 2; i < N; i++) { 19 | cost += costs[i].back(); 20 | } 21 | return cost; 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /1000-1099/1047-Remove-All-Adjacent-Duplicates-In-String.cpp: -------------------------------------------------------------------------------- 1 | // Stack 2 | // Time complexity: O(n). 3 | // Space complexity: O(n). 4 | 5 | class Solution { 6 | public: 7 | string removeDuplicates(string S) { 8 | string res; 9 | for (auto c : S) { 10 | if (res.empty() || res.back() != c) { 11 | res.push_back(c); 12 | } else { 13 | res.pop_back(); 14 | } 15 | } 16 | return res; 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /1000-1099/1053-Previous-Permutation-With-One-Swap.md: -------------------------------------------------------------------------------- 1 | # 1053-Previous Permutation With One Swap 2 | 3 | [Problem](https://leetcode.com/problems/previous-permutation-with-one-swap/) 4 | 5 | ## Approach 6 | 7 | Idea: If the array is sorted ascendingly (i.e., descending backwardly), then there is no solution existing. Otherwise, iterate the array backwardly until you find the first non-decreasing number, and swap it with the left-most (in case of duplicates) largest number that is smaller than it on the right side. 8 | 9 | Time complexity: O(n). 10 | 11 | Space complexity: O(1) auxiliary space. 12 | 13 | ```c++ 14 | class Solution { 15 | public: 16 | vector prevPermOpt1(vector& A) { 17 | int i = A.size() - 1; 18 | while (i >= 1 && A[i] >= A[i - 1]) i--; 19 | if (i == 0) 20 | return A; 21 | 22 | int j = A.size() - 1; 23 | while (A[i - 1] <= A[j]) j--; 24 | while (A[j] == A[j - 1]) j--; 25 | swap(A[i - 1], A[j]); 26 | return A; 27 | } 28 | }; 29 | ``` 30 | -------------------------------------------------------------------------------- /1000-1099/1099-Two-Sum-Less-Than-K.cpp: -------------------------------------------------------------------------------- 1 | // Sort + Two Pointers 2 | // Time complexity: O(nlogn). 3 | // Space complexity: O(1) extra space. 4 | 5 | class Solution { 6 | public: 7 | int twoSumLessThanK(vector& A, int K) { 8 | if (A.size() < 2) return -1; 9 | 10 | sort(A.begin(), A.end()); 11 | 12 | int S = A[0] + A[1]; 13 | if (S >= K) return -1; 14 | 15 | int left = 0; 16 | int right = A.size() - 1; 17 | while (left < right) { 18 | int sum = A[left] + A[right]; 19 | if (sum < K) { 20 | S = max(S, sum); 21 | left++; 22 | } else { 23 | right--; 24 | } 25 | } 26 | return S; 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /1100-1199/1101-The-Earliest-Moment-When-Everyone-Become-Friends.cpp: -------------------------------------------------------------------------------- 1 | // Union-Find 2 | 3 | // Time complexit: O(N) (amortized). 4 | // Space complexity: O(N). 5 | 6 | class DisjointSet { 7 | public: 8 | DisjointSet(int N) 9 | : parent(N, -1), rank(N, 0), count{N} 10 | { 11 | for (int i = 0; i < N; i++) 12 | parent[i] = i; 13 | } 14 | 15 | int find(int x) { 16 | if (parent[x] != x) 17 | parent[x] = find(parent[x]); 18 | return parent[x]; 19 | } 20 | 21 | void merge(int x, int y) { 22 | int xroot = find(x); 23 | int yroot = find(y); 24 | 25 | if (xroot == yroot) 26 | return; 27 | 28 | if (rank[xroot] < rank[yroot]) 29 | swap(xroot, yroot); 30 | parent[yroot] = xroot; 31 | if (rank[xroot] == rank[yroot]) 32 | rank[xroot]++; 33 | count--; 34 | } 35 | 36 | int getCount() const { 37 | return count; 38 | } 39 | private: 40 | vector parent; 41 | vector rank; 42 | int count; 43 | }; 44 | 45 | class Solution { 46 | public: 47 | int earliestAcq(vector>& logs, int N) { 48 | DisjointSet ds(N); 49 | sort(logs.begin(), logs.end(), [](vector& a, vector& b) { return a[0] < b[0]; }); 50 | for (auto& log : logs) { 51 | ds.merge(log[1], log[2]); 52 | if (ds.getCount() == 1) 53 | return log[0]; 54 | } 55 | return -1; 56 | } 57 | }; 58 | -------------------------------------------------------------------------------- /1100-1199/1143-Longest-Common-Subsequence.md: -------------------------------------------------------------------------------- 1 | # 1143-Longest Common Subsequence 2 | 3 | [Problem](https://leetcode.com/problems/longest-common-subsequence/) 4 | 5 | ## Approach: Dynamic Programming 6 | 7 | Time Complexity: O(len(text1) * len(text2)). 8 | 9 | Space complexity: O(len(text1) * len(text2)). 10 | 11 | **Base Case:** 12 | 13 | LCS(i, j) = 0, if i = 0 or j = 0 14 | 15 | **Recursive structure:** 16 | 17 | LCS(i, j) = 18 | 19 | * LCS(i - 1, j - 1) + 1, if text1[i] = text2[j] 20 | 21 | * max(LCS(i - 1, j), LCS(i, j - 1)), if text1[i] != text2[j] 22 | 23 | ```c++ 24 | class Solution { 25 | public: 26 | int longestCommonSubsequence(string text1, string text2) { 27 | const int len1 = text1.size(); 28 | const int len2 = text2.size(); 29 | vector> dp(len1 + 1, vector(len2 + 1, 0)); 30 | for (int i = 1; i < len1 + 1; i++) { 31 | for (int j = 1; j < len2 + 1; j++) { 32 | if (text1[i-1] == text2[j-1]) { 33 | dp[i][j] = dp[i-1][j-1] + 1; 34 | } else { 35 | dp[i][j] = max(dp[i-1][j], dp[i][j-1]); 36 | } 37 | } 38 | } 39 | return dp[len1][len2]; 40 | } 41 | }; 42 | ``` 43 | -------------------------------------------------------------------------------- /1100-1199/1184-Distance-Between-Bus-Stops.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(1). 3 | 4 | class Solution { 5 | public: 6 | int distanceBetweenBusStops(vector& distance, int start, int destination) { 7 | const int N = distance.size(); 8 | 9 | int d1 = 0; 10 | for (int i = start; i != destination; i = (i + 1) % N) { 11 | d1 += distance[i]; 12 | } 13 | 14 | int d2 = 0; 15 | for (int i = destination; i != start; i = (i + 1) % N) { 16 | d2 += distance[i]; 17 | } 18 | 19 | return min(d1, d2); 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /1100-1199/1185-Day-of-the-Week.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(day + month + year). 2 | // Space complexity: O(1). 3 | 4 | class Solution { 5 | public: 6 | string dayOfTheWeek(int day, int month, int year) { 7 | int day_of_week = 5; 8 | 9 | for (int i = 1971; i < year; ++i) { 10 | if (i % 4 == 0) { // 2000 is leap Year, 2100 not 11 | day_of_week += 366; 12 | } else { 13 | day_of_week += 365; 14 | } 15 | day_of_week %= 7; 16 | } 17 | 18 | vector months{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 19 | if (year % 4 == 0) months[1] = 29; // 2000 is leap Year, 2100 not 20 | for (int i = 1; i < month; ++i) { 21 | day_of_week += months[i - 1]; 22 | day_of_week %= 7; 23 | } 24 | 25 | for (int i = 1; i < day; ++i) { 26 | ++day_of_week; 27 | day_of_week %= 7; 28 | } 29 | 30 | vector week_days{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; 31 | return week_days[day_of_week]; 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /1100-1199/1189-Maximum-Number-of-Balloons.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n) 2 | // Space complexity: O(1) extra space. 3 | 4 | class Solution { 5 | public: 6 | int maxNumberOfBalloons(string text) { 7 | vector cnt(5, 0); // "balon" 8 | for (char c : text) { 9 | switch (c) { 10 | case 'b': 11 | ++cnt[0]; 12 | break; 13 | case 'a': 14 | ++cnt[1]; 15 | break; 16 | case 'l': 17 | ++cnt[2]; 18 | break; 19 | case 'o': 20 | ++cnt[3]; 21 | break; 22 | case 'n': 23 | ++cnt[4]; 24 | break; 25 | } 26 | } 27 | 28 | cnt[2] /= 2; 29 | cnt[3] /= 2; 30 | 31 | int min_cnt = cnt[0]; 32 | for (int n : cnt) { 33 | min_cnt = min(n, min_cnt); 34 | } 35 | 36 | return min_cnt; 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /1200-1299/1214-Two-Sum-BSTs.cpp: -------------------------------------------------------------------------------- 1 | // Inorder Traversal of BST 2 | // Time complexity: O(n). 3 | // Space complexity: O(n). 4 | 5 | /** 6 | * Definition for a binary tree node. 7 | * struct TreeNode { 8 | * int val; 9 | * TreeNode *left; 10 | * TreeNode *right; 11 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 12 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 13 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 14 | * }; 15 | */ 16 | class Solution { 17 | public: 18 | bool twoSumBSTs(TreeNode* root1, TreeNode* root2, int target) { 19 | unordered_set s; 20 | inorder(root1, target, s); 21 | return inCheck(root2, s); 22 | } 23 | private: 24 | void inorder(TreeNode* root, int target, unordered_set& s) { 25 | if (!root) return; 26 | inorder(root->left, target, s); 27 | s.insert(target - root->val); 28 | inorder(root->right, target, s); 29 | } 30 | 31 | bool inCheck(TreeNode* root, unordered_set& s) { 32 | if (!root) return false; 33 | return inCheck(root->left, s) || s.find(root->val) != s.end() || inCheck(root->right, s); 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /1200-1299/1256-Encode-Number.cpp: -------------------------------------------------------------------------------- 1 | // Observation: the prefix of encode(num) = encode((n - 1) / 2). 2 | 3 | // Time complexity: O(logn). 4 | // Space complexity: O(logn). 5 | 6 | class Solution { 7 | public: 8 | string encode(int num) { 9 | if (num == 0) 10 | return ""; 11 | return encode((num - 1) / 2) + "10"[num % 2]; 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /1200-1299/1281-Subtract-the-Product-and-Sum-of-Digits-of-an-Integer.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(logn). 2 | // Space complexity: O(1) extra space. 3 | 4 | class Solution { 5 | public: 6 | int subtractProductAndSum(int n) { 7 | if (n == 0) 8 | return 0; 9 | 10 | int prod = 1; 11 | int sum = 0; 12 | while (n > 0) { 13 | int digit = n % 10; 14 | prod *= digit; 15 | sum += digit; 16 | n /= 10; 17 | } 18 | return prod - sum; 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /1200-1299/1289-Minimum-Falling-Path-Sum-II.cpp: -------------------------------------------------------------------------------- 1 | // Dynamic Programming 2 | // Time complexity: O(n^2). 3 | 4 | // In-place solution 5 | // Time complexity in this implementation: O(n * nlogn). 6 | // Space complexity: O(1) extra space. 7 | class Solution { 8 | public: 9 | int minFallingPathSum(vector>& arr) { 10 | int ans = 0; 11 | 12 | for (int i = 1; i < arr.size(); i++) { 13 | // not sure why I cannot create minHeap directly from a vector, 14 | // otherwise the time complexity would be O(n^2) 15 | priority_queue, std::greater> pq; 16 | for (int n : arr[i-1]) { 17 | pq.push(n); 18 | } 19 | int smallest = pq.top(); 20 | pq.pop(); 21 | int second_smallest = pq.top(); 22 | 23 | for (int j = 0; j < arr[i].size(); j++) { 24 | int minPathSum = arr[i-1][j] == smallest ? 25 | second_smallest : smallest; 26 | arr[i][j] += minPathSum; 27 | } 28 | } 29 | 30 | return *min_element(arr.back().begin(), arr.back().end()); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /1200-1299/1295-Find-Numbers-with-Even-Number-of-Digits.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(nlogm), where n = nums.length, m = max(nums[i]). 2 | // Space complexity: O(1) extra space. 3 | 4 | class Solution { 5 | public: 6 | int findNumbers(vector& nums) { 7 | int cnt = 0; 8 | for (auto num : nums) { 9 | if (numDigits(num) % 2 == 0) { 10 | cnt++; 11 | } 12 | } 13 | return cnt; 14 | } 15 | private: 16 | int numDigits(int num) { 17 | if (num == 0) 18 | return 1; 19 | 20 | int n = 0; 21 | while (num > 0) { 22 | num /= 10; 23 | n++; 24 | } 25 | return n; 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /1300-1399/1396-Design-Underground-System.cpp: -------------------------------------------------------------------------------- 1 | class UndergroundSystem { 2 | public: 3 | UndergroundSystem() { 4 | 5 | } 6 | 7 | void checkIn(int id, string stationName, int t) { 8 | record[id] = make_pair(stationName, t); 9 | } 10 | 11 | void checkOut(int id, string stationName, int t) { 12 | auto rec = record[id]; 13 | auto checkin_station = rec.first; 14 | auto checkin_time = rec.second; 15 | total_cnts[checkin_station][stationName] += 1; 16 | total_time[checkin_station][stationName] += t - checkin_time; 17 | } 18 | 19 | double getAverageTime(string startStation, string endStation) { 20 | return double(total_time[startStation][endStation]) / total_cnts[startStation][endStation]; 21 | } 22 | private: 23 | unordered_map> total_cnts; 24 | unordered_map> total_time; 25 | unordered_map> record; 26 | }; 27 | 28 | /** 29 | * Your UndergroundSystem object will be instantiated and called as such: 30 | * UndergroundSystem* obj = new UndergroundSystem(); 31 | * obj->checkIn(id,stationName,t); 32 | * obj->checkOut(id,stationName,t); 33 | * double param_3 = obj->getAverageTime(startStation,endStation); 34 | */ 35 | -------------------------------------------------------------------------------- /1400-1499/1474-Delete-N-Nodes-After-M-Nodes-of-a-Linked-List.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n) 2 | // Space complexity: O(1) extra space 3 | 4 | /** 5 | * Definition for singly-linked list. 6 | * struct ListNode { 7 | * int val; 8 | * ListNode *next; 9 | * ListNode() : val(0), next(nullptr) {} 10 | * ListNode(int x) : val(x), next(nullptr) {} 11 | * ListNode(int x, ListNode *next) : val(x), next(next) {} 12 | * }; 13 | */ 14 | class Solution { 15 | public: 16 | ListNode* deleteNodes(ListNode* head, int m, int n) { 17 | auto curr = head; 18 | while (true) { 19 | auto prev = curr; 20 | for (int i = 0; i < m; i++) { 21 | prev = curr; 22 | curr = curr->next; 23 | if (!curr) 24 | return head; 25 | } 26 | prev->next = nullptr; 27 | for (int i = 0; i < n; i++) { 28 | curr = curr->next; 29 | if (!curr) 30 | return head; 31 | } 32 | prev->next = curr; 33 | } 34 | return head; 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /1400-1499/1480-Running-Sum-of-1d-Array.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(1) extra space. 3 | 4 | class Solution { 5 | public: 6 | vector runningSum(vector& nums) { 7 | vector res(nums); 8 | for (int i = 1; i < nums.size(); i++) { 9 | res[i] += res[i - 1]; 10 | } 11 | return res; 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /1400-1499/1491-Average-Salary-Excluding-the-Minimum-and-Maximum-Salary.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n) 2 | // Space complexity: O(1) extra space 3 | 4 | class Solution { 5 | public: 6 | double average(vector& salary) { 7 | int sum = 0; 8 | int min_val = numeric_limits::max(); 9 | int max_val = numeric_limits::min(); 10 | for (auto n : salary) { 11 | sum += n; 12 | min_val = min(min_val, n); 13 | max_val = max(max_val, n); 14 | } 15 | sum -= min_val; 16 | sum -= max_val; 17 | return (double)sum / (salary.size() - 2); 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /200-299/202-Happy-Number.cpp: -------------------------------------------------------------------------------- 1 | // Hash Set Cycle-Finding 2 | // Time complexity: O(logn). 3 | // Space complexity: O(logn). 4 | class Solution1 { 5 | public: 6 | bool isHappy(int n) { 7 | unordered_set seen; 8 | while (n != 1 && seen.find(n) == seen.end()) { 9 | seen.insert(n); 10 | n = get_next(n); 11 | } 12 | return n == 1; 13 | } 14 | private: 15 | int get_next(int n) { 16 | int total_sum = 0; 17 | while (n > 0) { 18 | int d = n % 10; 19 | n /= 10; 20 | total_sum += d * d; 21 | } 22 | return total_sum; 23 | } 24 | }; 25 | 26 | // Floyd's Cycle-Finding Algorithm 27 | // Time complexity: O(logn). 28 | // Space complexity: O(1). 29 | class Solution2 { 30 | public: 31 | bool isHappy(int n) { 32 | int slow = n; 33 | int fast = get_next(n); 34 | while (fast != 1 && slow != fast) { 35 | slow = get_next(slow); 36 | fast = get_next(get_next(fast)); 37 | } 38 | return fast == 1; 39 | } 40 | private: 41 | int get_next(int n) { 42 | int total_sum = 0; 43 | while (n > 0) { 44 | int d = n % 10; 45 | n /= 10; 46 | total_sum += d * d; 47 | } 48 | return total_sum; 49 | } 50 | }; 51 | 52 | -------------------------------------------------------------------------------- /200-299/203-Remove-Linked-List-Elements.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * public class ListNode { 4 | * int val; 5 | * ListNode next; 6 | * ListNode(int x) { val = x; } 7 | * } 8 | */ 9 | class Solution { 10 | public ListNode removeElements(ListNode head, int val) { 11 | ListNode dummy_head = new ListNode(-1); 12 | dummy_head.next = head; 13 | ListNode prev = dummy_head; 14 | while (head != null) { 15 | if (head.val == val) { 16 | prev.next = head.next; 17 | } else { 18 | prev = head; 19 | } 20 | head = head.next; 21 | } 22 | return dummy_head.next; 23 | } 24 | } -------------------------------------------------------------------------------- /200-299/215-Kth-Largest-Element-in-an-Array.md: -------------------------------------------------------------------------------- 1 | # 215-Kth Largest Element in an Array 2 | 3 | [Problem](https://leetcode.com/problems/kth-largest-element-in-an-array/) 4 | 5 | ## Approach 1: Heap 6 | 7 | Use C++ STL's priority queue (effectively a heap). 8 | 9 | Time complexity: O(n + n) = O(n). 10 | 11 | Space complexity: O(n). 12 | 13 | ```c++ 14 | class Solution { 15 | public: 16 | int findKthLargest(vector& nums, int k) { 17 | priority_queue q(std::less(), nums); 18 | for (int i = 0; i < k - 1; ++i) q.pop(); 19 | return q.top(); 20 | } 21 | }; 22 | ``` 23 | -------------------------------------------------------------------------------- /200-299/217-Contains-Duplicate.cpp: -------------------------------------------------------------------------------- 1 | // Approach 1: Naive Linear Search 2 | // Time complexity: O(n^2) 3 | // Space complexity: O(1) 4 | 5 | class Solution1 { 6 | public: 7 | bool containsDuplicate(vector& nums) { 8 | for (auto i = 0; i < nums.size(); ++i) { 9 | for (auto j = 0; j < i; ++j) { 10 | if (nums[i] == nums[j]) return true; 11 | } 12 | } 13 | return false; 14 | } 15 | }; 16 | 17 | // Approach 2: Sorting 18 | // Time complexity: O(nlogn) 19 | // Space complexity: O(1) or O(n) 20 | 21 | class Solution2 { 22 | public: 23 | bool containsDuplicate(vector& nums) { 24 | if (nums.empty()) return false; 25 | 26 | sort(nums.begin(), nums.end()); 27 | for (auto i = 0; i < nums.size() - 1; ++i) { 28 | if (nums[i] == nums[i + 1]) return true; 29 | } 30 | return false; 31 | } 32 | }; 33 | 34 | // Approach 3: Hash Set 35 | // Time complexity: O(n) 36 | // Space complexity: O(n) 37 | 38 | class Solution3 { 39 | public: 40 | bool containsDuplicate(vector& nums) { 41 | unordered_set s; 42 | for (auto num : nums) { 43 | if (s.find(num) != s.end()) return true; 44 | s.insert(num); 45 | } 46 | return false; 47 | } 48 | }; 49 | -------------------------------------------------------------------------------- /200-299/219-Contains-Duplicate-II.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n) 2 | // Space complexity: O(n) 3 | 4 | class Solution { 5 | public: 6 | bool containsNearbyDuplicate(vector& nums, int k) { 7 | unordered_map m; 8 | for (auto i = 0; i < nums.size(); ++i) { 9 | auto found = m.find(nums[i]); 10 | if (found != m.end()) { 11 | if (abs(found->second - i) <= k) return true; 12 | found->second = i; 13 | } else { 14 | m.insert({nums[i], i}); 15 | } 16 | } 17 | return false; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /200-299/223-Rectangle-Area.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(1) 2 | // Space complexity: O(1) 3 | 4 | class Solution { 5 | public: 6 | int computeArea(int A, int B, int C, int D, int E, int F, int G, int H) { 7 | long total = long{C-A} * long{D-B} + long{G-E} * long{H-F}; 8 | 9 | if (C <= E || A >= G || B >= H || D <= F) { 10 | return total; 11 | } else { 12 | vector h{A, C, E, G}; 13 | vector v{B, D, F, H}; 14 | sort(h.begin(), h.end()); 15 | sort(v.begin(), v.end()); 16 | total -= long{h[2] - h [1]} * long{v[2] - v[1]}; 17 | return total; 18 | } 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /200-299/228-Summary-Ranges.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n) 2 | // Space complexity: O(n), no additional space overhead besides the return valus 3 | 4 | class Solution { 5 | public: 6 | vector summaryRanges(vector& nums) { 7 | const int N = nums.size(); 8 | vector ranges; 9 | 10 | int left = 0; 11 | int right = 0; 12 | while (right < N) { 13 | while (right + 1 < N && nums[right + 1] == nums[right] + 1) ++right; 14 | 15 | string range{to_string(nums[left])}; 16 | if (left != right) { 17 | range += "->"; 18 | range += to_string(nums[right]); 19 | } 20 | ranges.push_back(range); 21 | 22 | left = right + 1; 23 | right = left; 24 | } 25 | 26 | return ranges; 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /200-299/234-Palindrome-Linked-List.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(1). 3 | 4 | /** 5 | * Definition for singly-linked list. 6 | * struct ListNode { 7 | * int val; 8 | * ListNode *next; 9 | * ListNode(int x) : val(x), next(NULL) {} 10 | * }; 11 | */ 12 | class Solution { 13 | public: 14 | bool isPalindrome(ListNode* head) { 15 | // Reverse the first half list 16 | ListNode *reverse = nullptr, *slow = head, *fast = head; 17 | while (fast && fast->next) { 18 | fast = fast->next->next; // must before slow->next is changed 19 | auto slow_next_tmp = slow->next; 20 | slow->next = reverse; 21 | reverse = slow; 22 | slow = slow_next_tmp; 23 | } 24 | 25 | if (fast) slow = slow->next; // if odd num of elements, jump over the center 26 | 27 | // Compare the two half 28 | while (reverse && slow) { 29 | if (reverse->val != slow->val) { 30 | return false; 31 | } 32 | reverse = reverse->next; 33 | slow = slow->next; 34 | } 35 | 36 | return true; 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /200-299/235-Lowest-Common-Ancestor-of-a-Binary-Search-Tree.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(h). 2 | // Space complexity: O(h) extra space. 3 | 4 | /** 5 | * Definition for a binary tree node. 6 | * struct TreeNode { 7 | * int val; 8 | * TreeNode *left; 9 | * TreeNode *right; 10 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 11 | * }; 12 | */ 13 | class Solution { 14 | public: 15 | TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { 16 | assert(p && q); 17 | 18 | if (p->val < q->val) { 19 | return lowestCommonAncestorHelper(root, p->val, q->val); 20 | } else { 21 | return lowestCommonAncestorHelper(root, q->val, p->val); 22 | } 23 | 24 | return nullptr; 25 | } 26 | private: 27 | TreeNode* lowestCommonAncestorHelper(TreeNode* root, int small, int large) { 28 | if (!root) return nullptr; 29 | 30 | int val = root->val; 31 | if (small <= val && large >= val) { 32 | return root; 33 | } 34 | if (small > val) { 35 | return lowestCommonAncestorHelper(root->right, small, large); 36 | } 37 | if (large < val) { 38 | return lowestCommonAncestorHelper(root->left, small, large); 39 | } 40 | 41 | return nullptr; 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /200-299/236-Lowest-Common-Ancestor-of-a-Binary-Tree.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(n) extra space. 3 | 4 | /** 5 | * Definition for a binary tree node. 6 | * struct TreeNode { 7 | * int val; 8 | * TreeNode *left; 9 | * TreeNode *right; 10 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 11 | * }; 12 | */ 13 | class Solution { 14 | public: 15 | TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { 16 | DFS(root, p, q); 17 | return answer; 18 | } 19 | private: 20 | TreeNode* answer; 21 | 22 | bool DFS(TreeNode* curr, TreeNode* p, TreeNode* q) { 23 | if (!curr) { 24 | return false; 25 | } 26 | 27 | int left = DFS(curr->left, p, q) ? 1 : 0; 28 | int right = DFS(curr->right, p, q) ? 1 : 0; 29 | int mid = (curr == p || curr == q) ? 1 : 0; 30 | if (mid + left + right >= 2) { 31 | answer = curr; 32 | } 33 | 34 | return (mid + left + right > 0); 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /200-299/237-Delete-Node-in-a-Linked-List.md: -------------------------------------------------------------------------------- 1 | # 237-Delete Node in a Linked List 2 | 3 | [Problem](https://leetcode.com/problems/delete-node-in-a-linked-list/) 4 | 5 | ## Approach 6 | 7 | We want to delete a node (except the tail) in a singly linked list. However, we are given only access to that node and we do not know the node before it. We can replace its value with the value of the node after it, and then make it directly point to the node after the node after it. 8 | 9 | Time complexity: O(1). 10 | 11 | Space complexity: O(1). 12 | 13 | ```c++ 14 | /** 15 | * Definition for singly-linked list. 16 | * struct ListNode { 17 | * int val; 18 | * ListNode *next; 19 | * ListNode(int x) : val(x), next(NULL) {} 20 | * }; 21 | */ 22 | class Solution { 23 | public: 24 | void deleteNode(ListNode* node) { 25 | node->val = node->next->val; 26 | node->next = node->next->next; 27 | } 28 | }; 29 | ``` 30 | -------------------------------------------------------------------------------- /200-299/240-Search-a-2D-Matrix-II.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public boolean searchMatrix(int[][] matrix, int target) { 3 | // corner case 4 | if (matrix == null || matrix.length == 0 || matrix[0].length == 0) 5 | return false; 6 | 7 | // start searching at the top-right corner 8 | int m = matrix.length, n = matrix[0].length; 9 | int r = 0, c = n - 1; 10 | while (r <= m - 1 && c >= 0) { 11 | if (target > matrix[r][c]) 12 | r++; 13 | else if (target < matrix[r][c]) 14 | c--; 15 | else 16 | return true; 17 | } 18 | return false; 19 | } 20 | } -------------------------------------------------------------------------------- /200-299/242-Valid-Anagram.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(1) extra space. 3 | 4 | class Solution { 5 | public: 6 | bool isAnagram(string s, string t) { 7 | if (s.size() != t.size()) return false; 8 | 9 | unordered_map m; 10 | for (char ch : s) ++m[ch]; 11 | for (char ch : t) { 12 | if (--m[ch] < 0) return false; 13 | } 14 | return true; 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /200-299/243-Shortest-Word-Distance.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(1). 3 | 4 | class Solution { 5 | public: 6 | int shortestDistance(vector& words, string word1, string word2) { 7 | int ans = words.size(); 8 | int pos1 = -1; 9 | int pos2 = -1; 10 | for (int i = 0; i < words.size(); i++) { 11 | if (words[i] == word1) { 12 | pos1 = i; 13 | if (pos2 >= 0) { 14 | ans = min(ans, pos1 - pos2); 15 | } 16 | } else if (words[i] == word2) { 17 | pos2 = i; 18 | if (pos1 >= 0) { 19 | ans = min(ans, pos2 - pos1); 20 | } 21 | } 22 | } 23 | 24 | return ans; 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /200-299/244-Shortest-Word-Distance-II.cpp: -------------------------------------------------------------------------------- 1 | // Init: O(n). 2 | // shortest: O(n). 3 | // Space complexity: O(n). 4 | 5 | class WordDistance { 6 | public: 7 | WordDistance(vector& words) { 8 | for (int i = 0; i < words.size(); i++) { 9 | locations[words[i]].push_back(i); 10 | } 11 | } 12 | 13 | int shortest(string word1, string word2) { 14 | auto loc1 = locations[word1]; 15 | auto loc2 = locations[word2]; 16 | 17 | int i = 0; 18 | int j = 0; 19 | int min_diff = numeric_limits::max(); 20 | while (i < loc1.size() && j < loc2.size()) { 21 | min_diff = min(min_diff, abs(loc1[i] - loc2[j])); 22 | if (loc1[i] < loc2[j]) { 23 | i++; 24 | } else { 25 | j++; 26 | } 27 | } 28 | return min_diff; 29 | } 30 | private: 31 | unordered_map> locations; 32 | }; 33 | 34 | /** 35 | * Your WordDistance object will be instantiated and called as such: 36 | * WordDistance* obj = new WordDistance(words); 37 | * int param_1 = obj->shortest(word1,word2); 38 | */ 39 | -------------------------------------------------------------------------------- /200-299/245-Shortest-Word-Distance-III.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(1). 3 | 4 | class Solution { 5 | public: 6 | int shortestWordDistance(vector& words, string word1, string word2) { 7 | if (word1 == word2) { 8 | int prev = -1; 9 | int curr = -1; 10 | int min_diff = words.size(); 11 | for (int i = 0; i < words.size(); i++) { 12 | if (words[i] == word1) { 13 | if (curr == -1) { 14 | curr = i; 15 | } else { 16 | prev = curr; 17 | curr = i; 18 | min_diff = min(min_diff, curr - prev); 19 | } 20 | } 21 | } 22 | return min_diff; 23 | } 24 | 25 | int ans = words.size(); 26 | int pos1 = -1; 27 | int pos2 = -1; 28 | for (int i = 0; i < words.size(); i++) { 29 | if (words[i] == word1) { 30 | pos1 = i; 31 | if (pos2 >= 0) { 32 | ans = min(ans, pos1 - pos2); 33 | } 34 | } else if (words[i] == word2) { 35 | pos2 = i; 36 | if (pos1 >= 0) { 37 | ans = min(ans, pos2 - pos1); 38 | } 39 | } 40 | } 41 | 42 | return ans; 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /200-299/246-Strobogrammatic-Number.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(1). 3 | 4 | class Solution { 5 | public: 6 | bool isStrobogrammatic(string num) { 7 | unordered_map m{{'0', '0'}, {'1', '1'}, {'6', '9'}, {'8', '8'}, {'9', '6'}}; 8 | for (int l = 0, r = num.size() - 1; l <= r; l++, r--) { 9 | if (m.find(num[l]) == m.end() || m[num[l]] != num[r]) { 10 | return false; 11 | } 12 | } 13 | return true; 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /200-299/249-Group-Shifted-Strings.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n), n = #chars in strings. 2 | // Space complexity: O(n). 3 | 4 | class Solution { 5 | public: 6 | vector> groupStrings(vector& strings) { 7 | unordered_map> m; 8 | for (const auto& str : strings) 9 | m[shift(str)].push_back(str); 10 | 11 | vector> groups; 12 | for (auto p : m) { 13 | groups.push_back(p.second); 14 | } 15 | return groups; 16 | } 17 | private: 18 | string shift(const string& str) { 19 | string res; 20 | char c = str[0]; 21 | for (int i = 1; i < str.length(); i++) { 22 | int diff = str[i] - c; 23 | if (diff < 0) diff += 26; 24 | res += 'a' + diff; 25 | } 26 | return res; 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /200-299/250-Count-Univalue-Subtrees.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * struct TreeNode { 4 | * int val; 5 | * TreeNode *left; 6 | * TreeNode *right; 7 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 8 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 9 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 10 | * }; 11 | */ 12 | 13 | // Approach: DFS 14 | // Time complexity: O(n). 15 | // Space complexity: O(h) extra space. 16 | 17 | class Solution { 18 | public: 19 | int countUnivalSubtrees(TreeNode* root) { 20 | return countUnivalSubtreesHelper(root).first; 21 | } 22 | private: 23 | pair countUnivalSubtreesHelper(TreeNode* root) { 24 | if (!root) { 25 | return {0, true}; 26 | } 27 | 28 | int count = 0; 29 | bool isUnivalSubtree = false; 30 | auto left = countUnivalSubtreesHelper(root->left); 31 | auto right = countUnivalSubtreesHelper(root->right); 32 | 33 | count += left.first + right.first; 34 | if (left.second && right.second && 35 | (!root->left || root->val == root->left->val) && 36 | (!root->right || root->val == root->right->val)) { 37 | count += 1; 38 | isUnivalSubtree = true; 39 | } 40 | 41 | return {count, isUnivalSubtree}; 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /200-299/252-Meeting-Rooms.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(nlogn). 2 | // Space complexity: O(1) extra space. 3 | 4 | class Solution { 5 | public: 6 | bool canAttendMeetings(vector>& intervals) { 7 | sort(intervals.begin(), intervals.end(), 8 | [](vector& a, vector& b) { return a.front() < b.front(); }); 9 | for (int i = 1; i < intervals.size(); i++) { 10 | if (intervals[i - 1].back() > intervals[i].front()) 11 | return false; 12 | } 13 | return true; 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /200-299/253-Meeting-Rooms-II.cpp: -------------------------------------------------------------------------------- 1 | // Simulate real-life situation: 2 | // when new meeting comes, check if there is already meeting finished to have its room reused 3 | // if not, add more room. 4 | // Time complexity: O(nlogn). 5 | // Space complexity: O(n) extra space. 6 | 7 | class Solution { 8 | public: 9 | int minMeetingRooms(vector>& intervals) { 10 | if (intervals.empty()) return 0; 11 | 12 | sort(intervals.begin(), intervals.end(), [](vector& a, vector& b) { 13 | return a.front() < b.front(); 14 | }); 15 | 16 | std::priority_queue, std::greater> q_end_times; 17 | q_end_times.push(intervals[0].back()); 18 | for (int i = 1; i < intervals.size(); i++) { 19 | if (intervals[i].front() >= q_end_times.top()) 20 | q_end_times.pop(); // the room is ready to be reused 21 | q_end_times.push(intervals[i].back()); // update end time 22 | } 23 | return q_end_times.size(); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /200-299/256-Paint-House.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(1). 3 | 4 | class Solution { 5 | public: 6 | int minCost(vector>& costs) { 7 | if (costs.empty()) 8 | return 0; 9 | for (int i = 1; i < costs.size(); i++) { 10 | vector& prev_cost = costs[i-1]; 11 | costs[i][0] += min(prev_cost[1], prev_cost[2]); 12 | costs[i][1] += min(prev_cost[0], prev_cost[2]); 13 | costs[i][2] += min(prev_cost[0], prev_cost[1]); 14 | } 15 | return *min_element(costs.back().begin(), costs.back().end()); 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /200-299/257-Binary-Tree-Paths.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). Visited each node once. 2 | // Space complexity: O(n^2). At most O(2^(logn)) = O(n) paths, each path has at most O(n) nodes. 3 | 4 | /** 5 | * Definition for a binary tree node. 6 | * struct TreeNode { 7 | * int val; 8 | * TreeNode *left; 9 | * TreeNode *right; 10 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 11 | * }; 12 | */ 13 | class Solution { 14 | public: 15 | vector binaryTreePaths(TreeNode* root) { 16 | vector paths; 17 | if (!root) { 18 | return paths; 19 | } 20 | 21 | string intermediate; 22 | binaryTreePathsRecu(root, intermediate, paths); 23 | 24 | return paths; 25 | } 26 | private: 27 | void binaryTreePathsRecu(TreeNode* root, string& intermediate, vector& paths) { 28 | if (!root->left && !root->right) { 29 | string new_intermediate = intermediate + to_string(root->val); 30 | paths.push_back(new_intermediate); 31 | } else { 32 | string new_intermediate = intermediate + to_string(root->val) + "->"; 33 | if (root->left) { 34 | binaryTreePathsRecu(root->left, new_intermediate, paths); 35 | } 36 | if (root->right) { 37 | binaryTreePathsRecu(root->right, new_intermediate, paths); 38 | } 39 | } 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /200-299/258-Add-Digits.cpp: -------------------------------------------------------------------------------- 1 | // Math 2 | // Time complexity: O(1). 3 | // Space complexity: O(1). 4 | 5 | class Solution { 6 | public: 7 | int addDigits(int num) { 8 | if (num == 0) return 0; 9 | if (num % 9 == 0) return 9; 10 | return num % 9; 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /200-299/259-3Sum-Smaller.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n^2). 2 | // Space complexity: O(1) extra space. 3 | 4 | class Solution { 5 | public: 6 | int threeSumSmaller(vector& nums, int target) { 7 | if (nums.size() < 3) return 0; 8 | 9 | sort(nums.begin(), nums.end()); 10 | int ans = 0; 11 | 12 | for (int i = 0; i < nums.size() - 2; i++) { 13 | int left = i + 1; 14 | int right = nums.size() - 1; 15 | while (left < right) { 16 | int sum = nums[i] + nums[left] + nums[right]; 17 | if (sum >= target) { 18 | right--; 19 | } else { 20 | ans += right - left; // Notice: KEY POINT! 21 | left++; 22 | } 23 | } 24 | } 25 | 26 | return ans; 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /200-299/263-Ugly-Number.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(logn). 2 | // Space complexity: O(1). 3 | 4 | class Solution { 5 | public: 6 | bool isUgly(int num) { 7 | if (num <= 0) { 8 | return false; 9 | } 10 | 11 | while (num % 2 == 0) { 12 | num /= 2; 13 | } 14 | while (num % 3 == 0) { 15 | num /= 3; 16 | } 17 | while (num % 5 == 0) { 18 | num /= 5; 19 | } 20 | return (num == 1); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /200-299/264-Ugly-Number-II.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(nlogn). 2 | // Space complexity: O(n). 3 | 4 | class Solution { 5 | public: 6 | int nthUglyNumber(int n) { 7 | if (n <= 6) { 8 | return n; 9 | } 10 | 11 | long curr = 0; 12 | set s; 13 | s.insert(1); 14 | for (int i = 0; i < n; i++) { 15 | curr = *(s.begin()); 16 | s.erase(s.begin()); 17 | s.insert(curr * 2); 18 | s.insert(curr * 3); 19 | s.insert(curr * 5); 20 | } 21 | return curr; 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /200-299/265-Paint-House-II.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(nk). 2 | // Space complexity: O(1). 3 | 4 | class Solution { 5 | public: 6 | int minCostII(vector>& costs) { 7 | const int n = costs.size(); 8 | if (n == 0) 9 | return 0; 10 | 11 | const int k = costs[0].size(); 12 | if (k == 0) 13 | return 0; 14 | if (k == 1) { 15 | if (n == 1) 16 | return costs[0][0]; 17 | return 0; 18 | } 19 | 20 | // precondition: n >= 1 && k >= 2 21 | for (int i = 1; i < n; i++) { 22 | vector& prev_cost = costs[i-1]; 23 | 24 | // find min and second_min of prev_cost 25 | int min = numeric_limits::max(); 26 | int second_min = min; 27 | for (auto n : prev_cost) { 28 | if (n < min) { 29 | second_min = min; 30 | min = n; 31 | } else if (n < second_min) { 32 | second_min = n; 33 | } 34 | } 35 | 36 | for (int j = 0; j < k; j++) { 37 | costs[i][j] += (prev_cost[j] == min ? second_min : min); 38 | } 39 | } 40 | 41 | return *min_element(costs.back().begin(), costs.back().end()); 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /200-299/266-Palindrome-Permutation.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(1). Depends on the size of character set, but it is a constant. 3 | 4 | class Solution { 5 | public: 6 | bool canPermutePalindrome(string s) { 7 | unordered_map m; 8 | for (auto c : s) { 9 | m[c]++; 10 | } 11 | int cnt_of_odds = 0; 12 | for (auto p : m) { 13 | if (m[p.first] % 2 == 1) { 14 | cnt_of_odds++; 15 | } 16 | } 17 | return cnt_of_odds <= 1; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /200-299/268-Missing-Number.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(1). 3 | 4 | class Solution1 { 5 | public: 6 | int missingNumber(vector& nums) { 7 | const int n = static_cast(nums.size()); 8 | int sum = (0 + n) * (n + 1) / 2; 9 | for (auto num : nums) { 10 | sum -= num; 11 | } 12 | return sum; 13 | } 14 | }; 15 | 16 | class Solution2 { 17 | public: 18 | int missingNumber(vector& nums) { 19 | const int n = static_cast(nums.size()); 20 | int sum = (0 + n) * (n + 1) / 2; 21 | int vector_sum = accumulate(nums.begin(), nums.end(), 0); 22 | return sum - vector_sum; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /200-299/276-Paint-Fence.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(n). 3 | 4 | class Solution { 5 | public: 6 | int numWays(int n, int k) { 7 | if (n == 0) return 0; 8 | if (n == 1) return k; 9 | if (n == 2) return k * k; 10 | 11 | vectordp(n, 0); 12 | dp[0] = k; 13 | dp[1] = k * k; 14 | for (int i = 2; i < n; i++) 15 | dp[i] = (k - 1) * (dp[i - 1] + dp[i - 2]); 16 | 17 | return dp.back(); 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /200-299/278-First-Bad-Version.cpp: -------------------------------------------------------------------------------- 1 | // Binary Search 2 | // Time complexity: O(logn). 3 | // Space complexity: O(1). 4 | 5 | // The API isBadVersion is defined for you. 6 | // bool isBadVersion(int version); 7 | 8 | class Solution { 9 | public: 10 | int firstBadVersion(int n) { 11 | int lo = 1; 12 | int hi = n; 13 | while (lo < hi) { 14 | int mid = lo + (hi - lo) / 2; 15 | if (isBadVersion(mid)) { 16 | hi = mid; 17 | } else { 18 | lo = mid + 1; 19 | } 20 | } 21 | return lo; 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /200-299/279-Perfect-Squares.md: -------------------------------------------------------------------------------- 1 | # 279-Perfect Squares 2 | 3 | ## Approach: Dynamic Programming 4 | 5 | Recursive structure: 6 | 7 | * numSquares(0) = 0 8 | * numSquares(n) = min(numSquares(n-k) + 1 for any square number k) 9 | 10 | Time complexity: O(n x sqrt(n)). 11 | 12 | Space complexity: O(n). 13 | 14 | ```c++ 15 | class Solution { 16 | public: 17 | int numSquares(int n) { 18 | vector dp(n + 1, numeric_limits::max()); 19 | dp[0] = 0; 20 | 21 | // precalculate the square numbers 22 | vector square_nums{0}; 23 | for (int i = 1; i * i <= n; i++) { 24 | square_nums.push_back(i * i); 25 | } 26 | 27 | for (int i = 0; i <= n; i++) { 28 | for (int s = 1; s * s <= n; s++) { 29 | if (i >= square_nums[s]) { 30 | dp[i] = min(dp[i], dp[i - square_nums[s]] + 1); 31 | } 32 | } 33 | } 34 | return dp[n]; 35 | } 36 | }; 37 | ``` 38 | -------------------------------------------------------------------------------- /200-299/283-Move-Zeroes.md: -------------------------------------------------------------------------------- 1 | # 283-Move Zeroes 2 | 3 | [Problem](https://leetcode.com/problems/move-zeroes/) 4 | 5 | ## Approach 1 6 | 7 | Invariants maintained: 8 | 9 | * All elements before the slow pointer (left) are non-zeroes. 10 | * All elements between the current (right) and slow pointer are zeroes. 11 | 12 | Time complexity: O(n^2). 13 | 14 | Space complexity: O(1). 15 | 16 | ```c++ 17 | class Solution { 18 | public: 19 | void moveZeroes(vector& nums) { 20 | const int n = nums.size(); 21 | 22 | int left{0}; 23 | int right{0}; 24 | 25 | while (right < n) { 26 | while (left < n && nums[left] != 0) { 27 | left++; 28 | } 29 | right = left; 30 | while (right < n && nums[right] == 0) { 31 | right++; 32 | } 33 | if (left != right && right < n) { 34 | swap(nums[left], nums[right]); 35 | } 36 | } 37 | } 38 | }; 39 | ``` 40 | 41 | ## Approach 2: Optimized 42 | 43 | Same invariants maintained. 44 | 45 | Time complexity: O(n). 46 | 47 | Space complexity: O(1). 48 | 49 | ```c++ 50 | class Solution { 51 | public: 52 | void moveZeroes(vector& nums) { 53 | int left = 0; 54 | int right = 0; 55 | while (right < nums.size()) { 56 | if (nums[right] != 0) { 57 | swap(nums[left], nums[right]); 58 | left++; 59 | } 60 | right++; 61 | } 62 | } 63 | }; 64 | ``` 65 | -------------------------------------------------------------------------------- /200-299/286-Walls-and-Gates.cpp: -------------------------------------------------------------------------------- 1 | // BFS 2 | // Time complexity: O(mn). 3 | // Space complexity: O(mn). 4 | 5 | class Solution { 6 | public: 7 | void wallsAndGates(vector>& rooms) { 8 | const int M = rooms.size(); 9 | if (M == 0) return; 10 | const int N = rooms[0].size(); 11 | 12 | const int GATE = 0; 13 | const int EMPTY = numeric_limits::max(); 14 | const vector> DIRECTIONS{ 15 | {1, 0}, 16 | {-1, 0}, 17 | {0, 1}, 18 | {0, -1} 19 | }; 20 | 21 | queue> q; 22 | for (int i = 0; i < M; i++) { 23 | for (int j = 0; j < N; j++) { 24 | if (rooms[i][j] == GATE) { 25 | q.push({i, j}); 26 | } 27 | } 28 | } 29 | 30 | while (!q.empty()) { 31 | auto pos = q.front(); 32 | q.pop(); 33 | int row = pos[0]; 34 | int col = pos[1]; 35 | for (const auto& dir : DIRECTIONS) { 36 | int r = row + dir[0]; 37 | int c = col + dir[1]; 38 | if (r >= 0 && c >= 0 && r < M && c < N && rooms[r][c] == EMPTY) { 39 | rooms[r][c] = rooms[row][col] + 1; 40 | q.push({r, c}); 41 | } 42 | } 43 | } 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /300-399/303-Range-Sum-Query---Immutable.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity : O(1) time per query, O(n) time pre-computation (the cumulative sum is cached). 2 | // Space complexity : O(n). 3 | 4 | Space complexity : O(n)O(n). 5 | class NumArray { 6 | public: 7 | NumArray(vector& nums) { 8 | accumulate.push_back(0); 9 | for (auto i = 1; i < nums.size() + 1; ++i) { 10 | accumulate.push_back(accumulate[i - 1] + nums[i - 1]); 11 | } 12 | } 13 | 14 | int sumRange(int i, int j) { 15 | return accumulate[j + 1] - accumulate[i]; 16 | } 17 | private: 18 | vector accumulate; 19 | }; 20 | 21 | /** 22 | * Your NumArray object will be instantiated and called as such: 23 | * NumArray* obj = new NumArray(nums); 24 | * int param_1 = obj->sumRange(i,j); 25 | */ 26 | -------------------------------------------------------------------------------- /300-399/304-Range-Sum-Query-2D---Immutable.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity : O(1) time per query, O(mn) time pre-computation (the cumulative sum is cached). 2 | // Space complexity : O(mn). 3 | 4 | class NumMatrix { 5 | public: 6 | NumMatrix(vector>& matrix) { 7 | if (matrix.size() == 0 || matrix[0].size() == 0) return; 8 | 9 | dp = vector>(matrix.size() + 1, vector(matrix[0].size() + 1, 0)); 10 | for (int r = 0; r < matrix.size(); r++) { 11 | for (int c = 0; c < matrix[0].size(); c++) { 12 | dp[r + 1][c + 1] = dp[r + 1][c] + dp[r][c + 1] - dp[r][c] + matrix[r][c]; 13 | } 14 | } 15 | } 16 | 17 | int sumRegion(int row1, int col1, int row2, int col2) { 18 | return dp[row2 + 1][col2 + 1] - dp[row1][col2 + 1] - dp[row2 + 1][col1] + dp[row1][col1]; 19 | } 20 | private: 21 | vector> dp; 22 | }; 23 | 24 | /** 25 | * Your NumMatrix object will be instantiated and called as such: 26 | * NumMatrix* obj = new NumMatrix(matrix); 27 | * int param_1 = obj->sumRegion(row1,col1,row2,col2); 28 | */ 29 | -------------------------------------------------------------------------------- /300-399/319-Bulb-Switcher.cpp: -------------------------------------------------------------------------------- 1 | // Simulation 2 | // Time complexity: O(N^2). 3 | // Space complexity: O(N). 4 | class Solution1 { 5 | public: 6 | int bulbSwitch(int n) { 7 | vector bulbs(n, -1); 8 | for (int i = 0; i < n; i++) { 9 | for (int j = i; j < n; j += i + 1) { 10 | bulbs[j] *= -1; 11 | } 12 | } 13 | return count(bulbs.begin(), bulbs.end(), 1); 14 | } 15 | }; 16 | 17 | // Math 18 | // Time complexity: O(logN) for computing sqrt. 19 | // Space complexity: O(1). 20 | 21 | /* 22 | * Explanation: 23 | * Bulb i is switched in round d if and only if d divides i. 24 | * So bulb i ends up on if and only if it has an odd number of divisors. 25 | * Divisors come in pairs, a number n has an odd number of divisors i.f.f. n is a square number. 26 | * So bulb i ends up on if and only if i is a square. 27 | * So just count the square numbers, and result is int(sqrt(N)). 28 | */ 29 | 30 | class Solution2 { 31 | public: 32 | int bulbSwitch(int n) { 33 | return sqrt(n); 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /300-399/326-Power-of-Three.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(log_3(n)) 2 | // Space complexity: O(1) (by tail call optimization) 3 | 4 | class Solution1 { 5 | public: 6 | bool isPowerOfThree(int n) { 7 | if (n == 1) return true; 8 | if (n < 1 || n % 3 > 0) return false; 9 | 10 | return isPowerOfThree(n / 3); 11 | } 12 | }; 13 | 14 | // Another interesting solution 15 | 16 | // n is 32-bit signed int. 17 | // Knowing the limitation of n, we can now deduce that the maximum value of n 18 | // that is also a power of three is 116226146 = 3^19. 19 | // All of its factors are power of three. 20 | 21 | class Solution2 { 22 | public: 23 | bool isPowerOfThree(int32_t n) { 24 | return n > 0 && 1162261467 % n == 0; 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /300-399/338-Counting-Bits.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n) 2 | // Space complexity: O(n) 3 | 4 | // Key observation: 5 | // whenever one more "1" is added in the front, the rest of the bits restart from all zeros to all ones 6 | 7 | class Solution { 8 | public: 9 | vector countBits(int num) { 10 | assert(num >= 0); 11 | 12 | vector result; 13 | result.reserve(num); 14 | result.push_back(0); 15 | 16 | int exp = 1; 17 | while (exp <= num) { 18 | for (auto i = 0; i < exp && exp + i <= num; ++i) { 19 | result.push_back(1 + result[i]); 20 | } 21 | exp *= 2; 22 | } 23 | 24 | return result; 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /300-399/340-Longest-Substring-with-At-Most-K-Distinct-Characters.cpp: -------------------------------------------------------------------------------- 1 | // Sliding Window 2 | 3 | // Time complexity: O(N). 4 | // Extra space complexity: O(K) if we erase the element when shrinking the sliding window, otherwise O(N) 5 | 6 | class Solution { 7 | public: 8 | int lengthOfLongestSubstringKDistinct(string s, int k) { 9 | int n = s.size(); 10 | if (n * k == 0) return 0; 11 | 12 | int max_len = 0; 13 | int cnt_distinct = 0; 14 | int left = 0, right = 0; 15 | unordered_map m; 16 | 17 | while (right < n) { 18 | if (++m[s[right]] == 1) ++cnt_distinct; 19 | ++right; 20 | 21 | while (cnt_distinct > k) { 22 | if (--m[s[left]] == 0) --cnt_distinct; 23 | ++left; 24 | } 25 | 26 | max_len = max(right - left, max_len); 27 | } 28 | 29 | return max_len; 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /300-399/342-Power-of-Four.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(logn). 2 | // Space complexity: O(1). 3 | 4 | class Solution { 5 | public: 6 | bool isPowerOfFour(int num) { 7 | if (num == 1) return true; 8 | if (num % 4 != 0) return false; 9 | 10 | int one_fourth_num = num / 4; // avoid overflow 11 | int power_of_four = 1; 12 | while (power_of_four < one_fourth_num) { 13 | power_of_four *= 4; 14 | } 15 | return (power_of_four == one_fourth_num); 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /300-399/344-Reverse-String.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(1) extra space. 3 | 4 | class Solution { 5 | public: 6 | void reverseString(vector& s) { 7 | const int N = s.size(); 8 | for (int i = 0; i < N / 2; ++i) { 9 | swap(s[i], s[N - 1 - i]); 10 | } 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /300-399/346-Moving-Average-from-Data-Stream.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(1) for next. 2 | // Space complexity: O(qsize) extra space. 3 | 4 | class MovingAverage { 5 | public: 6 | /** Initialize your data structure here. */ 7 | MovingAverage(int size) : sum(0), qsize(size) { } 8 | 9 | double next(int val) { 10 | q.push(val); 11 | sum += val; 12 | if (q.size() > qsize) { 13 | sum -= q.front(); 14 | q.pop(); 15 | } 16 | return static_cast(sum) / q.size(); 17 | } 18 | private: 19 | int sum; 20 | int qsize; 21 | queue q; 22 | }; 23 | 24 | /** 25 | * Your MovingAverage object will be instantiated and called as such: 26 | * MovingAverage* obj = new MovingAverage(size); 27 | * double param_1 = obj->next(val); 28 | */ 29 | -------------------------------------------------------------------------------- /300-399/347-Top-K-Frequent-Elements.md: -------------------------------------------------------------------------------- 1 | # 347-Top K Frequent Elements 2 | 3 | ## Approach 1: Heap 4 | 5 | Time complexity: O(nlogk). 6 | 7 | Space complexity: O(n + k). 8 | 9 | ```c++ 10 | class Solution { 11 | public: 12 | vector topKFrequent(vector& nums, int k) { 13 | unordered_map m; 14 | for (int n : nums) { 15 | m[n]++; 16 | } 17 | 18 | auto cmp = [&m](const pair& a, const pair& b) { return a.second > b.second; }; 19 | priority_queue, vector>, decltype(cmp)> pq(cmp); 20 | for (const auto& entry : m) { 21 | pq.push(entry); 22 | if (pq.size() > k) pq.pop(); 23 | } 24 | 25 | vector res; 26 | for (int i = 0; i < k; i++) { 27 | res.push_back(pq.top().first); 28 | pq.pop(); 29 | } 30 | return res; 31 | } 32 | }; 33 | ``` 34 | 35 | ## Approach 2: Quick Select 36 | 37 | TODO 38 | -------------------------------------------------------------------------------- /300-399/349-Intersection-of-Two-Arrays.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n + m). 2 | // Space complexity: O(n + m). 3 | 4 | class Solution { 5 | public: 6 | vector intersection(vector& nums1, vector& nums2) { 7 | unordered_set s1; 8 | for (int num : nums1) s1.insert(num); 9 | unordered_set s2; 10 | for (int num : nums2) s2.insert(num); 11 | 12 | return set_intersection(s1, s2); 13 | } 14 | private: 15 | vector set_intersection(unordered_set s1, unordered_set s2) { 16 | vector intersection; 17 | 18 | for (int e : s1) { 19 | auto found = s2.find(e); 20 | if (found != s2.end()) { 21 | intersection.push_back(e); 22 | } 23 | } 24 | 25 | return intersection; 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /300-399/366-Find-Leaves-of-Binary-Tree.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(1).. 3 | 4 | /** 5 | * Definition for a binary tree node. 6 | * struct TreeNode { 7 | * int val; 8 | * TreeNode *left; 9 | * TreeNode *right; 10 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 11 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 12 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 13 | * }; 14 | */ 15 | class Solution { 16 | public: 17 | vector> findLeaves(TreeNode* root) { 18 | vector> res; 19 | dfs(root, res); 20 | return res; 21 | } 22 | private: 23 | int dfs(TreeNode* root, vector>& res){ 24 | if (!root) return 0; 25 | int level = max(dfs(root->left, res), dfs(root->right, res)) + 1; 26 | if (level > res.size()) res.push_back(vector()); 27 | res[level - 1].push_back(root->val); 28 | return level; 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /300-399/374-Guess-Number-Higher-or-Lower.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity : O(logn). 2 | // Space complexity : O(1). 3 | 4 | /** 5 | * Forward declaration of guess API. 6 | * @param num your guess 7 | * @return -1 if num is lower than the guess number 8 | * 1 if num is higher than the guess number 9 | * otherwise return 0 10 | * int guess(int num); 11 | */ 12 | 13 | class Solution { 14 | public: 15 | int guessNumber(int n) { 16 | int lo = 1; 17 | int hi = n; 18 | while (lo <= hi) { 19 | int mid = lo + (hi - lo) / 2; 20 | int mid_val = guess(mid); 21 | if (mid_val == 0) { 22 | return mid; 23 | } else if (mid_val == 1) { 24 | lo = mid + 1; 25 | } else { 26 | hi = mid - 1; 27 | } 28 | } 29 | return -1; 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /300-399/376-Valid-Perfect-Square.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(logn). 2 | // Space complexity: O(1). 3 | 4 | class Solution { 5 | public: 6 | bool isPerfectSquare(int num) { 7 | assert (num > 0); 8 | if (num == 1) return true; 9 | 10 | int min = 1; 11 | int max = std::min(num / 2, 46340); // 46340 is the largest sqrt possible for int32_t 12 | 13 | while (min <= max) { 14 | int mid = min + (max - min) / 2; 15 | int res = mid * mid; 16 | if (res < num) { 17 | min = mid + 1; 18 | } else if (res > num){ 19 | max = mid - 1; 20 | } else { 21 | return true; 22 | } 23 | } 24 | 25 | return false; 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /300-399/383-Ransom-Note.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(1) extra space (at most 26 letters). 3 | 4 | class Solution { 5 | public: 6 | bool canConstruct(string ransomNote, string magazine) { 7 | unordered_map m; 8 | 9 | for (char ch : magazine) ++m[ch]; 10 | for (char ch : ransomNote) { 11 | if (--m[ch] < 0) { 12 | return false; 13 | } 14 | } 15 | 16 | return true; 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /300-399/387-First-Unique-Character-in-a-String.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(n) extra space. 3 | 4 | class Solution { 5 | public: 6 | int firstUniqChar(string s) { 7 | unordered_map occurrences; 8 | for (auto ch : s) { 9 | occurrences[ch]++; 10 | } 11 | for (int i = 0; i < s.size(); i++) { 12 | if (occurrences[s[i]] == 1) 13 | return i; 14 | } 15 | return -1; 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /300-399/392-Is-Subsequence.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(t.size()). 2 | // Space complexity: O(1) extra space. 3 | 4 | class Solution { 5 | public: 6 | bool isSubsequence(string s, string t) { 7 | int i = 0; 8 | for (auto ch : s) { 9 | while (i < t.size() && t[i] != ch) { 10 | ++i; 11 | } 12 | if (i == t.size()) { 13 | return false; // ch not found in t subsequently 14 | } else { 15 | ++i; // ch found, move to next one for future searching 16 | } 17 | } 18 | 19 | return true; 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /400-499/404-Sum-of-Left-Leaves.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n) 2 | // Space complexity: O(h) 3 | 4 | /** 5 | * Definition for a binary tree node. 6 | * struct TreeNode { 7 | * int val; 8 | * TreeNode *left; 9 | * TreeNode *right; 10 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 11 | * }; 12 | */ 13 | class Solution { 14 | public: 15 | int sumOfLeftLeaves(TreeNode* root) { 16 | if (!root) return 0; 17 | 18 | int left_sum = 0; 19 | int right_sum = 0; 20 | TreeNode* left_child = root->left; 21 | TreeNode* right_child = root->right; 22 | 23 | if (left_child) { 24 | if (!left_child->left && !left_child->right) { 25 | left_sum = left_child->val; 26 | } else { 27 | left_sum = sumOfLeftLeaves(left_child); 28 | } 29 | } 30 | 31 | if (right_child) { 32 | right_sum = sumOfLeftLeaves(right_child); 33 | } 34 | 35 | return left_sum + right_sum; 36 | } 37 | }; -------------------------------------------------------------------------------- /400-499/412-Fizz-Buzz.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(1). 3 | 4 | class Solution { 5 | public: 6 | vector fizzBuzz(int n) { 7 | vector res; 8 | for (int i = 1; i <= n; i++) { 9 | if (i % 3 == 0) { 10 | if (i % 5 == 0) { 11 | res.push_back("FizzBuzz"); 12 | } else { 13 | res.push_back("Fizz"); 14 | } 15 | } else if (i % 5 == 0) { 16 | res.push_back("Buzz"); 17 | } else { 18 | res.push_back(to_string(i)); 19 | } 20 | } 21 | return res; 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /400-499/429-N-ary-Tree-Level-Order-Traversal.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(n) extra space. 3 | 4 | /* 5 | // Definition for a Node. 6 | class Node { 7 | public: 8 | int val; 9 | vector children; 10 | 11 | Node() {} 12 | 13 | Node(int _val) { 14 | val = _val; 15 | } 16 | 17 | Node(int _val, vector _children) { 18 | val = _val; 19 | children = _children; 20 | } 21 | }; 22 | */ 23 | 24 | class Solution { 25 | public: 26 | vector> levelOrder(Node* root) { 27 | if (!root) { 28 | return vector>{}; 29 | } 30 | 31 | vector> res; 32 | 33 | queue> q; 34 | q.push({root, 0}); 35 | while (!q.empty()) { 36 | auto p = q.front(); 37 | q.pop(); 38 | 39 | auto node = p.first; 40 | auto level = p.second; 41 | if (level >= res.size()) { 42 | res.push_back({}); 43 | } 44 | res[level].push_back(node->val); 45 | 46 | for (auto child : node->children) { 47 | q.push({child, level + 1}); 48 | } 49 | } 50 | 51 | return res; 52 | } 53 | }; 54 | -------------------------------------------------------------------------------- /400-499/449-Serialize-and-Deserialize-BST.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(n). 3 | 4 | /** 5 | * Definition for a binary tree node. 6 | * struct TreeNode { 7 | * int val; 8 | * TreeNode *left; 9 | * TreeNode *right; 10 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 11 | * }; 12 | */ 13 | class Codec { 14 | public: 15 | 16 | // Encodes a tree to a single string. 17 | string serialize(TreeNode* root) { 18 | ostringstream oss; 19 | out(root, oss); 20 | return oss.str(); 21 | } 22 | 23 | // Decodes your encoded data to tree. 24 | TreeNode* deserialize(string data) { 25 | istringstream iss(data); 26 | return in(iss); 27 | } 28 | 29 | private: 30 | void out(TreeNode* node, ostringstream& oss) { 31 | if (!node) { 32 | oss << "# "; 33 | return; 34 | } 35 | oss << node->val << " "; 36 | out(node->left, oss); 37 | out(node->right, oss); 38 | } 39 | 40 | TreeNode* in(istringstream& iss) { 41 | string str; 42 | iss >> str; 43 | if (str == "#") return nullptr; 44 | TreeNode* node = new TreeNode(stoi(str)); 45 | node->left = in(iss); 46 | node->right = in(iss); 47 | return node; 48 | } 49 | }; 50 | 51 | // Your Codec object will be instantiated and called as such: 52 | // Codec codec; 53 | // codec.deserialize(codec.serialize(root)); 54 | -------------------------------------------------------------------------------- /400-499/451-Sort-Characters-By-Frequency.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(nlogn) 2 | // Space complexity: O(n) extra space 3 | 4 | class Solution1 { 5 | public: 6 | string frequencySort(string s) { 7 | unordered_map freq; 8 | for (auto c : s) { 9 | freq[c]++; 10 | } 11 | sort(s.begin(), s.end(), [&freq](char a, char b) 12 | { 13 | if (freq[a] == freq[b]) { 14 | return a > b; 15 | } else { 16 | return freq[a] > freq[b]; 17 | } 18 | } 19 | ); 20 | return s; 21 | } 22 | }; 23 | 24 | class Solution2 { 25 | public: 26 | string frequencySort(string s) { 27 | unordered_map freq; 28 | for (auto c : s) { 29 | freq[c]++; 30 | } 31 | 32 | map ascending_freq; 33 | for (auto& p : freq) { 34 | ascending_freq[p.second] += p.first; 35 | } 36 | 37 | string result; 38 | for (auto it = ascending_freq.rbegin(); it != ascending_freq.rend(); ++it) { 39 | for (auto c : it->second) { 40 | result += string(it->first, c); // fill string with arg1 (int) consecutive copies of arg2 (char) 41 | } 42 | } 43 | return result; 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /400-499/485-Max-Consecutive-Ones.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n) 2 | // Space complexity: O(1) 3 | 4 | class Solution { 5 | public: 6 | int findMaxConsecutiveOnes(vector& nums) { 7 | int cnt = 0; 8 | int max_cnt = 0; 9 | for (auto n : nums) { 10 | if (n == 1) { 11 | cnt++; 12 | } else { 13 | max_cnt = max(max_cnt, cnt); 14 | cnt = 0; 15 | } 16 | } 17 | max_cnt = max(max_cnt, cnt); 18 | return max_cnt; 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /400-499/496-Next-Greater-Element-I.cpp: -------------------------------------------------------------------------------- 1 | // Monotonic Stack 2 | // Time complexity: O(N). 3 | // Space complexity: O(N). 4 | 5 | class Solution { 6 | public: 7 | vector nextGreaterElement(vector& nums1, vector& nums2) { 8 | vector ans; 9 | stack s; 10 | unordered_map m; 11 | 12 | for (int num : nums2) { 13 | while (!s.empty() && num > s.top()) { 14 | m[s.top()] = num; 15 | s.pop(); 16 | } 17 | s.push(num); 18 | } 19 | 20 | while (!s.empty()) { 21 | m[s.top()] = -1; 22 | s.pop(); 23 | } 24 | 25 | for (int num : nums1) { 26 | ans.push_back(m[num]); 27 | } 28 | 29 | return ans; 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /400-499/498-Diagonal-Traverse.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(M * N). 2 | // Space complexity: O(1) extra space. 3 | 4 | class Solution { 5 | public: 6 | vector findDiagonalOrder(vector>& matrix) { 7 | if (matrix.empty()) return {}; 8 | int M = matrix.size(); 9 | int N = matrix[0].size(); 10 | 11 | vector result; 12 | 13 | int i = 0, j = 0; 14 | int step = 1; 15 | while (i < M && j < N) { 16 | result.push_back(matrix[i][j]); 17 | if (step > 0) { 18 | while (i - 1 >= 0 && j + 1 < N) { 19 | i--; 20 | j++; 21 | result.push_back(matrix[i][j]); 22 | } 23 | if (j == N - 1) { 24 | i++; 25 | } else if (i == 0) { 26 | j++; 27 | } 28 | } else { 29 | while (i + 1 < M && j - 1 >= 0) { 30 | i++; 31 | j--; 32 | result.push_back(matrix[i][j]); 33 | } 34 | if (i == M - 1) { 35 | j++; 36 | } else if (j == 0) { 37 | i++; 38 | } 39 | } 40 | step = -step; 41 | } 42 | 43 | return result; 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /500-599/500-Keyboard-Row.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(N) (N is total number of chars). 2 | // Space complexity: O(1) auxiliary space. 3 | 4 | class Solution { 5 | public: 6 | vector findWords(vector& words) { 7 | vector dict(26); 8 | string row0 = "qwertyuiop"; 9 | string row1 = "asdfghjkl"; 10 | string row2 = "zxcvbnm"; 11 | for (auto c : row0) { 12 | dict[c - 'a'] = 0; 13 | } 14 | for (auto c : row1) { 15 | dict[c - 'a'] = 1; 16 | } 17 | for (auto c : row2) { 18 | dict[c - 'a'] = 2; 19 | } 20 | 21 | vector result; 22 | for (auto& word : words) { 23 | bool flag = true; 24 | int row = dict[tolower(word[0]) - 'a']; 25 | for (auto c : word) { 26 | if (dict[tolower(c) - 'a'] != row) { 27 | flag = false; 28 | break; 29 | } 30 | } 31 | if (flag) { 32 | result.push_back(word); 33 | } 34 | } 35 | return result; 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /500-599/503-Next-Greater-Element-II.cpp: -------------------------------------------------------------------------------- 1 | // Brute Force 2 | // Time complexity: O(n^2). 3 | // Space complexity: O(1). 4 | class Solution1 { 5 | public: 6 | vector nextGreaterElements(vector& nums) { 7 | vector res(nums.size(), -1); 8 | for (int i = 0; i < nums.size(); i++) { 9 | for (int j = 1; j < nums.size(); j++) { 10 | if (nums[(i + j) % nums.size()] > nums[i]) { 11 | res[i] = nums[(i + j) % nums.size()]; 12 | break; 13 | } 14 | } 15 | } 16 | return res; 17 | } 18 | }; 19 | 20 | // Monotonic Stack 21 | // Circular List ? Just go over the list twice! 22 | // Time complexity: O(n). 23 | // Space complexity: O(n). 24 | class Solution2 { 25 | public: 26 | vector nextGreaterElements(vector& nums) { 27 | vector ans(nums.size()); 28 | stack s; 29 | for (int j = 0; j < 2; j++) { 30 | for (int i = nums.size() - 1; i >= 0; i--) { 31 | while (!s.empty() && nums[i] >= s.top()) { 32 | s.pop(); 33 | } 34 | ans[i] = s.empty() ? -1 : s.top(); 35 | s.push(nums[i]); 36 | } 37 | } 38 | return ans; 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /500-599/515-Find-Largest-Value-in-Each-Tree-Row.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(2 * n) extra space. 3 | 4 | /** 5 | * Definition for a binary tree node. 6 | * struct TreeNode { 7 | * int val; 8 | * TreeNode *left; 9 | * TreeNode *right; 10 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 11 | * }; 12 | */ 13 | class Solution { 14 | public: 15 | vector largestValues(TreeNode* root) { 16 | if (!root) return {}; 17 | 18 | vector largest_values; 19 | 20 | queue> q; 21 | q.push({root, 0}); 22 | 23 | int max_value = root->val; 24 | int prev_depth = -1; 25 | while (!q.empty()) { 26 | auto p = q.front(); 27 | q.pop(); 28 | TreeNode* curr = p.first; 29 | int curr_depth = p.second; 30 | 31 | if (curr_depth > 0 && curr_depth > prev_depth) { // start of a new row (excludes first row) 32 | largest_values.push_back(max_value); 33 | max_value = curr->val; 34 | } 35 | 36 | max_value = max(max_value, curr->val); 37 | if (curr->left) q.push({curr->left, curr_depth + 1}); 38 | if (curr->right) q.push({curr->right, curr_depth + 1}); 39 | prev_depth = curr_depth; 40 | } 41 | largest_values.push_back(max_value); // handles last row 42 | 43 | return largest_values; 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /500-599/559-Maximum-Depth-of-N-ary-Tree.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(h) extra space. 3 | 4 | /* 5 | // Definition for a Node. 6 | class Node { 7 | public: 8 | int val; 9 | vector children; 10 | 11 | Node() {} 12 | 13 | Node(int _val) { 14 | val = _val; 15 | } 16 | 17 | Node(int _val, vector _children) { 18 | val = _val; 19 | children = _children; 20 | } 21 | }; 22 | */ 23 | 24 | class Solution { 25 | public: 26 | int maxDepth(Node* root) { 27 | if (!root) return 0; 28 | 29 | int max_depth = 1; 30 | for (auto child : root->children) { 31 | max_depth = max(max_depth, maxDepth(child) + 1); 32 | } 33 | return max_depth; 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /500-599/563-Binary-Tree-Tilt.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(h) extra space. 3 | 4 | /** 5 | * Definition for a binary tree node. 6 | * struct TreeNode { 7 | * int val; 8 | * TreeNode *left; 9 | * TreeNode *right; 10 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 11 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 12 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 13 | * }; 14 | */ 15 | class Solution { 16 | public: 17 | int findTilt(TreeNode* root) { 18 | int tilt = 0; 19 | visit(root, tilt); 20 | return tilt; 21 | } 22 | private: 23 | int visit(TreeNode* root, int& tilt) { 24 | if (!root) return 0; 25 | int left = visit(root->left, tilt); 26 | int right = visit(root->right, tilt); 27 | tilt += abs(left - right); 28 | return left + right + root->val; 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /500-599/589-N-ary-Tree-Preorder-Traversal.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(h) extra space. 3 | 4 | /* 5 | // Definition for a Node. 6 | class Node { 7 | public: 8 | int val; 9 | vector children; 10 | 11 | Node() {} 12 | 13 | Node(int _val) { 14 | val = _val; 15 | } 16 | 17 | Node(int _val, vector _children) { 18 | val = _val; 19 | children = _children; 20 | } 21 | }; 22 | */ 23 | 24 | class Solution { 25 | public: 26 | vector preorder(Node* root) { 27 | if (!root) return {}; 28 | 29 | vector res; 30 | 31 | stack stk; 32 | stk.push(root); 33 | while (!stk.empty()) { 34 | auto node = stk.top(); 35 | stk.pop(); 36 | res.push_back(node->val); 37 | for (auto i = node->children.rbegin(), e = node->children.rend(); i != e; ++i) { 38 | stk.push(*i); 39 | } 40 | } 41 | 42 | return res; 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /500-599/590-N-ary-Tree-Postorder-Traversal.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(h) extra space. 3 | 4 | /* 5 | // Definition for a Node. 6 | class Node { 7 | public: 8 | int val; 9 | vector children; 10 | 11 | Node() {} 12 | 13 | Node(int _val) { 14 | val = _val; 15 | } 16 | 17 | Node(int _val, vector _children) { 18 | val = _val; 19 | children = _children; 20 | } 21 | }; 22 | */ 23 | 24 | class Solution { 25 | public: 26 | vector postorder(Node* root) { 27 | if (!root) return {}; 28 | 29 | vector res; 30 | 31 | stack stk; 32 | stk.push(root); 33 | while (!stk.empty()) { 34 | auto node = stk.top(); 35 | stk.pop(); 36 | res.push_back(node->val); 37 | for (auto child : node->children) { 38 | stk.push(child); 39 | } 40 | } 41 | 42 | reverse(res.begin(), res.end()); 43 | return res; 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /600-699/617-Merge-Two-Binary-Trees.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(n). 3 | 4 | /** 5 | * Definition for a binary tree node. 6 | * struct TreeNode { 7 | * int val; 8 | * TreeNode *left; 9 | * TreeNode *right; 10 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 11 | * }; 12 | */ 13 | class Solution { 14 | public: 15 | TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) { 16 | if (!t1) return t2; 17 | if (!t2) return t1; 18 | t1->val += t2->val; 19 | t1->left = mergeTrees(t1->left, t2->left); 20 | t1->right = mergeTrees(t1->right, t2->right); 21 | return t1; 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /600-699/637-Average-of-Levels-in-Binary-Tree.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(n). 3 | 4 | /** 5 | * Definition for a binary tree node. 6 | * struct TreeNode { 7 | * int val; 8 | * TreeNode *left; 9 | * TreeNode *right; 10 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 11 | * }; 12 | */ 13 | class Solution { 14 | public: 15 | vector averageOfLevels(TreeNode* root) { 16 | assert(root != nullptr); 17 | 18 | vector averages; 19 | 20 | queue q; 21 | q.push(root); 22 | 23 | while (!q.empty()) { 24 | long sum = 0, count = 0; 25 | queue temp; 26 | 27 | while (!q.empty()) { 28 | TreeNode* curr = q.front(); 29 | q.pop(); 30 | sum += curr->val; 31 | ++count; 32 | if (curr->left) temp.push(curr->left); 33 | if (curr->right) temp.push(curr->right); 34 | } 35 | 36 | q = temp; 37 | averages.push_back(sum / double{count}); 38 | } 39 | 40 | return averages; 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /600-699/665-Non-decreasing-Array.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public boolean checkPossibility(int[] nums) { 3 | int count = 0; 4 | int prev_max = Integer.MIN_VALUE; 5 | for (int i = 0; i < nums.length - 1; i++) { 6 | if (nums[i] > nums[i + 1]) { 7 | count += 1; 8 | if (nums[i + 1] >= prev_max) { 9 | nums[i] = nums[i + 1]; 10 | } else { 11 | nums[i + 1] = nums[i]; 12 | } 13 | } 14 | prev_max = nums[i]; 15 | } 16 | return (count <= 1); 17 | } 18 | } -------------------------------------------------------------------------------- /600-699/673-Number-of-Longest-Increasing-Subsequence.md: -------------------------------------------------------------------------------- 1 | # 673-Number of Longest Increasing Subsequence 2 | 3 | [Problem](https://leetcode.com/problems/number-of-longest-increasing-subsequence/) 4 | 5 | ## Approach 1: Dynamic Programming 6 | 7 | sasd 8 | 9 | Time complexity: O(n^2). 10 | 11 | Space complexity: O(n). 12 | 13 | ```c++ 14 | class Solution { 15 | public: 16 | int findNumberOfLIS(vector& nums) { 17 | auto N = nums.size(); 18 | if (N <= 1) return N; 19 | 20 | vector mem_len(N, 1); 21 | vector mem_num(N, 1); 22 | 23 | for (auto i = 1; i < N; ++i) { 24 | for (auto j = 0; j < i; ++j) { 25 | if (nums[i] > nums[j]) { 26 | auto len_seq = mem_len[j] + 1; 27 | if (len_seq > mem_len[i]) { 28 | mem_len[i] = len_seq; 29 | mem_num[i] = mem_num[j]; 30 | } else if (len_seq == mem_len[i]) { 31 | mem_num[i] += mem_num[j]; 32 | } 33 | } 34 | } 35 | } 36 | 37 | int result = 0; 38 | auto max_len = *max_element(mem_len.begin(), mem_len.end()); 39 | for (auto i = 0; i < N; ++i) { 40 | if (mem_len[i] == max_len) { 41 | result += mem_num[i]; 42 | } 43 | } 44 | return result; 45 | } 46 | }; 47 | ``` 48 | 49 | ## Approach 2: Segment Tree 50 | 51 | Time complexity: O(nlogn). 52 | 53 | Space complexity: O(n). 54 | 55 | TODO 56 | -------------------------------------------------------------------------------- /600-699/674-Longest-Continuous-Increasing-Subsequence.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n^2). 2 | // Space complexity: O(n). 3 | 4 | class Solution { 5 | public: 6 | int findLengthOfLCIS(vector& nums) { 7 | if (nums.empty()) { 8 | return 0; 9 | } 10 | 11 | int len = 1; 12 | int max_len = 1; 13 | for (int i = 1; i < nums.size(); i++) { 14 | if (nums[i] > nums[i - 1]) { 15 | len++; 16 | max_len = max(len, max_len); 17 | } else { 18 | len = 1; 19 | } 20 | } 21 | return max_len; 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /600-699/680-Valid-Palindrome-II.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(s.length). 2 | // Space complexity: O(1) auxiliary space. 3 | 4 | class Solution { 5 | public: 6 | bool validPalindrome(string s) { 7 | int left = 0; 8 | int right = s.size() - 1; 9 | 10 | while (left <= right) { 11 | if (s[left] != s[right]) 12 | return isPalindromeRange(s, left + 1, right) || 13 | isPalindromeRange(s, left, right - 1); 14 | left++; 15 | right--; 16 | } 17 | 18 | return true; 19 | } 20 | private: 21 | bool isPalindromeRange(const string& s, int left, int right) { 22 | while (left <= right) { 23 | if (s[left] != s[right]) 24 | return false; 25 | left++; 26 | right--; 27 | } 28 | return true; 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /600-699/684-Redundant-Connection.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(N x α(N)) ~= O(N). 2 | // Space complexity: O(N). 3 | 4 | class UnionFind { 5 | public: 6 | UnionFind(int N) : parent(N, 0), rank(N, 0) { 7 | for (int i = 0; i < N; ++i) { 8 | make_set(i); 9 | } 10 | } 11 | 12 | void make_set(int x) { 13 | parent[x] = x; 14 | } 15 | 16 | int find(int x) { 17 | if (parent[x] != x) 18 | parent[x] = find(parent[x]); 19 | return parent[x]; 20 | } 21 | 22 | void merge(int x, int y) { 23 | int xroot = find(x); 24 | int yroot = find(y); 25 | 26 | if (xroot == yroot) 27 | return; 28 | 29 | if (rank[xroot] < rank[yroot]) { 30 | swap(xroot, yroot); 31 | } 32 | parent[yroot] = xroot; 33 | if (rank[xroot] == rank[yroot]) 34 | ++rank[xroot]; 35 | } 36 | 37 | bool connected(int x, int y) { 38 | return find(x) == find(y); 39 | } 40 | private: 41 | vector parent; 42 | vector rank; 43 | }; 44 | 45 | class Solution { 46 | public: 47 | vector findRedundantConnection(vector>& edges) { 48 | UnionFind uf(edges.size()); 49 | for (const auto& edge : edges) { 50 | if (uf.connected(edge[0] - 1, edge[1] - 1)) { 51 | return edge; 52 | } 53 | uf.merge(edge[0] - 1, edge[1] - 1); 54 | } 55 | return {}; 56 | } 57 | }; 58 | -------------------------------------------------------------------------------- /600-699/692-Top-K-Frequent-Words.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(nlogk). 2 | // Space complexity: O(n). 3 | 4 | class Solution { 5 | public: 6 | vector topKFrequent(vector& words, int k) { 7 | unordered_map counts; 8 | unordered_set wordsSet; 9 | for (string& word : words) { 10 | counts[word]++; 11 | wordsSet.insert(word); 12 | } 13 | 14 | auto cmp = [&](const string& left, const string& right) { 15 | if (counts[left] == counts[right]) { 16 | return left > right; 17 | } 18 | return counts[left] < counts[right]; 19 | }; 20 | priority_queue, decltype(cmp)> heap(cmp); 21 | for (const string& word : wordsSet) { 22 | heap.push(word); 23 | } 24 | 25 | vector res; 26 | for (int i = 0; i < k; i++) { 27 | res.push_back(heap.top()); 28 | heap.pop(); 29 | } 30 | return res; 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /600-699/695-Max-Area-of-Island.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(M*N). 2 | // Space complexity: O(M*N) extra space due to recursion. 3 | 4 | class Solution { 5 | public: 6 | int maxAreaOfIsland(vector>& grid) { 7 | int M = grid.size(); 8 | int N = grid[0].size(); 9 | 10 | int max_area = 0; 11 | for (int i = 0; i < M; i++) { 12 | for (int j = 0; j < N; j++) { 13 | if (grid[i][j] == 1) { 14 | int area = dfs(i, j, grid); 15 | max_area = max(area, max_area); 16 | } 17 | } 18 | } 19 | return max_area; 20 | } 21 | private: 22 | int dfs(int i, int j, vector>& grid) { 23 | if (i < 0 || j < 0 || i >= grid.size() || j >= grid[0].size() || 24 | grid[i][j] == 0) { 25 | return 0; 26 | } 27 | 28 | int area = 1; 29 | grid[i][j] = 0; 30 | area += dfs(i - 1, j, grid); 31 | area += dfs(i + 1, j, grid); 32 | area += dfs(i, j - 1, grid); 33 | area += dfs(i, j + 1, grid); 34 | return area; 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /700-799/700-Search-in-a-Binary-Search-Tree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * struct TreeNode { 4 | * int val; 5 | * TreeNode *left; 6 | * TreeNode *right; 7 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 8 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 9 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 10 | * }; 11 | */ 12 | 13 | // Recursion 14 | // Time complexity: O(h) = O(logn). 15 | // Space complexity: O(h) extra space. 16 | class Solution1 { 17 | public: 18 | TreeNode* searchBST(TreeNode* root, int val) { 19 | if (!root) return nullptr; 20 | 21 | if (val == root->val) { 22 | return root; 23 | } else if (val < root->val) { 24 | return searchBST(root->left, val); 25 | } else { 26 | return searchBST(root->right, val); 27 | } 28 | } 29 | }; 30 | 31 | // Iteration 32 | // Time complexity: O(h) = O(logn). 33 | // Space complexity: O(1) extra space. 34 | class Solution2 { 35 | public: 36 | TreeNode* searchBST(TreeNode* root, int val) { 37 | while (root && val != root->val) 38 | root = val < root->val ? root->left : root->right; 39 | return root; 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /700-799/704-Binary-Search.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(logn). 2 | // Space complexity: O(1). 3 | 4 | class Solution { 5 | public: 6 | int search(vector& nums, int target) { 7 | int lo = 0; 8 | int hi = nums.size(); 9 | while (lo <= hi) { 10 | int mid = lo + (hi - lo) / 2; 11 | if (nums[mid] == target) { 12 | return mid; 13 | } 14 | if (nums[mid] > target) { 15 | hi = mid - 1; 16 | } else { 17 | lo = mid + 1; 18 | } 19 | } 20 | return -1; 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /700-799/725-Split-Linked-List-in-Parts.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(1). 3 | 4 | /** 5 | * Definition for singly-linked list. 6 | * struct ListNode { 7 | * int val; 8 | * ListNode *next; 9 | * ListNode(int x) : val(x), next(NULL) {} 10 | * }; 11 | */ 12 | class Solution { 13 | public: 14 | vector splitListToParts(ListNode* root, int k) { 15 | // Count list length 16 | int list_len{0}; 17 | for (auto node = root; node; node = node->next) list_len++; 18 | 19 | // Calculate base part length and remainder 20 | int part_len_base{list_len / k}; 21 | int remainder{list_len % k}; 22 | 23 | vector v{}; 24 | ListNode* curr{root}; 25 | ListNode* prev{nullptr}; 26 | for (auto i = 0; i < k; ++i) { 27 | ListNode* head{curr}; 28 | 29 | int part_len{part_len_base + ((i < remainder) ? 1 : 0)}; 30 | for (auto j = 0; j < part_len; ++j) { 31 | prev = curr; 32 | curr = curr->next; 33 | } 34 | if (prev) prev->next = nullptr; // tricky part, prev of first sublist is nullptr 35 | 36 | v.push_back(head); 37 | } 38 | 39 | return v; 40 | } 41 | }; -------------------------------------------------------------------------------- /700-799/733-Flood-Fill.cpp: -------------------------------------------------------------------------------- 1 | // DFS 2 | // Time complexity: O(mn). 3 | // Space complexity: O(mn). 4 | 5 | class Solution { 6 | public: 7 | vector> floodFill(vector>& image, int sr, int sc, int newColor) { 8 | vector> res(image); 9 | vector> visited(image.size(), vector(image[0].size(), 0)); 10 | dfs(image, res, visited, sr, sc, newColor); 11 | return res; 12 | } 13 | private: 14 | void dfs(vector>& image, vector>& res, vector>& visited, int sr, int sc, int newColor) { 15 | if (visited[sr][sc] == 1) { 16 | return; 17 | } 18 | visited[sr][sc] = 1; 19 | res[sr][sc] = newColor; 20 | 21 | const int N = image.size(); 22 | const int M = image[0].size(); 23 | int color = image[sr][sc]; 24 | if (sr + 1 < N && image[sr + 1][sc] == color) { 25 | dfs(image, res, visited, sr + 1, sc, newColor); 26 | } 27 | if (sr - 1 >= 0 && image[sr - 1][sc] == color) { 28 | dfs(image, res, visited, sr - 1, sc, newColor); 29 | } 30 | if (sc + 1 < M && image[sr][sc + 1] == color) { 31 | dfs(image, res, visited, sr, sc + 1, newColor); 32 | } 33 | if (sc - 1 >= 0 && image[sr][sc - 1] == color) { 34 | dfs(image, res, visited, sr, sc - 1, newColor); 35 | } 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /700-799/744-Find-Smallest-Letter-Greater-Than-Target.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(logn). 2 | // Space complexity: O(1). 3 | class Solution { 4 | public: 5 | char nextGreatestLetter(vector& letters, char target) { 6 | int ans = letters[0]; 7 | int lo = 0; 8 | int hi = letters.size() - 1; 9 | while (lo <= hi) { 10 | int mid = lo + (hi - lo) / 2; 11 | if (letters[mid] == target) { 12 | lo = mid + 1; 13 | } else if (letters[mid] < target) { 14 | lo = mid + 1; 15 | } else { 16 | ans = letters[mid]; 17 | hi = mid - 1; 18 | } 19 | } 20 | return ans; 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /700-799/746-Min-Cost-Climbing-Stairs.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(1). 3 | 4 | class Solution { 5 | public: 6 | int minCostClimbingStairs(vector& cost) { 7 | const int N = cost.size(); 8 | 9 | vector min_costs(N + 1, 0); 10 | for (int i = 2; i < N + 1; ++i) { 11 | min_costs[i] = min(min_costs[i - 2] + cost[i - 2], min_costs[i - 1] + cost[i - 1]); 12 | } 13 | 14 | return min_costs.back(); 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /700-799/754-Reach-a-Number.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(sqrt(target)). 2 | // Space complexity: O(1). 3 | 4 | // Math trick: https://leetcode.com/problems/reach-a-number/solution/. 5 | 6 | class Solution { 7 | public: 8 | int reachNumber(int target) { 9 | target = abs(target); 10 | 11 | int k = 0; 12 | while (target > 0) { 13 | k++; 14 | target -= k; 15 | } 16 | 17 | return target % 2 == 0 ? k : k + 1 + k % 2; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /700-799/771-Jewels-and-Stones.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n + m). 2 | // Space complexity: O(n). 3 | 4 | class Solution { 5 | public: 6 | int numJewelsInStones(string J, string S) { 7 | unordered_set s; 8 | for (auto c : J) { 9 | s.insert(c); 10 | } 11 | 12 | int num = 0; 13 | for (auto c : S) { 14 | if (s.find(c) != s.end()) { 15 | num++; 16 | } 17 | } 18 | return num; 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /700-799/785-Is-Graph-Bipartite.cpp: -------------------------------------------------------------------------------- 1 | // DFS coloring 2 | // Time complexity: O(n). 3 | // Space complexity: O(n). 4 | 5 | class Solution { 6 | public: 7 | bool isBipartite(vector>& graph) { 8 | enum Color { UNCOLORED, RED, GREEN }; 9 | const int N = graph.size(); 10 | vector color(N, UNCOLORED); 11 | 12 | for (int i = 0; i < N; i++) { 13 | if (color[i] == UNCOLORED) { 14 | stack stk; 15 | stk.push(i); 16 | color[i] = RED; 17 | 18 | while (!stk.empty()) { 19 | int node = stk.top(); 20 | stk.pop(); 21 | for (int neighbor : graph[node]) { 22 | if (color[neighbor] == UNCOLORED) { 23 | stk.push(neighbor); 24 | color[neighbor] = (color[node] == RED ? GREEN : RED); 25 | } else if (color[neighbor] == color[node]) { 26 | return false; 27 | } 28 | } 29 | } 30 | } 31 | } 32 | 33 | return true; 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /800-899/811-Subdomain-Visit-Count.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(N), where N is the length of cpdomains, and assuming the length of cpdomains[i] is fixed. 2 | // Space complexity: O(number of subdomains) extra space. 3 | 4 | class Solution { 5 | public: 6 | vector subdomainVisits(vector& cpdomains) { 7 | unordered_map subdomain_counts; 8 | for (const auto &str: cpdomains) { 9 | // Get the number 10 | size_t pos = str.find(' '); 11 | int count = stoi(str.substr(0, pos)); 12 | 13 | // Get each subdomain 14 | while (pos != string::npos){ 15 | string subdomain = str.substr(pos + 1, str.size() - pos); 16 | subdomain_counts[subdomain] += count; 17 | pos = str.find('.', pos + 1); 18 | } 19 | } 20 | 21 | vector res; 22 | for (const auto &p : subdomain_counts) { 23 | res.push_back(to_string(p.second) + " " + p.first); 24 | } 25 | return res; 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /800-899/829-Consecutive-Numbers-Sum.md: -------------------------------------------------------------------------------- 1 | # 829 Consecutive Numbers Sum 2 | 3 | [Problem](https://leetcode.com/problems/consecutive-numbers-sum/) 4 | 5 | ## Solution 6 | 7 | We can write N = (x+1) + (x+2) + ... + (x+k), x >= 0, k >= 1, both integers. It can be further written as N - (1 + 2 + ... + k) = k * x, and as long as N - (1 + 2 + ... + k) is evenly divided by k, there exist a solution x. 8 | 9 | Time complexity: O(sqrt(n)). 10 | 11 | Space complexity: O(1). 12 | 13 | ```c++ 14 | class Solution { 15 | public: 16 | int consecutiveNumbersSum(int N) { 17 | int cnt = 0; 18 | 19 | for (int k = 1; ; k++) { 20 | N -= k; 21 | if (N < 0) break; 22 | if (N % k == 0) cnt++; 23 | } 24 | 25 | return cnt; 26 | } 27 | }; 28 | ``` 29 | -------------------------------------------------------------------------------- /800-899/852-Peak-Index-in-a-Mountain-Array.cpp: -------------------------------------------------------------------------------- 1 | // Approach 1: Linear Scan 2 | // Time complexity: O(n). 3 | // Space complexity: O(1) extra space. 4 | class Solution { 5 | public: 6 | int peakIndexInMountainArray(vector& A) { 7 | int i = 0; 8 | while (A[i] < A[i+1]) i++; 9 | return i; 10 | } 11 | }; 12 | 13 | // Approach 2: Binary Search 14 | // Time complexity: O(logn). 15 | // Space complexity: O(1) extra space. 16 | class Solution { 17 | public: 18 | int peakIndexInMountainArray(vector& A) { 19 | int left = 0, right = A.size() - 1; 20 | while (left < right) { 21 | int mid = left + (right - left) / 2; 22 | if (A[mid] < A[mid + 1]) 23 | left = mid + 1; 24 | else 25 | right = mid; 26 | } 27 | return left; 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /800-899/881-Boats-to-Save-People.md: -------------------------------------------------------------------------------- 1 | # 881-Boats to Save People 2 | 3 | [Problem](https://leetcode.com/problems/boats-to-save-people/) 4 | 5 | ## Approach: Sort + Two Pointer 6 | 7 | If the heaviest person can share a boat with the lightest person, then do so. Otherwise, the heaviest person can't pair with anyone, so they get their own boat. 8 | 9 | Time complexity: O(nlogn). 10 | 11 | Space complexity: O(1) extra space. 12 | 13 | ```c++ 14 | class Solution { 15 | public: 16 | int numRescueBoats(vector& people, int limit) { 17 | sort(people.begin(), people.end()); 18 | int lo = 0, hi = people.size() - 1; 19 | int ans = 0; 20 | 21 | while (lo <= hi) { 22 | ans++; 23 | if (people[lo] + people[hi] <= limit) { 24 | lo++; 25 | } 26 | hi--; 27 | } 28 | 29 | return ans; 30 | } 31 | }; 32 | ``` 33 | -------------------------------------------------------------------------------- /800-899/896-Monotonic-Array.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(1) extra space. 3 | 4 | class Solution { 5 | public: 6 | bool isMonotonic(vector& A) { 7 | int len = A.size(); 8 | 9 | if (len <= 1) { 10 | return true; 11 | } 12 | 13 | if (A[0] <= A[len - 1]) { 14 | for (int i = 0; i < len - 1; i++) { 15 | if (A[i] > A[i + 1]) { 16 | return false; 17 | } 18 | } 19 | } else { 20 | for (int i = 0; i < len - 1; i++) { 21 | if (A[i] < A[i + 1]) { 22 | return false; 23 | } 24 | } 25 | } 26 | 27 | return true; 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /900-999/938-Range-Sum-of-BST.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(N) 2 | // Space complexity: O(H) 3 | 4 | /** 5 | * Definition for a binary tree node. 6 | * struct TreeNode { 7 | * int val; 8 | * TreeNode *left; 9 | * TreeNode *right; 10 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 11 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 12 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 13 | * }; 14 | */ 15 | class Solution { 16 | public: 17 | int rangeSumBST(TreeNode* root, int L, int R) { 18 | int sum = 0; 19 | stack stk; 20 | stk.push(root); 21 | while (!stk.empty()) { 22 | auto node = stk.top(); 23 | stk.pop(); 24 | if (node) { 25 | if (L <= node->val && node->val <= R) { 26 | sum += node->val; 27 | } 28 | if (L < node->val) { 29 | stk.push(node->left); 30 | } 31 | if (node->val < R) { 32 | stk.push(node->right); 33 | } 34 | } 35 | } 36 | return sum; 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /900-999/965-Univalued-Binary-Tree.cpp: -------------------------------------------------------------------------------- 1 | // Time complexity: O(n). 2 | // Space complexity: O(h) extra space. 3 | 4 | /** 5 | * Definition for a binary tree node. 6 | * struct TreeNode { 7 | * int val; 8 | * TreeNode *left; 9 | * TreeNode *right; 10 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 11 | * }; 12 | */ 13 | class Solution { 14 | public: 15 | bool isUnivalTree(TreeNode* root) { 16 | if (!root) return true; 17 | return isUnivalTreeRecu(root, root->val); 18 | } 19 | private: 20 | bool isUnivalTreeRecu(TreeNode* root, int val) { 21 | if (!root) return true; 22 | if (root->val != val) return false; 23 | return isUnivalTreeRecu(root->left, val) && isUnivalTreeRecu(root->right, val); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /900-999/977-Squares-of-a-Sorted-Array.cpp: -------------------------------------------------------------------------------- 1 | // Two pointer 2 | // Time complexity: O(n). 3 | // Space complexity: O(1) extra space. 4 | 5 | class Solution { 6 | public: 7 | vector sortedSquares(vector& A) { 8 | int N = (int)A.size(); 9 | int i = 0; // to iterate non-negative numbers 10 | while (i < N && A[i] < 0) i++; 11 | int j = i - 1; // to iterate negative numbers reversely 12 | 13 | vector ans; 14 | auto sqr = [](int x) { return x * x; }; 15 | 16 | while (i < N && j >= 0) { 17 | if (sqr(A[i]) < sqr(A[j])) { 18 | ans.push_back(sqr(A[i])); 19 | i++; 20 | } else { 21 | ans.push_back(sqr(A[j])); 22 | j--; 23 | } 24 | } 25 | while (i < N) { 26 | ans.push_back(sqr(A[i])); 27 | i++; 28 | } 29 | while (j >= 0) { 30 | ans.push_back(sqr(A[j])); 31 | j--; 32 | } 33 | 34 | return ans; 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Algorithms-LeetCode 2 | 3 | This started as a repo of solutions to LeetCode problems in preparation for job interviews. I summed up some of the problems and a few special topics that I found hard to tackle or inspiring. Over time, it has evolved into a collection of algorithms notes backed up with solutions to LeetCode problems as examples. 4 | 5 | The main programming lanaguage I used is C++. I also used Java for some of the problems. 6 | 7 | ## Data Structures 8 | 9 | * [Linked List](Topics/Linked-List.md) 10 | 11 | * [Tree](Topics/Tree.md) 12 | 13 | * [Graph](Topics/Graph.md) 14 | * [Topological Sort](Topics/Topological-Sort.md) 15 | 16 | * [Heap & Priority Queue](Topics/Heap-&-Priority-Queue.md) 17 | 18 | * [Monotonic Stack & Queue](Topics/Monotonic-Stack-&-Queue.md) 19 | 20 | * [Trie (Prefix Tree)](Topics/Trie.md) 21 | 22 | * [Disjoint Set (Union-Find)](Topics/Disjoint-Set.md) 23 | 24 | * [Segment Tree](Topics/Segment-Tree.md) 25 | 26 | ## Algorithmic Patterns 27 | 28 | * [Dynamic Programming](Topics/Dynamic-Programming.md) 29 | 30 | * [Divide and Conquer](Topics/Divide-and-Conquer.md) 31 | * [Binary Search](Topics/Binary-Search.md) 32 | 33 | ## Specific Algorithms and Techniques 34 | 35 | * [K-Sum](Topics/K-Sum.md) 36 | 37 | * [K-Palindrome](Topics/K-Palindrome.md) 38 | 39 | * [Path-Sum](Topics/Path-Sum.md) 40 | 41 | * [Bit Manipulation](Topics/Bit-Manipulation.md) 42 | 43 | ## Language-specific Practices 44 | 45 | * [C++ Memo](Topics/C++-Memo.md) 46 | -------------------------------------------------------------------------------- /Topics/Bit-Manipulation.md: -------------------------------------------------------------------------------- 1 | # Bit Manipulation 2 | 3 | ## XOR for eliminating paired duplicates 4 | 5 | As 0 ^ a = a, a ^ a = 0, XOR can be used to eliminate paired duplicates. 6 | 7 | Example: [136-Single Number](../100-199/136-Single-Number.md), [389-Find the Difference](../300-399/389-Find-the-Difference.md). 8 | -------------------------------------------------------------------------------- /Topics/Divide-and-Conquer.md: -------------------------------------------------------------------------------- 1 | # Divide and Conquer 2 | 3 | ## Binary Search 4 | 5 | See [here](Binary-Search.md). 6 | -------------------------------------------------------------------------------- /Topics/Graph.md: -------------------------------------------------------------------------------- 1 | # Graph 2 | 3 | ## Representation 4 | 5 | Following two are the most commonly used representations of a graph: 6 | 7 | 1. Adjacency Matrix 8 | 2. Adjacency List 9 | 10 | ### Adjacency Matrix 11 | 12 | Adjacency Matrix is a matrix of size V x V where V is the number of vertices in a graph. Let the matrix by adj[][], adj[i][j] = 1 represents that there is an edge from vertex i to vertex j in the graph. An adjacency matrix for undirected graph is always symmetric. For unweighted graph, we can just use adj[i][j] = w to represent that the edge from vertex i to vertex j has weight w. 13 | 14 | ### Adjacency List 15 | 16 | Adjacency List is a size V array of lists where V is the number of vertices. Let the array be adj[], adj[i] represents the list of vertices adjacent to vertex i. This representation can also be used to represent a weighted graph. The weights of edges can be represented as lists of pairs. 17 | 18 | ## DFS and BFS 19 | 20 | DFS: use a stack, often use recursion 21 | BFS: use a queue 22 | 23 | ## Topological Sort 24 | 25 | See [here](Topological-Sort.md). 26 | 27 | ## Connected Component 28 | 29 | 547 30 | 31 | 1. DFS 32 | 2. BFS 33 | 3. Union Find 34 | 35 | ## Shortest Path 36 | 37 | ## Minimum Spanning Tree 38 | -------------------------------------------------------------------------------- /Topics/Heap-&-Priority-Queue.md: -------------------------------------------------------------------------------- 1 | # Heap & Priority Queue 2 | 3 | ## Heap 4 | 5 | ## Priority Queue 6 | -------------------------------------------------------------------------------- /Topics/Path-Sum.md: -------------------------------------------------------------------------------- 1 | # Path-Sum 2 | 3 | Given a binary tree and a sum, determine the existence/counts of the tree paths whose path sum (adding up all the values along the path) equals the target sum OR find the max/min path sum. 4 | 5 | ## Root-to-leaf Path Only 6 | 7 | Simple DFS. 8 | 9 | * (Existence) [112-Path Sum](../100-199/112-Path-Sum.cpp). 10 | * (Print all paths) [113-Path Sum II](../100-199/113-Path-Sum-II.cpp). 11 | 12 | ## Downwards Path Only 13 | 14 | Here, the path does not need to start or end at the root or a leaf, but it must go downwards. The simplest way is to traverse the tree with DFS/BFS, then run the above approach at each node. 15 | 16 | Optimizaton: use a hash map to store the prefix sum along the traversal. 17 | 18 | * (Counts) [437-Path Sum III](../400-499/437-Path-Sum-III.md) 19 | * (Counts; Array Variant) [560-Subarray Sum Equals K](../500-599/560-Subarray-Sum-Equals-K.md) 20 | 21 | ## Arbitrary Path 22 | 23 | Any path in a tree must be either a downwards path or the concatenation of two downwards paths (a central node + two downwards path starting at two different children of the central node, can view the central node + one downwards path as one path). 24 | 25 | It is in gerneral difficult to determine the existence/counts of the tree paths whose path sum equals the target sum. However, it is easy to find a recursive solution to the max/min path sum problem. 26 | 27 | * (Max path sum) [124-Binary Tree Maximum Path Sum](../100-199/124-Binary-Tree-Maximum-Path-Sum.md) 28 | -------------------------------------------------------------------------------- /Topics/Segment-Tree.md: -------------------------------------------------------------------------------- 1 | # Segment Tree 2 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /img/142.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-czh/Algorithms-LeetCode/de1a991e4c63df4fd3ab244d0a153e142211e781/img/142.jpg -------------------------------------------------------------------------------- /img/160_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-czh/Algorithms-LeetCode/de1a991e4c63df4fd3ab244d0a153e142211e781/img/160_1.jpg -------------------------------------------------------------------------------- /img/160_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-czh/Algorithms-LeetCode/de1a991e4c63df4fd3ab244d0a153e142211e781/img/160_2.jpg -------------------------------------------------------------------------------- /img/421.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-czh/Algorithms-LeetCode/de1a991e4c63df4fd3ab244d0a153e142211e781/img/421.png -------------------------------------------------------------------------------- /img/tree_traverse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-czh/Algorithms-LeetCode/de1a991e4c63df4fd3ab244d0a153e142211e781/img/tree_traverse.png -------------------------------------------------------------------------------- /img/trie.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-czh/Algorithms-LeetCode/de1a991e4c63df4fd3ab244d0a153e142211e781/img/trie.jpg --------------------------------------------------------------------------------