├── .gitignore ├── 1. January ├── Day10SameTree.cpp ├── Day11MinimumTimeToCollectAllApplesInATree.cpp ├── Day12NumberOfNodesInTheSubTreeWithTheSameLabel.cpp ├── Day13LongestPathWithDifferentAdjacentCharacters.cpp ├── Day14LexicographicallySmallestEquivalentString.cpp ├── Day15NumberOfGoodPaths.cpp ├── Day16InsertInterval.cpp ├── Day17FlipStringToMonotoneIncreasing.cpp ├── Day18MaximumSumCircularSubarray.cpp ├── Day19SubarraySumsDivisibleByK.cpp ├── Day1WordPattern.cpp ├── Day20NonDecreasingSubsequences.cpp ├── Day21RestoreIPAddresses.cpp ├── Day22PalindromePartitioning.cpp ├── Day23FindTheTownJudge.cpp ├── Day24SnakesAndLadders.cpp ├── Day25FindClosestNodeToGivenTwoNodes.cpp ├── Day26CheapestFlightsWithinKStops.cpp ├── Day27ConcatenatedWords.cpp ├── Day28DataStreamAsDisjointIntervals.cpp ├── Day29LFUCache.cpp ├── Day2DetectCapital.cpp ├── Day30NthTribonacciNumber.cpp ├── Day31BestTeamWithNoConflicts.cpp ├── Day3DeleteColumnsToMakeSorted.cpp ├── Day4MinimumRoundsToCompleteAllTasks.cpp ├── Day5MinimumNumberOfArrowsToBurstBalloons.cpp ├── Day6MaximumIceCreamBars.cpp ├── Day7GasStation.cpp ├── Day8MaxPointsOnALine.cpp └── Day9BinaryTreePreorderTraversal.cpp ├── 2. February ├── Day10AsFarFromLandAsPossible.cpp ├── Day11ShortestPathWithAlternatingColors.cpp ├── Day12MinimumFuelCostToReportToTheCapital.cpp ├── Day13CountOddNumbersInAnIntervalRange.cpp ├── Day14AddBinary.cpp ├── Day15AddToArrayFormOfInteger.cpp ├── Day16MaximumDepthOfBinaryTree.cpp ├── Day17MinimumDistanceBetweenBSTNodes.cpp ├── Day18InvertBinaryTree.cpp ├── Day19BinaryTreeZigzagLevelOrderTraversal.cpp ├── Day1GreatestCommonDivisorOfStrings.cpp ├── Day20SearchInsertPosition.cpp ├── Day21SingleElementInASortedArray.cpp ├── Day22CapacityToShipPackagesWithinDDays.cpp ├── Day23IPO.cpp ├── Day24MinimizeDeviationInArray.cpp ├── Day25BestTimeToBuyAndSellStock.cpp ├── Day26EditDistance.cpp ├── Day27ConstructQuadTree.cpp ├── Day28FindDuplicateSubtrees.cpp ├── Day2VerifyingAnAlienDictionary.cpp ├── Day3ZigzagConversion.cpp ├── Day4PermutationInString.cpp ├── Day5FindAllAnagramsInAString.cpp ├── Day6ShuffleTheArray.cpp ├── Day7FruitIntoBaskets.cpp ├── Day8JumpGameII.cpp └── Day9NamingACompany.cpp ├── 3. March ├── Day10LinkedListRandomNode.cpp ├── Day11ConvertSortedListToBinarySearchTree.cpp ├── Day12MergeKSortedLists.cpp ├── Day13SymmetricTree.cpp ├── Day14SumRootToLeafNumbers.cpp ├── Day15.CheckCompletenessOfABinaryTree.cpp ├── Day16ConstructBinaryTreeFromInorderAndPostorderTraversal.cpp ├── Day17ImplementTriePrefixTree.cpp ├── Day18DesignBrowserHistory.cpp ├── Day19DesignAddAndSearchWordsDataStructure.cpp ├── Day1SortAnArray.cpp ├── Day20CanPlaceFlowers.cpp ├── Day21NumberOfZeroFilledSubarrays.cpp ├── Day22MinimumScoreOfAPathBetweenTwoCities.cpp ├── Day23NumberOfOperationsToMakeNetworkConnected.cpp ├── Day24ReorderRoutesToMakeAllPathsLeadToTheCityZero.cpp ├── Day25CountUnreachablePairsOfNodesInAnUndirectedGraph.cpp ├── Day26LongestCycleInAGraph.cpp ├── Day27MinimumPathSum.cpp ├── Day28MinimumCostForTickets.cpp ├── Day29ReducingDishes.cpp ├── Day2StringCompression.cpp ├── Day30ScrambleString.cpp ├── Day31NumberOfWaysOfCuttingAPizza.cpp ├── Day3FindTheIndexOfTheFirstOccurrenceInAString.cpp ├── Day4CountSubarraysWithFixedBounds.cpp ├── Day5JumpGameIV.cpp ├── Day6KthMissingPositiveNumber.cpp ├── Day7MinimumTimeToCompleteTrips.cpp ├── Day8KokoEatingBananas.cpp └── Day9LinkedListCycleII.cpp ├── 4. April ├── Day10ValidParentheses.cpp ├── Day11RemovingStarsFromAString.cpp ├── Day12SimplifyPath.cpp ├── Day13ValidateStackSequences.cpp ├── Day14LongestPalindromicSubsequence.cpp ├── Day15MaximumValueOfKCoinsFromPiles.cpp ├── Day16NumberOfWaysToFormATargetStringGivenADictionary.cpp ├── Day17KidsWithTheGreatestNumberOfCandies.cpp ├── Day18MergeStringsAlternately.cpp ├── Day19LongestZigZagPathInABinaryTree.cpp ├── Day1BinarySearch.cpp ├── Day20MaximumWidthOfBinaryTree.cpp ├── Day21ProfitableSchemes.cpp ├── Day22MinimumInsertionStepsToMakeAStringPalindrome.cpp ├── Day23RestoreTheArray.cpp ├── Day24LastStoneWeight.cpp ├── Day25SmallestNumberInInfiniteSet.cpp ├── Day26AddDigits.cpp ├── Day27BulbSwitcher.cpp ├── Day28SimilarStringGroups.cpp ├── Day29CheckingExistenceOfEdgeLengthLimitedPaths.cpp ├── Day2SuccessfulPairsOfSpellsAndPotions.cpp ├── Day30RemoveMaxNumberOfEdgesToKeepGraphFullyTraversable.cpp ├── Day3BoatsToSavePeople.cpp ├── Day4OptimalPartitionOfString.cpp ├── Day5MinimizeMaximumOfArray.cpp ├── Day6NumberOfClosedIslands.cpp ├── Day7NumberOfEnclaves.cpp ├── Day8CloneGraph.cpp └── Day9LargestColorValueInADirectedGraph.cpp ├── README.md └── images ├── AppBreweryWallpaper 8.png └── AppBreweryWallpaper.png /1. January/Day10SameTree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day10SameTree.cpp 3 | * @author Ginny Dang 4 | * @brief 100. Same Tree (https://leetcode.com/problems/same-tree/description/) 5 | * @version 0.1 6 | * @date 2023-01-10 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * @brief New thing I've learned from this challenge 14 | * If the 2 first conditions in this code were in reversed order, the whole program would be ruined in 15 | * if (!p && !q) MUST go before else if (!p || !q) 16 | * This is due to the nature of C++ 17 | * 18 | * Checking (!p || !q) before (!p && !q) causes the problem because if both p and q are null, 19 | * the condition (!p || !q) returns false right away due to p is null without even considering whether q is null or not. 20 | * Meanwhile, if both p and q are null, we should return true. 21 | * Therefore, the "tighter" condition, which is (!p && !q) must come first. 22 | */ 23 | 24 | /** 25 | * Definition for a binary tree node. 26 | * struct TreeNode { 27 | * int val; 28 | * TreeNode *left; 29 | * TreeNode *right; 30 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 31 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 32 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 33 | * }; 34 | */ 35 | class Solution 36 | { 37 | public: 38 | bool isSameTree(TreeNode *p, TreeNode *q) 39 | { 40 | // Both trees are none 41 | if (!p && !q) 42 | return true; 43 | // 1 of the 2 trees is none 44 | else if (!p || !q) 45 | return false; 46 | // Both trees are not none 47 | // cout << p->val << " " << q->val << "\n"; 48 | if (p->val != q->val) 49 | return false; 50 | return isSameTree(p->left, q->left) && isSameTree(p->right, q->right); 51 | } 52 | }; 53 | 54 | // Time Complexity: O(N) 55 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /1. January/Day11MinimumTimeToCollectAllApplesInATree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day11MinimumTimeToCollectAllApplesInATree.cpp 3 | * @author Ginny Dang 4 | * @brief 1443. Minimum Time to Collect All Apples in a Tree (https://leetcode.com/problems/minimum-time-to-collect-all-apples-in-a-tree/description/) 5 | * @version 0.1 6 | * @date 2023-01-11 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int dfs(int start, vector> &graph, vector &hasApple, vector &visited, int seconds) 16 | { 17 | visited[start] = true; 18 | 19 | for (int neighbor : graph[start]) 20 | { 21 | if (visited[neighbor]) 22 | continue; 23 | 24 | seconds += dfs(neighbor, graph, hasApple, visited, 0); 25 | 26 | if (hasApple[neighbor]) 27 | hasApple[start] = true; 28 | } 29 | 30 | if (start != 0 && hasApple[start]) 31 | seconds += 2; 32 | 33 | return seconds; 34 | } 35 | 36 | int minTime(int n, vector> &edges, vector &hasApple) 37 | { 38 | vector visited(n, false); 39 | vector> graph(n, vector()); 40 | 41 | for (auto edge : edges) 42 | { 43 | graph[edge[0]].push_back(edge[1]); 44 | graph[edge[1]].push_back(edge[0]); 45 | } 46 | 47 | return dfs(0, graph, hasApple, visited, 0); 48 | } 49 | }; 50 | 51 | // Time Complexity: O(V + E) 52 | // Space Complexity: O(V + E) -------------------------------------------------------------------------------- /1. January/Day12NumberOfNodesInTheSubTreeWithTheSameLabel.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day12NumberOfNodesInTheSubTreeWithTheSameLabel.cpp 3 | * @author Ginny Dang 4 | * @brief 1519. Number of Nodes in the Sub-Tree With the Same Label (https://leetcode.com/problems/number-of-nodes-in-the-sub-tree-with-the-same-label/description/) 5 | * @version 0.1 6 | * @date 2023-01-12 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | void dfs(int start, string &labels, vector &label_freq, vector &ans, vector> &tree_graph, vector &visited) 16 | { 17 | visited[start] = true; 18 | ans[start] = label_freq[labels[start] - 'a']; 19 | label_freq[labels[start] - 'a'] += 1; 20 | 21 | for (int neighbor : tree_graph[start]) 22 | { 23 | if (visited[neighbor]) 24 | continue; 25 | dfs(neighbor, labels, label_freq, ans, tree_graph, visited); 26 | } 27 | 28 | ans[start] = label_freq[labels[start] - 'a'] - ans[start]; 29 | } 30 | 31 | vector countSubTrees(int n, vector> &edges, string labels) 32 | { 33 | vector ans(n, 0); 34 | vector visited(n, false); 35 | vector> tree_graph(n, vector()); 36 | vector label_freq(26, 0); 37 | 38 | for (auto edge : edges) 39 | { 40 | tree_graph[edge[0]].push_back(edge[1]); 41 | tree_graph[edge[1]].push_back(edge[0]); 42 | } 43 | 44 | dfs(0, labels, label_freq, ans, tree_graph, visited); 45 | 46 | return ans; 47 | } 48 | }; 49 | 50 | // Time complexity: O(n) 51 | // Space complexity: O(n) -------------------------------------------------------------------------------- /1. January/Day13LongestPathWithDifferentAdjacentCharacters.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day13LongestPathWithDifferentAdjacentCharacters.cpp 3 | * @author Ginny Dang 4 | * @brief 2246. Longest Path With Different Adjacent Characters (https://leetcode.com/problems/longest-path-with-different-adjacent-characters/description/) 5 | * @version 0.1 6 | * @date 2023-01-12 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * @brief Idea learned from the discussion forum 14 | * Every recursion cycle has 2 largest branches. 15 | * The sum of these branches and 1 (meaning the start node of the cycle) can be the longest path we need. 16 | */ 17 | 18 | /** 19 | * @brief Algorithm learned from the discussion forum 20 | * Start from the source node 21 | * For each recursion cycle starting from each node 22 | * - Keep track of the 2 largest branches starting from the current node 23 | * - Iterate over each of the current node' children 24 | * --- For each child, call dfs on it to calc its longest result path 25 | * --- If the current child has the same letter as its parent, skip it 26 | * --- Otherwise 27 | * ------ Update the values of the 2 longest branches 28 | * ------ Update the final answer 29 | */ 30 | 31 | class Solution 32 | { 33 | public: 34 | int result; 35 | 36 | int dfs(int start, vector> &graph, vector &visited, string &s) 37 | { 38 | visited[start] = true; 39 | 40 | int max_length1 = 0; // 1st largest branch of start node 41 | int max_length2 = 0; // 2nd largest branch of start node 42 | 43 | for (int neighbor : graph[start]) 44 | { 45 | if (visited[neighbor]) 46 | continue; 47 | int prev_lenght = dfs(neighbor, graph, visited, s); 48 | if (s[neighbor] == s[start]) 49 | continue; 50 | if (prev_lenght > max_length1) 51 | { 52 | max_length2 = max_length1; 53 | max_length1 = prev_lenght; 54 | } 55 | else 56 | max_length2 = max(max_length2, prev_lenght); 57 | } 58 | 59 | result = max(result, 1 + max_length1 + max_length2); 60 | 61 | return 1 + max_length1; 62 | } 63 | 64 | int longestPath(vector &parent, string s) 65 | { 66 | result = 1; 67 | 68 | int n = parent.size(); 69 | vector visited(n, false); 70 | 71 | vector> graph(n, vector()); 72 | for (int i = 1; i < n; i++) 73 | { 74 | graph[parent[i]].push_back(i); 75 | graph[i].push_back(parent[i]); 76 | } 77 | 78 | dfs(0, graph, visited, s); 79 | 80 | return result; 81 | } 82 | }; 83 | 84 | // Time Complexity: O(n) 85 | // Space Complexity: O(n) -------------------------------------------------------------------------------- /1. January/Day14LexicographicallySmallestEquivalentString.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day14LexicographicallySmallestEquivalentString.cpp 3 | * @author Ginny Dang 4 | * @brief 1061. Lexicographically Smallest Equivalent String (https://leetcode.com/problems/lexicographically-smallest-equivalent-string/description/) 5 | * @version 0.1 6 | * @date 2023-01-13 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * @brief High level idea 14 | * Using Disjoint Set - Union Find 15 | * For each set, the smallest letter is the parent 16 | */ 17 | 18 | #define MAX 26 19 | 20 | class DisjointSet 21 | { 22 | private: 23 | int parent[MAX]; 24 | 25 | public: 26 | void make_set(int v) 27 | { 28 | parent[v] = v; 29 | } 30 | 31 | int find_set(int v) 32 | { 33 | return v == parent[v] ? v : parent[v] = find_set(parent[v]); 34 | } 35 | 36 | void union_sets(int u, int v) 37 | { 38 | u = find_set(u); 39 | v = find_set(v); 40 | 41 | if (u == v) 42 | return; 43 | 44 | int minParent = min(u, v); 45 | int maxParent = max(u, v); 46 | parent[maxParent] = minParent; 47 | } 48 | }; 49 | 50 | class Solution 51 | { 52 | public: 53 | string smallestEquivalentString(string s1, string s2, string baseStr) 54 | { 55 | int n = s1.length(); 56 | DisjointSet dsu = DisjointSet(); 57 | 58 | for (int i = 0; i < MAX; i++) 59 | dsu.make_set(i); 60 | 61 | for (int i = 0; i < n; i++) 62 | dsu.union_sets(s1[i] - 'a', s2[i] - 'a'); 63 | 64 | string result = ""; 65 | for (int i = 0; i < baseStr.length(); i++) 66 | { 67 | int rep = dsu.find_set(baseStr[i] - 'a'); // representative aka parent of each set 68 | result += (char)('a' + rep); 69 | } 70 | 71 | return result; 72 | } 73 | }; 74 | 75 | // Time Complexity: O(n) 76 | // Space Complexity: O(1) or O(2 * 26) to be exact -------------------------------------------------------------------------------- /1. January/Day15NumberOfGoodPaths.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day15NumberOfGoodPaths.cpp 3 | * @author Ginny Dang 4 | * @brief 2421. Number of Good Paths (https://leetcode.com/problems/number-of-good-paths/description/) 5 | * @version 0.1 6 | * @date 2023-01-15 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * @brief Idea learned from the official solution 14 | * Nodes whose values are equal to the smallest value cannot form any good path with length greater than 1 -> Sort all nodes by their values 15 | * Start from the smallest value X 16 | * - Find all components of nodes whose values are equal to X 17 | * - For each component of N nodes with value X, the number of good paths starting and ending at value X is N * (N - 1) / 2 18 | * Move to the very next higher value X + 1 19 | * - Add all nodes whose values are X + 1 to the components found in the previous step 20 | * - Repeat the same process as in the previous step to compute all good paths starting with the value of X + 1 21 | * - The node with value X can serve as intermediate nodes in a good path starting and ending with value X + 1 22 | * Continue with other values in order. After finishing all iterations, we'll have a complete tree 23 | */ 24 | 25 | class DisjointSetUnion 26 | { 27 | private: 28 | vector parent, rank; 29 | 30 | public: 31 | DisjointSetUnion(int size) 32 | { 33 | parent.resize(size); 34 | rank.resize(size, 0); 35 | for (int i = 0; i < size; i++) 36 | parent[i] = i; 37 | } 38 | 39 | int find_set(int v) 40 | { 41 | return v == parent[v] ? v : parent[v] = find_set(parent[v]); 42 | } 43 | 44 | void union_set(int u, int v) 45 | { 46 | u = find_set(u); 47 | v = find_set(v); 48 | 49 | if (u == v) 50 | return; 51 | else if (rank[u] < rank[v]) 52 | parent[u] = v; 53 | else if (rank[u] > rank[v]) 54 | parent[v] = u; 55 | else 56 | { 57 | parent[v] = u; 58 | rank[u]++; 59 | } 60 | } 61 | }; 62 | 63 | class Solution 64 | { 65 | public: 66 | int numberOfGoodPaths(vector &vals, vector> &edges) 67 | { 68 | int n = vals.size(); 69 | vector> graph(n, vector()); 70 | for (auto &edge : edges) 71 | { 72 | graph[edge[0]].push_back(edge[1]); 73 | graph[edge[1]].push_back(edge[0]); 74 | } 75 | 76 | map> valuesToNodes; 77 | for (int node = 0; node < n; node++) 78 | valuesToNodes[vals[node]].push_back(node); 79 | 80 | DisjointSetUnion dsu(n); 81 | int result = 0; 82 | 83 | for (auto &[value, nodes] : valuesToNodes) 84 | { 85 | for (int node : nodes) 86 | for (int neighbor : graph[node]) 87 | if (vals[node] >= vals[neighbor]) 88 | dsu.union_set(node, neighbor); 89 | 90 | unordered_map group; 91 | 92 | for (int node : nodes) 93 | group[dsu.find_set(node)]++; 94 | 95 | for (auto &[aSet, size] : group) 96 | result += (size * (size + 1) / 2); 97 | } 98 | return result; 99 | } 100 | }; 101 | 102 | // Time Complexity: O(NlogN) 103 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /1. January/Day16InsertInterval.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day16InsertInterval.cpp 3 | * @author Ginny Dang 4 | * @brief 57. Insert Interval (https://leetcode.com/problems/insert-interval/description/) 5 | * @version 0.1 6 | * @date 2023-01-16 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | vector> insert(vector> &intervals, vector &newInterval) 16 | { 17 | vector> result; 18 | int start = newInterval[0]; 19 | int end = newInterval[1]; 20 | 21 | for (auto &interval : intervals) 22 | { 23 | if (newInterval[0] > interval[1] || newInterval[1] < interval[0]) 24 | { 25 | if (interval[0] < start) 26 | result.push_back(interval); 27 | } 28 | else 29 | { 30 | start = min(start, interval[0]); 31 | end = max(end, interval[1]); 32 | } 33 | } 34 | 35 | result.push_back({start, end}); 36 | 37 | for (auto &interval : intervals) 38 | { 39 | if (interval[0] > end) 40 | result.push_back(interval); 41 | } 42 | 43 | return result; 44 | } 45 | }; 46 | 47 | // Time Complexity: O(N) 48 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /1. January/Day17FlipStringToMonotoneIncreasing.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day17FlipStringToMonotoneIncreasing.cpp 3 | * @author Ginny Dang 4 | * @brief 926. Flip String to Monotone Increasing (https://leetcode.com/problems/flip-string-to-monotone-increasing/description/) 5 | * @version 0.1 6 | * @date 2023-01-16 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * @brief New idea learned from the Official Solution 14 | * Approach 1: Dynamic Windows 15 | * - Consider the 2 substrings as 2 windows on the original string 16 | * -- Initially, the left window is empty and the right window contains the whole original string. 17 | * -- At each step, the left window's size increases by one and the right window's size decreases by 1. 18 | * We want to change all the characters in the left window into '0' and all the characters in the right window into '1'. 19 | * - We enumerate each left-right window configuration, 20 | * the number of flips to make the string monotone increasing is the sum of the number of '1's in the left window and the number of '0's in the right window. 21 | * - Save the smallest value. 22 | */ 23 | 24 | /** 25 | * @brief Algorithm learned from the Official Solution 26 | * - Count the number of '0's in string s. 27 | * - Let m, which is the number of flips needed when the left window is empty and the right window is the whole string, be the above value. 28 | * - Set result = m. 29 | * - Scan the input string 's' again 30 | * -- For each character '0', decrease m by 1 and replace result with m if m is smaller. 31 | * -- For each character '1', increase m by 1. 32 | * - Return result. 33 | */ 34 | 35 | class Solution1 36 | { 37 | public: 38 | int minFlipsMonoIncr(string s) 39 | { 40 | int m = 0; // the number of flips needed when the left window is empty and the right window is the whole string 41 | for (char c : s) 42 | if (c == '0') 43 | m++; 44 | 45 | int result = m; 46 | for (char c : s) 47 | { 48 | if (c == '0') 49 | { 50 | m--; 51 | result = min(result, m); 52 | } 53 | else 54 | m++; 55 | } 56 | return result; 57 | } 58 | }; 59 | 60 | // Time Complexity: O(n) 61 | // Space Complexity: O(1) 62 | 63 | /** 64 | * @brief New idea learned from the Official Solution 65 | * Approach 2: Dynamic Programming 66 | * - Let dp[i] represent the minimum number of flips to make the prefix of s of length i 67 | * - Set the base case dp[0] = 0 68 | * - Let num1s be the number of 1's from the begining of the string to right before i 69 | * - For each step i in the range [1, s.length()] 70 | * -- If s[i - 1] = 1 -> Min num of flips is 0 and num1s increments 71 | * -- If s[i - 1] = 0 72 | * --- If we don't flip s[i] -> Need to flips all num1s 1's before as well 73 | * --- If we flip s[i] -> dp[i] = dp[i - 1] + 1 74 | * - Return dp[s.length()] 75 | */ 76 | 77 | /** 78 | * @brief Naive implementation 79 | */ 80 | 81 | class Solution2 82 | { 83 | public: 84 | int minFlipsMonoIncr(string s) 85 | { 86 | vector dp(s.length() + 1, 0); 87 | dp[0] = 0; 88 | int num1s = s[0] == 1 ? 1 : 0; // the number of character 1s in so far 89 | for (int i = 1; i <= s.length(); i++) 90 | { 91 | if (s[i - 1] == '1') 92 | { 93 | dp[i] = dp[i - 1]; 94 | num1s++; 95 | } 96 | else 97 | dp[i] = min(num1s, dp[i - 1] + 1); 98 | } 99 | return dp[s.length()]; 100 | } 101 | }; 102 | 103 | // Time Complexity: O(N) 104 | // Space Complexity: O(N) 105 | 106 | /** 107 | * @brief Optimized implementation with no extra space 108 | */ 109 | 110 | class Solution3 111 | { 112 | public: 113 | int minFlipsMonoIncr(string s) 114 | { 115 | int minFlips = 0; 116 | int num1s = s[0] == 1 ? 1 : 0; // the number of character 1s in so far 117 | 118 | for (int i = 1; i <= s.length(); i++) 119 | { 120 | if (s[i - 1] == '1') 121 | num1s++; 122 | else 123 | minFlips = min(num1s, minFlips + 1); 124 | } 125 | 126 | return minFlips; 127 | } 128 | }; 129 | 130 | // Time Complexity: O(N) 131 | // Space Complexity: O(1) 132 | -------------------------------------------------------------------------------- /1. January/Day18MaximumSumCircularSubarray.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day18MaximumSumCircularSubarray.cpp 3 | * @author Ginny Dang 4 | * @brief 918. Maximum Sum Circular Subarray (https://leetcode.com/problems/maximum-sum-circular-subarray/description/) 5 | * @version 0.1 6 | * @date 2023-01-17 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * @brief Idea 14 | * - 2 types of subarrays 15 | * -- Type 1: Subarray in the middle 16 | * -- Type 2: Subarray split across 17 | * - Find the max sum subarray in the middle 18 | * - Find the max sum subarray split across 19 | * -- Find the min sum subarray in the middle 20 | * --- In [0, len(nums) - 1] 21 | * --- In [1, len(nums)] 22 | * -- sum(nums) - min_sum 23 | * -> Finalize the max sum 24 | */ 25 | 26 | class Solution 27 | { 28 | public: 29 | int maxSubarraySum(vector &nums) 30 | { 31 | int maxSum = nums[0]; 32 | int maxSoFar = nums[0]; 33 | 34 | for (int i = 1; i < nums.size(); i++) 35 | { 36 | maxSoFar = max(maxSoFar + nums[i], nums[i]); 37 | maxSum = max(maxSum, maxSoFar); 38 | } 39 | 40 | return maxSum; 41 | } 42 | 43 | int minSubarraySum(vector &nums, int start, int end) 44 | { 45 | int minSum = nums[start]; 46 | int minSoFar = nums[start]; 47 | 48 | for (int i = start + 1; i <= end; i++) 49 | { 50 | minSoFar = min(minSoFar + nums[i], nums[i]); 51 | minSum = min(minSum, minSoFar); 52 | } 53 | 54 | return minSum; 55 | } 56 | 57 | int maxSubarraySumCircular(vector &nums) 58 | { 59 | // Edge case 60 | if (nums.size() == 1) 61 | return nums[0]; 62 | 63 | // Find the max sum subarray in the middle 64 | int maxSum1 = maxSubarraySum(nums); 65 | 66 | // Find the min sum subarray in the middle 67 | int minSum1 = minSubarraySum(nums, 0, nums.size() - 2); 68 | int minSum2 = minSubarraySum(nums, 1, nums.size() - 1); 69 | 70 | // Find the max sum subarray split across 71 | int maxSum2 = accumulate(nums.begin(), nums.end(), 0) - min(minSum1, minSum2); 72 | 73 | return max(maxSum1, maxSum2); 74 | } 75 | }; 76 | 77 | // Time Complexity: O(N) 78 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /1. January/Day19SubarraySumsDivisibleByK.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day19SubarraySumsDivisibleByK.cpp 3 | * @author Ginny Dang 4 | * @brief 974. Subarray Sums Divisible by K (https://leetcode.com/problems/subarray-sums-divisible-by-k/description/) 5 | * @version 0.1 6 | * @date 2023-01-18 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int subarraysDivByK(vector &nums, int k) 16 | { 17 | int result = 0; 18 | int n = nums.size(); 19 | int prefixMod = 0; // the remainder when the sum of the elements of a subarray that start from index 0 is divided by k 20 | vector modGroups(k, 0); 21 | 22 | modGroups[0] = 1; 23 | 24 | for (int i = 0; i < n; i++) 25 | { 26 | prefixMod = (prefixMod + nums[i] % k + k) % k; 27 | result += modGroups[prefixMod]; 28 | modGroups[prefixMod]++; 29 | } 30 | 31 | return result; 32 | } 33 | }; 34 | 35 | // Time Complexity: O(n + k) 36 | // Space Complexity: O(k) -------------------------------------------------------------------------------- /1. January/Day1WordPattern.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day1WordPattern.cpp 3 | * @author Ginny Dang 4 | * @brief 290. Word Pattern (https://leetcode.com/problems/word-pattern/) 5 | * @version 0.1 6 | * @date 2023-01-01 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | bool wordPattern(string pattern, string s) 16 | { 17 | // Split the given string into words 18 | stringstream ss(s); 19 | string word; 20 | vector words; 21 | while (getline(ss, word, ' ')) 22 | { 23 | words.push_back(word); 24 | } 25 | 26 | if (words.size() != pattern.length()) 27 | return false; 28 | 29 | // Match each letter in pattern to a word 30 | map charToWord; 31 | for (int i = 0; i < pattern.length(); i++) 32 | { 33 | if (charToWord.count(pattern[i])) 34 | { 35 | if (charToWord[pattern[i]].compare(words[i]) != 0) 36 | return false; 37 | } 38 | else 39 | charToWord[pattern[i]] = words[i]; 40 | } 41 | 42 | // Match each word to a letter in pattern 43 | map wordToChar; 44 | for (int i = 0; i < words.size(); i++) 45 | { 46 | if (wordToChar.count(words[i])) 47 | { 48 | if (wordToChar[words[i]] != pattern[i]) 49 | return false; 50 | } 51 | else 52 | wordToChar[words[i]] = pattern[i]; 53 | } 54 | 55 | // Compare 56 | for (auto pair : charToWord) 57 | if (pair.first != wordToChar[pair.second]) 58 | return false; 59 | 60 | return true; 61 | } 62 | }; 63 | 64 | // Time Complexity: O(N) 65 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /1. January/Day20NonDecreasingSubsequences.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day20NonDecreasingSubsequences.cpp 3 | * @author Ginny Dang 4 | * @brief 491. Non-decreasing Subsequences (https://leetcode.com/problems/non-decreasing-subsequences/description/) 5 | * @version 0.1 6 | * @date 2023-01-20 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * @brief Backtracking with set 14 | */ 15 | 16 | class Solution1 17 | { 18 | public: 19 | void search(vector &nums, set> &subsequences, int k, int n, vector &subsequence, bool wasChosen) 20 | { 21 | if (k == n) 22 | { 23 | if (subsequence.size() >= 2) 24 | subsequences.insert(subsequence); 25 | } 26 | else 27 | { 28 | // Include nums[k] in the current subset 29 | if (!(k - 1 >= 0 && nums[k] == nums[k - 1] && !wasChosen)) 30 | { 31 | if (subsequence.empty() || subsequence[subsequence.size() - 1] <= nums[k]) 32 | { 33 | subsequence.push_back(nums[k]); 34 | search(nums, subsequences, k + 1, n, subsequence, true); 35 | subsequence.pop_back(); 36 | } 37 | } 38 | // Dont include nums[k] in the current subset 39 | search(nums, subsequences, k + 1, n, subsequence, false); 40 | } 41 | } 42 | 43 | vector> findSubsequences(vector &nums) 44 | { 45 | int n = nums.size(); 46 | set> subsequences; 47 | vector subsequence; 48 | search(nums, subsequences, 0, n, subsequence, false); 49 | return vector>(subsequences.begin(), subsequences.end()); 50 | } 51 | }; 52 | 53 | // Time Complexity: ~O(2^N * N * log(2^N)) (worst case) 54 | // Space Complexity: ~O(2^N * N) (worst case) 55 | 56 | /** 57 | * @brief Optimizing backtracking with unordered map 58 | */ 59 | class Solution2 60 | { 61 | public: 62 | void search(vector &nums, vector> &subsequences, int k, int n, vector &subsequence, int lastChosen, unordered_map &lastAppearance) 63 | { 64 | if (k == n) 65 | { 66 | if (subsequence.size() >= 2) 67 | subsequences.push_back(subsequence); 68 | } 69 | else 70 | { 71 | // search(nums, subsequences, k + 1, n, subsequence, false); 72 | bool isSkipped = false; 73 | // Check if nums[k] is skipped 74 | if (lastAppearance.count(nums[k]) && lastAppearance[nums[k]] > lastChosen) 75 | isSkipped = true; 76 | int oldLastAppearance = -1; 77 | if (lastAppearance.count(nums[k])) 78 | oldLastAppearance = lastAppearance[nums[k]]; 79 | lastAppearance[nums[k]] = k; 80 | if (isSkipped) 81 | search(nums, subsequences, k + 1, n, subsequence, lastChosen, lastAppearance); 82 | else 83 | { 84 | // Include nums[k] in the current subset 85 | if (subsequence.empty() || subsequence[subsequence.size() - 1] <= nums[k]) 86 | { 87 | subsequence.push_back(nums[k]); 88 | search(nums, subsequences, k + 1, n, subsequence, k, lastAppearance); 89 | subsequence.pop_back(); 90 | } 91 | // Dont include nums[k] in the current subset 92 | search(nums, subsequences, k + 1, n, subsequence, lastChosen, lastAppearance); 93 | } 94 | lastAppearance[nums[k]] = oldLastAppearance; 95 | } 96 | } 97 | 98 | vector> findSubsequences(vector &nums) 99 | { 100 | int n = nums.size(); 101 | vector> subsequences; 102 | vector subsequence; 103 | unordered_map lastAppearance; 104 | search(nums, subsequences, 0, n, subsequence, -1, lastAppearance); 105 | return subsequences; 106 | } 107 | }; 108 | 109 | // Time Complexity: ~O(2^N * N) (worst case) 110 | // Space Complexity: ~O(2^N * N) (worst case) -------------------------------------------------------------------------------- /1. January/Day21RestoreIPAddresses.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day21RestoreIPAddresses.cpp 3 | * @author Ginny Dang 4 | * @brief 93. Restore IP Addresses (https://leetcode.com/problems/restore-ip-addresses/description/) 5 | * @version 0.1 6 | * @date 2023-01-21 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | bool valid(string &s, int start, int length) 16 | { 17 | return length == 1 || (s[start] != '0' && (length < 3 || s.substr(start, length) <= "255")); 18 | } 19 | 20 | void search(string &s, int start, vector &dots, vector &ips) 21 | { 22 | int remainingLength = s.length() - start; // the string length we want to process 23 | int remainingNumberOfIntegers = 4 - dots.size(); // number of integers we have left to form 24 | 25 | // Make sure that each integer has 0 to 3 digits 26 | if (remainingLength > remainingNumberOfIntegers * 3 || remainingLength < remainingNumberOfIntegers) 27 | return; 28 | 29 | if (remainingNumberOfIntegers == 1) 30 | { 31 | if (valid(s, start, remainingLength)) 32 | { 33 | string ip = ""; 34 | int last = 0; 35 | for (int dot : dots) 36 | { 37 | ip += s.substr(last, dot) + '.'; 38 | last += dot; 39 | } 40 | ip += s.substr(start); 41 | ips.push_back(ip); 42 | } 43 | return; 44 | } 45 | 46 | for (int pos = 1; pos <= min(3, remainingLength); pos++) 47 | { 48 | dots.push_back(pos); 49 | if (valid(s, start, pos)) 50 | search(s, start + pos, dots, ips); 51 | dots.pop_back(); 52 | } 53 | } 54 | 55 | vector restoreIpAddresses(string s) 56 | { 57 | vector ips; 58 | vector dots; // saves distances for the dots we have added so far 59 | 60 | search(s, 0, dots, ips); 61 | 62 | return ips; 63 | } 64 | }; 65 | 66 | // Time Complexity: O(M^N * N) 67 | // Space Complexity: O(MN) -------------------------------------------------------------------------------- /1. January/Day22PalindromePartitioning.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day22PalindromePartitioning.cpp 3 | * @author Ginny Dang 4 | * @brief 131. Palindrome Partitioning (https://leetcode.com/problems/palindrome-partitioning/description/) 5 | * @version 0.1 6 | * @date 2023-01-22 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | bool isPalindrome(string &s, int left, int right) 16 | { 17 | while (left <= right) 18 | { 19 | if (s[left] != s[right]) 20 | return false; 21 | else 22 | { 23 | left++; 24 | right--; 25 | } 26 | } 27 | 28 | return true; 29 | } 30 | 31 | void search(string &s, int start, vector &breakPoints, vector> &palindromeLists) 32 | { 33 | if (start == s.length()) 34 | { 35 | vector palindromes; 36 | int last = 0; 37 | for (int bp : breakPoints) 38 | { 39 | palindromes.push_back(s.substr(last, bp - last + 1)); 40 | last = bp + 1; 41 | } 42 | palindromeLists.push_back(palindromes); 43 | } 44 | else 45 | { 46 | // Break point right after start 47 | if (isPalindrome(s, breakPoints.size() ? breakPoints[breakPoints.size() - 1] + 1 : 0, start)) 48 | { 49 | breakPoints.push_back(start); 50 | search(s, start + 1, breakPoints, palindromeLists); 51 | breakPoints.pop_back(); 52 | } 53 | // No break point right after start 54 | if (start != s.length() - 1) 55 | search(s, start + 1, breakPoints, palindromeLists); 56 | } 57 | } 58 | 59 | vector> partition(string s) 60 | { 61 | vector> palindromeLists; 62 | vector breakPoints; // ending points of all palindrome substrings 63 | 64 | search(s, 0, breakPoints, palindromeLists); 65 | 66 | return palindromeLists; 67 | } 68 | }; 69 | 70 | // Time Complexity: O(2^N * N) 71 | // Space Complexity: O(2^N * N) -------------------------------------------------------------------------------- /1. January/Day23FindTheTownJudge.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day23FindTheTownJudge.cpp 3 | * @author Ginny Dang 4 | * @brief 997. Find the Town Judge (https://leetcode.com/problems/find-the-town-judge/description/) 5 | * @version 0.1 6 | * @date 2023-01-22 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int findJudge(int n, vector> &trust) 16 | { 17 | int judge = -1; 18 | vector indegrees(n + 1, 0); 19 | vector outdegrees(n + 1, 0); 20 | 21 | for (auto conn : trust) 22 | { 23 | indegrees[conn[1]]++; 24 | outdegrees[conn[0]]++; 25 | } 26 | 27 | for (int i = 1; i <= n; i++) 28 | { 29 | if (indegrees[i] == n - 1 && outdegrees[i] == 0) 30 | { 31 | judge = i; 32 | break; 33 | } 34 | } 35 | 36 | return judge; 37 | } 38 | }; 39 | 40 | // Time Complexity: O(E) 41 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /1. January/Day24SnakesAndLadders.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day24SnakesAndLadders.cpp 3 | * @author Ginny Dang 4 | * @brief 909. Snakes and Ladders (https://leetcode.com/problems/snakes-and-ladders/description/) 5 | * @version 0.1 6 | * @date 2023-01-23 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * @brief Idea 14 | * - Make a new n x n board filled with numbers following the Boustrophedon style 15 | * -- 1st row (bottom row) left -> right 16 | * -- 2nd row right -> left 17 | * -- ... 18 | * -- nth row (top row): 19 | * ---- if n is odd: left -> right 20 | * ---- else: right -> left 21 | * count: level of the current cell 22 | * - Graph: 23 | * -- Vertices: all cells in the grid 24 | * -- Edges: cur -> cur_next 25 | * + cur_next lie between [cur + 1, min(cur + 6, n** 2)] 26 | * if cur_next == -1 -> stop the current jump -> edge: cur -> cur_next 27 | * if cur_next is a snake or ladder -> jump to the destination of that snake or ladder -> edge: cur -> dest(cur_next) 28 | * - Find shortest path -> Do BFS from the starting point only 29 | */ 30 | 31 | class Solution 32 | { 33 | public: 34 | int snakesAndLadders(vector> &board) 35 | { 36 | // Create a new grid in Boustrophedon style 37 | int n = board.size(); 38 | int cells = pow(n, 2); 39 | vector> newGrid(n, vector(n, 0)); // Store all levels of all cell 40 | int count = 1; // Level of the current cell 41 | 42 | // Fill the new grid with numbers 43 | int dir = 1; // 1 means left -> right, -1 means right -> left 44 | for (int i = n - 1; i > -1; i--) 45 | { 46 | // Left to right 47 | if (dir == 1) 48 | { 49 | for (int j = 0; j < n; j++) 50 | { 51 | newGrid[i][j] = count; 52 | count++; 53 | } 54 | } 55 | // Right to left 56 | else 57 | { 58 | for (int j = n - 1; j > -1; j--) 59 | { 60 | newGrid[i][j] = count; 61 | count++; 62 | } 63 | } 64 | // Change direction after filling out each line 65 | dir *= -1; 66 | } 67 | 68 | // Save the coordinates of n^2 cells 69 | vector> coordinates(cells + 1, vector()); 70 | for (int i = 0; i < n; i++) 71 | { 72 | for (int j = 0; j < n; j++) 73 | { 74 | coordinates[newGrid[i][j]].push_back(i); 75 | coordinates[newGrid[i][j]].push_back(j); 76 | } 77 | } 78 | 79 | // Traverse every vertex (cell) 80 | vector> neighbors(cells + 1, vector()); 81 | for (int i = 0; i < n; i++) 82 | { 83 | for (int j = 0; j < n; j++) 84 | { 85 | int curr = newGrid[i][j]; 86 | for (int k = curr + 1; k <= min(curr + 6, cells); k++) 87 | { 88 | // Neither snake nor ladder starting at cur_next 89 | if (board[coordinates[k][0]][coordinates[k][1]] == -1) 90 | neighbors[curr].push_back(k); 91 | // Either snake or ladder starting at cur_next 92 | else 93 | neighbors[curr].push_back(board[coordinates[k][0]][coordinates[k][1]]); // cur -> cur_next -> board[coordinates[k][0]][coordinates[k][1]] 94 | } 95 | } 96 | } 97 | 98 | // BFS 99 | vector moves(cells + 1, -1); // moves[i] is the min number of moves from 1 to i 100 | queue q; 101 | q.push(1); 102 | moves[1] = 0; 103 | while (!q.empty()) 104 | { 105 | int curr = q.front(); 106 | q.pop(); 107 | for (int neighbor : neighbors[curr]) 108 | { 109 | if (moves[neighbor] == -1) 110 | { 111 | moves[neighbor] = moves[curr] + 1; 112 | q.push(neighbor); 113 | } 114 | } 115 | } 116 | 117 | return moves[cells]; 118 | } 119 | }; 120 | 121 | // Time Complexity: O(N^2) 122 | // Space Complexity: O(N^2) -------------------------------------------------------------------------------- /1. January/Day25FindClosestNodeToGivenTwoNodes.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day25FindClosestNodeToGivenTwoNodes.cpp 3 | * @author Ginny Dang 4 | * @brief 2359. Find Closest Node to Given Two Nodes (https://leetcode.com/problems/find-closest-node-to-given-two-nodes/description/) 5 | * @version 0.1 6 | * @date 2023-01-24 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * @brief Idea 14 | * - BFS from node1 to find distances from it to all other nodes 15 | * - BFS from node2 to find distances from it to all other nodes 16 | * - Filter out nodes that can be reached from both node1 and node2 17 | * -- For each of these nodes, find max(dist1[i], dist2[i]) 18 | * -- Get the min of these above values 19 | */ 20 | 21 | class Solution 22 | { 23 | public: 24 | vector calcDistances(int node, vector> &graph, int n) 25 | { 26 | vector dist(n, -1); 27 | queue q; 28 | 29 | dist[node] = 0; 30 | q.push(node); 31 | 32 | while (!q.empty()) 33 | { 34 | int curr = q.front(); 35 | q.pop(); 36 | if (graph[curr].size() && dist[graph[curr][0]] == -1) 37 | { 38 | dist[graph[curr][0]] = dist[curr] + 1; 39 | q.push(graph[curr][0]); 40 | } 41 | } 42 | 43 | return dist; 44 | } 45 | 46 | int closestMeetingNode(vector &edges, int node1, int node2) 47 | { 48 | int n = edges.size(); 49 | vector> graph(n, vector()); 50 | for (int i = 0; i < n; i++) 51 | if (edges[i] != -1) 52 | graph[i].push_back(edges[i]); 53 | 54 | vector dist1 = calcDistances(node1, graph, n); 55 | vector dist2 = calcDistances(node2, graph, n); 56 | int minMutualDist = 10e5; 57 | for (int i = 0; i < n; i++) 58 | if (dist1[i] != -1 && dist2[i] != -1) 59 | minMutualDist = min(minMutualDist, max(dist1[i], dist2[i])); 60 | 61 | for (int i = 0; i < n; i++) 62 | if (dist1[i] != -1 && dist2[i] != -1) 63 | if (max(dist1[i], dist2[i]) == minMutualDist) 64 | return i; 65 | 66 | return -1; 67 | } 68 | }; 69 | 70 | // Time Complexity: O(N) 71 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /1. January/Day26CheapestFlightsWithinKStops.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day26CheapestFlightsWithinKStops.cpp 3 | * @author Ginny Dang 4 | * @brief 787. Cheapest Flights Within K Stops (https://leetcode.com/problems/cheapest-flights-within-k-stops/description/) 5 | * @version 0.1 6 | * @date 2023-01-25 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * @brief New idea learned from the Official Solution 14 | * - This problem limits the number of stops to k -> No need to search the paths with lengths greater than k + 1. 15 | * - BFS can be used for this problem because the number of levels to be explored is bounded by k. 16 | * - We perform a level-wise iteration over the nodes. 17 | * -- We explore all the nodes at the present level (say l) before moving on to the nodes at the next level (l + 1). 18 | * --- This level would correspond to the number of stops that would be limited by k. 19 | * -- When we move from a level of l to l + 1, we will increase the stops by 1. 20 | * --- We are allowed a maximum of k stops, which means we could go up to a maximum level of k + 1 from the src node, trying to reach dst at the minimum price. 21 | * - We can maintain an array dist which stores the minimum price to reach each node. 22 | * -- When we want to move to a node, we only consider edges where the total price after traversing the edge is less than the currently calculated dist[node]. 23 | */ 24 | 25 | class Solution 26 | { 27 | public: 28 | int bfs(int n, vector>> &graph, vector &dist, int src, int dst, int k) 29 | { 30 | queue> q; 31 | q.push({src, 0}); 32 | int stops = 0; 33 | 34 | while (stops <= k && !q.empty()) 35 | { 36 | int size = q.size(); 37 | while (size--) 38 | { 39 | auto [u, uDist] = q.front(); 40 | q.pop(); 41 | for (auto &[v, vPrice] : graph[u]) 42 | { 43 | if (vPrice + uDist < dist[v]) 44 | { 45 | dist[v] = vPrice + uDist; 46 | q.push({v, dist[v]}); 47 | } 48 | } 49 | } 50 | stops++; 51 | } 52 | 53 | return dist[dst] == numeric_limits::max() ? -1 : dist[dst]; 54 | } 55 | 56 | int findCheapestPrice(int n, vector> &flights, int src, int dst, int k) 57 | { 58 | vector>> graph(n, vector>()); 59 | for (auto &flight : flights) 60 | graph[flight[0]].push_back({flight[1], flight[2]}); 61 | 62 | vector dist(n, numeric_limits::max()); 63 | return bfs(n, graph, dist, src, dst, k); 64 | } 65 | }; 66 | 67 | // Time Complexity: O(N + EK) 68 | // Space Complexity: O(N + EK) -------------------------------------------------------------------------------- /1. January/Day27ConcatenatedWords.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day27ConcatenatedWords.cpp 3 | * @author Ginny Dang 4 | * @brief 472. Concatenated Words (https://leetcode.com/problems/concatenated-words/description/) 5 | * @version 0.1 6 | * @date 2023-01-27 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * @brief New idea learned from the Official Solution 14 | * - For each word, construct an implicit graph 15 | * -- All prefixes are nodes. Each prefix aka node is represented by its length in range [0, word.length] 16 | * -- There're (word.length + 1) nodes in each graph 17 | * -- There's a directed edge from node i to node j, if there're prefixes i and j such that 18 | * ---- 0 <= i < j <= word.length and 19 | * ---- prefix j = prefix i + word in the input 20 | * - DFS on each word's graph 21 | * -- Add that word to the answer if 22 | * ---- The node word.length can be reached from node 0 in the graph 23 | */ 24 | 25 | class Solution 26 | { 27 | public: 28 | bool dfs(string &word, int prefixLength, vector &visited, unordered_set &allWords) 29 | { 30 | if (prefixLength == word.length()) 31 | return true; 32 | 33 | if (visited[prefixLength]) 34 | return false; 35 | 36 | visited[prefixLength] = true; 37 | 38 | /* 39 | * prefixLength = 0 -> None of the non-empty prefix/nodes has been explored 40 | * prefixLength > 0 -> Some of the non-empty prefix/nodes have been explored 41 | */ 42 | for (int i = word.length() - (prefixLength == 0 ? 1 : 0); i > prefixLength; i--) 43 | { 44 | // The prefix represented by the current prefixLength + 1 of the given words 45 | // becomes one of the remaining prefixes 46 | if (allWords.count(word.substr(prefixLength, i - prefixLength)) && dfs(word, i, visited, allWords)) 47 | return true; 48 | } 49 | 50 | return false; 51 | } 52 | 53 | vector findAllConcatenatedWordsInADict(vector &words) 54 | { 55 | vector concatenatedWords; 56 | unordered_set allWords(words.begin(), words.end()); 57 | 58 | for (string &word : words) 59 | { 60 | vector visited(word.length() + 1, false); 61 | if (dfs(word, 0, visited, allWords)) 62 | concatenatedWords.push_back(word); 63 | } 64 | 65 | return concatenatedWords; 66 | } 67 | }; 68 | 69 | // Time Complexity: O(M^3 * N) 70 | // Space Complexity: O(M * N) -------------------------------------------------------------------------------- /1. January/Day28DataStreamAsDisjointIntervals.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day28DataStreamAsDisjointIntervals.cpp 3 | * @author Ginny Dang 4 | * @brief 352. Data Stream as Disjoint Intervals (https://leetcode.com/problems/data-stream-as-disjoint-intervals/description/) 5 | * @version 0.1 6 | * @date 2023-01-28 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class SummaryRanges 13 | { 14 | unordered_set nums; 15 | vector> intervals; 16 | 17 | public: 18 | SummaryRanges() {} 19 | 20 | void addNum(int value) 21 | { 22 | // value has already been added to nums 23 | if (nums.count(value)) 24 | return; 25 | 26 | // value has not been added to nums 27 | nums.insert(value); 28 | 29 | // value is the very first element to be added 30 | if (intervals.empty()) 31 | { 32 | intervals.push_back({value, value}); 33 | return; 34 | } 35 | 36 | // value is not the very first element to be added -> adjust existing intervals 37 | vector> newIntervals; 38 | int pivot = 0; 39 | for (int i = 0; i < intervals.size(); i++) 40 | { 41 | // value is within the range [a - 1, b + 1] inclusively 42 | if (value >= intervals[i][0] - 1 && value <= intervals[i][1] + 1) 43 | { 44 | if (value == intervals[i][0] - 1) 45 | intervals[i][0] = value; 46 | else if (value == intervals[i][1] + 1) 47 | intervals[i][1] = value; 48 | newIntervals.push_back(intervals[i]); 49 | pivot = i + 1; 50 | break; 51 | } 52 | // value is somewhere strictly before [a, b] inclusively 53 | else if (value < intervals[i][0] - 1) 54 | { 55 | newIntervals.push_back({value, value}); 56 | newIntervals.push_back(intervals[i]); 57 | pivot = i + 1; 58 | break; 59 | } 60 | // value is somewhere strictly after [a, b] inclusively 61 | else if (value > intervals[i][1] + 1) 62 | { 63 | newIntervals.push_back(intervals[i]); 64 | if (i == intervals.size() - 1 || value < intervals[i + 1][0]) 65 | { 66 | newIntervals.push_back({value, value}); 67 | pivot = i + 1; 68 | break; 69 | } 70 | } 71 | } 72 | 73 | vector lastNew = newIntervals.size() ? newIntervals[newIntervals.size() - 1] : vector(); 74 | vector pivotOld = pivot < intervals.size() ? intervals[pivot] : vector(); 75 | vector nextNew = vector(); 76 | if (lastNew.size() && pivotOld.size()) 77 | { 78 | if (lastNew[1] == pivotOld[0] - 1) 79 | { 80 | nextNew.push_back(lastNew[0]); 81 | nextNew.push_back(pivotOld[1]); 82 | newIntervals.pop_back(); 83 | newIntervals.push_back(nextNew); 84 | pivot++; 85 | } 86 | } 87 | 88 | for (int i = pivot; i < intervals.size(); i++) 89 | newIntervals.push_back(intervals[i]); 90 | 91 | intervals = newIntervals; 92 | } 93 | 94 | vector> getIntervals() 95 | { 96 | return intervals; 97 | } 98 | }; 99 | 100 | /** 101 | * Your SummaryRanges object will be instantiated and called as such: 102 | * SummaryRanges* obj = new SummaryRanges(); 103 | * obj->addNum(value); 104 | * vector> param_2 = obj->getIntervals(); 105 | */ 106 | 107 | // Time Complexity: O(3x10e4N) 108 | // Space Complexity: O(3x10e4N) -------------------------------------------------------------------------------- /1. January/Day29LFUCache.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day29LFUCache.cpp 3 | * @author Ginny Dang 4 | * @brief 460. LFU Cache (https://leetcode.com/problems/lfu-cache/description/) 5 | * @version 0.1 6 | * @date 2023-01-29 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class LFUCache 13 | { 14 | unordered_map>::iterator>> cache; // key : (freq : iterator pointing to a list of {key : value} pairs) in the other map 15 | unordered_map>> frequencies; // freq : {{key1 : value1}, {key2 : value2}, {key3 : value3}, ...} 16 | int minFreq; // the minimum frequency at any given time 17 | int capacity; // the capacity given in the input 18 | 19 | void insert(int key, int val, int freq) 20 | { 21 | frequencies[freq].push_back({key, val}); 22 | cache[key] = {freq, --frequencies[freq].end()}; // --frequencies[freq].end() refers to the very last element of the list frequencies[freq] 23 | } 24 | 25 | public: 26 | LFUCache(int capacity) : minFreq(0), 27 | capacity(capacity) {} 28 | 29 | int get(int key) 30 | { 31 | // Get the iterator pointing to an entry in cache 32 | const auto keyItInCache = cache.find(key); 33 | 34 | // If this key does not exist in the cache 35 | if (keyItInCache == cache.end()) 36 | return -1; 37 | 38 | // If this key exists in the cache 39 | const pair>::iterator>> keyEntryInCache = *keyItInCache; 40 | const int freq = keyEntryInCache.second.first; // The frequency of this key 41 | const auto freqIt = keyEntryInCache.second.second; // The iterator associating with the frequency of this key 42 | const pair kv = *freqIt; // The actual (key : value) pair associating with freq in the frequencies unordered map 43 | //// Update frequencies and the min frequency 44 | frequencies[freq].erase(freqIt); // Can be understood as removing the old frequency of this key 45 | if (frequencies[freq].empty() && minFreq == freq) 46 | minFreq++; 47 | //// Insert this key to the cache 48 | insert(key, kv.second, freq + 1); 49 | return kv.second; 50 | } 51 | 52 | void put(int key, int value) 53 | { 54 | if (capacity <= 0) 55 | return; 56 | 57 | // Get the iterator pointing to an entry in cache 58 | const auto keyItInCache = cache.find(key); 59 | 60 | // If this key is already in the cache 61 | if (keyItInCache != cache.end()) 62 | { 63 | // Update the (new) value of this key 64 | keyItInCache->second.second->second = value; // keyItInCache->second is the frequency of this key 65 | // Update the new frequency of this key 66 | get(key); 67 | return; 68 | } 69 | // If this key is not in the cache 70 | //// If the capacity has been full 71 | if (cache.size() == capacity) 72 | { 73 | // Get the least frequently used key 74 | int leastFreqUsedKey = frequencies[minFreq].front().first; 75 | // Erase the least frequently used key 76 | cache.erase(leastFreqUsedKey); 77 | frequencies[minFreq].pop_front(); 78 | } 79 | //// Update the cache with the new key 80 | minFreq = 1; 81 | insert(key, value, minFreq); 82 | } 83 | }; 84 | 85 | /** 86 | * Your LFUCache object will be instantiated and called as such: 87 | * LFUCache* obj = new LFUCache(capacity); 88 | * int param_1 = obj->get(key); 89 | * obj->put(key,value); 90 | */ 91 | 92 | // Time complexity: O(1) 93 | // Space complexity: O(N) -------------------------------------------------------------------------------- /1. January/Day2DetectCapital.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day2DetectCapital.cpp 3 | * @author Ginny Dang 4 | * @brief 520. Detect Capital (https://leetcode.com/problems/detect-capital/description/) 5 | * @version 0.1 6 | * @date 2023-01-02 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | bool detectCapitalUse(string word) 16 | { 17 | auto allUpper = [](int start, int end, string word) -> bool 18 | { 19 | for (int i = start; i <= end; i++) 20 | if (islower(word[i])) 21 | return false; 22 | return true; 23 | }; 24 | 25 | auto allLower = [](int start, int end, string word) -> bool 26 | { 27 | for (int i = start; i <= end; i++) 28 | if (isupper(word[i])) 29 | return false; 30 | return true; 31 | }; 32 | 33 | bool capFirst = isupper(word[0]); 34 | if (capFirst) 35 | return (allUpper(0, word.length() - 1, word) || allLower(1, word.length() - 1, word)); 36 | else 37 | return allLower(1, word.length() - 1, word); 38 | } 39 | }; 40 | 41 | // Time Complexity: O(N) 42 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /1. January/Day30NthTribonacciNumber.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day30NthTribonacciNumber.cpp 3 | * @author Ginny Dang 4 | * @brief 1137. N-th Tribonacci Number (https://leetcode.com/problems/n-th-tribonacci-number/description/) 5 | * @version 0.1 6 | * @date 2023-01-29 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int tribonacci(int n) 16 | { 17 | // Edge case handling 18 | if (n == 0) 19 | return 0; 20 | else if (n == 1 || n == 2) 21 | return 1; 22 | 23 | // Normal case 24 | int prev3 = 0; // n-3 25 | int prev2 = 1; // n-2 26 | int prev1 = 1; // n-1 27 | int tribonacciSum = 0; 28 | 29 | for (int i = 3; i <= n; i++) 30 | { 31 | tribonacciSum = prev1 + prev2 + prev3; 32 | prev3 = prev2; 33 | prev2 = prev1; 34 | prev1 = tribonacciSum; 35 | } 36 | 37 | return tribonacciSum; 38 | } 39 | }; 40 | 41 | // Time Complexity: O(1) or O(35) to be exact 42 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /1. January/Day31BestTeamWithNoConflicts.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day31BestTeamWithNoConflicts.cpp 3 | * @author Ginny Dang 4 | * @brief 1626. Best Team With No Conflicts (https://leetcode.com/problems/best-team-with-no-conflicts/description/) 5 | * @version 0.1 6 | * @date 2023-01-31 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * @brief High level idea: Dynamic Programming "Longest increasing subsequence" 14 | */ 15 | 16 | class Solution 17 | { 18 | public: 19 | int bestTeamScore(vector &scores, vector &ages) 20 | { 21 | int n = scores.size(); 22 | // Gather all {age : score} pairs 23 | vector> ageToScore; 24 | for (int i = 0; i < n; i++) 25 | ageToScore.push_back({ages[i], scores[i]}); 26 | 27 | // Sort by ages 28 | sort(ageToScore.begin(), ageToScore.end()); 29 | 30 | vector lnds(n, 0); // lnds[i] is the max total score ending at i 31 | for (int i = 0; i < n; i++) 32 | { 33 | lnds[i] = ageToScore[i].second; 34 | for (int j = 0; j < i; j++) 35 | if (ageToScore[j].second <= ageToScore[i].second) 36 | lnds[i] = max(lnds[i], lnds[j] + ageToScore[i].second); 37 | } 38 | 39 | return *max_element(lnds.begin(), lnds.end()); 40 | } 41 | }; 42 | 43 | // Time Complexity: O(N^2) 44 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /1. January/Day3DeleteColumnsToMakeSorted.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day3DeleteColumnsToMakeSorted.cpp 3 | * @author Ginny Dang 4 | * @brief 944. Delete Columns to Make Sorted (https://leetcode.com/problems/delete-columns-to-make-sorted/description/) 5 | * @version 0.1 6 | * @date 2023-01-02 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int minDeletionSize(vector &strs) 16 | { 17 | int result = 0; 18 | int n = strs.size(); // rows 19 | int m = strs[0].length(); // columns 20 | 21 | for (int i = 0; i < m; i++) 22 | { 23 | bool deleted = false; // each column can only be deleted once 24 | for (int j = 1; j < n; j++) 25 | { 26 | if (strs[j][i] < strs[j - 1][i] && !deleted) 27 | { 28 | result++; 29 | deleted = true; 30 | } 31 | } 32 | } 33 | 34 | return result; 35 | } 36 | }; 37 | 38 | // Time Complexity: O(m * n) 39 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /1. January/Day4MinimumRoundsToCompleteAllTasks.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day4MinimumRoundsToCompleteAllTasks.cpp 3 | * @author Ginny Dang 4 | * @brief 2244. Minimum Rounds to Complete All Tasks (https://leetcode.com/problems/minimum-rounds-to-complete-all-tasks/description/) 5 | * @version 0.1 6 | * @date 2023-01-03 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int minimumRounds(vector &tasks) 16 | { 17 | int rounds = 0; 18 | unordered_map difficulties; 19 | 20 | for (int task : tasks) 21 | difficulties[task]++; 22 | 23 | for (auto pair : difficulties) 24 | { 25 | if (pair.second == 1) 26 | return -1; 27 | else if (pair.second % 3 == 0) 28 | rounds += (pair.second / 3); 29 | else 30 | rounds += (pair.second / 3) + 1; 31 | } 32 | return rounds; 33 | } 34 | }; 35 | 36 | // Time Complexity: O(n) 37 | // Space Complexity: O(n) -------------------------------------------------------------------------------- /1. January/Day5MinimumNumberOfArrowsToBurstBalloons.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day5MinimumNumberOfArrowsToBurstBalloons.cpp 3 | * @author Ginny Dang 4 | * @brief 452. Minimum Number of Arrows to Burst Balloons (https://leetcode.com/problems/minimum-number-of-arrows-to-burst-balloons/description/) 5 | * @version 0.1 6 | * @date 2023-01-04 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | static bool sortcol(const vector &v1, const vector &v2) 16 | { 17 | if (v1[0] == v2[0]) 18 | return v1[1] < v2[1]; 19 | return v1[0] < v2[0]; 20 | } 21 | 22 | int findMinArrowShots(vector> &points) 23 | { 24 | // Corner case handling 25 | if (points.size() == 1) 26 | return 1; 27 | 28 | // Sort by 1st column 29 | sort(points.begin(), points.end(), sortcol); 30 | 31 | // Count number of arrows 32 | int curr_start = points[0][0]; 33 | int curr_end = points[0][1]; 34 | int arrows = 1; 35 | for (int i = 1; i < points.size(); i++) 36 | { 37 | curr_start = max(curr_start, points[i][0]); 38 | curr_end = min(curr_end, points[i][1]); 39 | if (curr_start > curr_end) 40 | { 41 | arrows++; 42 | curr_start = points[i][0]; 43 | curr_end = points[i][1]; 44 | } 45 | } 46 | return arrows; 47 | } 48 | }; 49 | 50 | // Time Complexity: O(NlogN) 51 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /1. January/Day6MaximumIceCreamBars.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day6MaximumIceCreamBars.cpp 3 | * @author Ginny Dang 4 | * @brief 1833. Maximum Ice Cream Bars (https://leetcode.com/problems/maximum-ice-cream-bars/description/) 5 | * @version 0.1 6 | * @date 2023-01-05 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | // As the input array's element's range is not very large, we can use counting sort. 13 | 14 | class Solution 15 | { 16 | public: 17 | int maxIceCream(vector &costs, int coins) 18 | { 19 | int maxCost = *max_element(costs.begin(), costs.end()); 20 | vector counts(maxCost + 1, 0); 21 | for (int cost : costs) 22 | counts[cost]++; 23 | 24 | int bars = 0; 25 | int total = 0; 26 | int count = 0; // keep track of the number of bars we can buy for each cost with our remaining money 27 | for (int cost = 1; cost < counts.size(); cost++) 28 | { 29 | if (counts[cost] == 0) 30 | continue; 31 | if (cost > coins) 32 | break; 33 | // Either we can pick all ice creams of 'cost' or we will be limited by remaining 'coins'. 34 | count = min(counts[cost], coins / cost); 35 | coins -= count * cost; 36 | bars += count; 37 | } 38 | return bars; 39 | } 40 | }; 41 | 42 | // Time complexity: O(N + M) where N is the length of the input array, and M is the maximum element in it. 43 | // Space complexity: O(M) -------------------------------------------------------------------------------- /1. January/Day7GasStation.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day7GasStation.cpp 3 | * @author Ginny Dang 4 | * @brief 134. Gas Station (https://leetcode.com/problems/gas-station/description/) 5 | * @version 0.1 6 | * @date 2023-01-07 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int canCompleteCircuit(vector &gas, vector &cost) 16 | { 17 | int n = gas.size(); 18 | int start = 0; 19 | int end = 0; 20 | 21 | while (start < n) 22 | { 23 | end = start; 24 | bool updatedEnd = false; 25 | int remainingGas = gas[start]; 26 | while (remainingGas - cost[end % n] >= 0) 27 | { 28 | updatedEnd = true; 29 | remainingGas -= cost[end % n]; 30 | remainingGas += gas[++end % n]; 31 | if (end == start + n) 32 | break; 33 | } 34 | if (updatedEnd && end == start + n) 35 | { 36 | cout << "Done line 8" 37 | << "\n"; 38 | return start; 39 | } 40 | start = ++end; 41 | } 42 | 43 | return -1; 44 | } 45 | }; 46 | 47 | // Time Complexity: O(N) 48 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /1. January/Day8MaxPointsOnALine.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day8MaxPointsOnALine.cpp 3 | * @author Ginny Dang 4 | * @brief 149. Max Points on a Line (https://leetcode.com/problems/max-points-on-a-line/description/) 5 | * @version 0.1 6 | * @date 2023-01-08 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * @brief Idea learned from the official solution 14 | * For a fixed point points[i], consider all other points points[j] and calculate the atan2 for each vector points[j] - points[i] (the vector with the magnitudes (points[j].x - points[i].x, points[j].y - points[i].y)). 15 | * Then find the maximum number of times some angle value occurs among the calculated values. One can use a hash map for this. 16 | */ 17 | 18 | /** 19 | * @brief Algorithm learned from the official solution 20 | * For each points[i], maintain a hash map cnt to count the angles. 21 | * - For each j ≠ i, calculate the atan2 of the vector points[j] - points[i] and add this value to the current hash map. 22 | * - Let k be the maximum number of occurrences of some angle value in the hash map. 23 | * - Update the answer with k+1. (+1 because the point points[i] also lies on the line, and we must include it in the answer.) 24 | */ 25 | 26 | /** 27 | * @brief New thing I've learned from this challenge 28 | * The atan2 built-in function in C++ (https://cplusplus.com/reference/cmath/atan2/) 29 | * - double atan2(double y, double x); 30 | * - Compute arc tangent with two parameters 31 | * - Returns the principal value of the arc tangent of y/x, expressed in radians. 32 | */ 33 | 34 | class Solution 35 | { 36 | public: 37 | int maxPoints(vector> &points) 38 | { 39 | if (points.size() == 1) 40 | return 1; 41 | 42 | int result = 2; 43 | 44 | for (int i = 0; i < points.size(); i++) 45 | { 46 | unordered_map cnt; // keep track of the frequencies of different arc tangent values 47 | 48 | for (int j = 0; j < points.size(); j++) 49 | if (j != i) 50 | cnt[atan2(points[j][1] - points[i][1], points[j][0] - points[i][0])]++; 51 | 52 | for (auto pair : cnt) 53 | result = max(result, pair.second + 1); 54 | } 55 | 56 | return result; 57 | } 58 | }; 59 | 60 | // Time Complexity: O(N^2) 61 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /1. January/Day9BinaryTreePreorderTraversal.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day9BinaryTreePreorderTraversal.cpp 3 | * @author Ginny Dang 4 | * @brief 144. Binary Tree Preorder Traversal (https://leetcode.com/problems/binary-tree-preorder-traversal/description/) 5 | * @version 0.1 6 | * @date 2023-01-09 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * Definition for a binary tree node. 14 | * struct TreeNode { 15 | * int val; 16 | * TreeNode *left; 17 | * TreeNode *right; 18 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 19 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 20 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 21 | * }; 22 | */ 23 | class Solution 24 | { 25 | public: 26 | vector preorderTraversal(TreeNode *root) 27 | { 28 | if (!root) 29 | return vector(); 30 | else 31 | { 32 | vector node_values; 33 | node_values.push_back(root->val); 34 | vector left_children = preorderTraversal(root->left); 35 | node_values.insert(node_values.end(), left_children.begin(), left_children.end()); 36 | vector right_children = preorderTraversal(root->right); 37 | node_values.insert(node_values.end(), right_children.begin(), right_children.end()); 38 | return node_values; 39 | } 40 | } 41 | }; 42 | 43 | // Time Complexity: O(n) 44 | // Space Complexity: O(n) -------------------------------------------------------------------------------- /2. February/Day10AsFarFromLandAsPossible.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day10AsFarFromLandAsPossible.cpp 3 | * @author Ginny Dang 4 | * @brief 1162. As Far from Land as Possible (https://leetcode.com/problems/as-far-from-land-as-possible/description/) 5 | * @version 0.1 6 | * @date 2023-02-09 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | const int dr[] = {-1, 1, 0, 0}; 13 | const int dc[] = {0, 0, -1, 1}; 14 | 15 | class Solution 16 | { 17 | public: 18 | int calcDist(int x0, int y0, int x1, int y1) 19 | { 20 | return abs(x0 - x1) + abs(y0 - y1); 21 | } 22 | 23 | int bfs(int n, vector> &grid) 24 | { 25 | // Init 26 | int maxDist = INT_MIN; 27 | vector> dist(n, vector(n, INT_MAX)); 28 | queue> q; 29 | 30 | // Add all sources to the queue 31 | for (int i = 0; i < n; i++) 32 | { 33 | for (int j = 0; j < n; j++) 34 | { 35 | if (grid[i][j] == 1) 36 | { 37 | dist[i][j] = 0; 38 | q.push({i, j}); 39 | } 40 | } 41 | } 42 | 43 | // Calculate the distances 44 | while (q.size()) 45 | { 46 | int curRow = q.front().first; 47 | int curCol = q.front().second; 48 | q.pop(); 49 | for (int i = 0; i < 4; i++) 50 | { 51 | int nextRow = curRow + dr[i]; 52 | int nextCol = curCol + dc[i]; 53 | if ((nextRow >= 0 && nextRow < n) && (nextCol >= 0 && nextCol < n) && (dist[nextRow][nextCol] == INT_MAX)) 54 | { 55 | dist[nextRow][nextCol] = dist[curRow][curCol] + calcDist(curRow, curCol, nextRow, nextCol); 56 | grid[nextRow][nextCol] = 1; 57 | q.push({nextRow, nextCol}); 58 | } 59 | } 60 | } 61 | 62 | // Make sure that there's no unvisited cell 63 | for (int i = 0; i < n; i++) 64 | for (int j = 0; j < n; j++) 65 | if (grid[i][j] == 0) 66 | return -1; 67 | 68 | // Find the maximum distance 69 | for (int i = 0; i < n; i++) 70 | for (int j = 0; j < n; j++) 71 | maxDist = max(maxDist, dist[i][j]); 72 | 73 | return maxDist; 74 | } 75 | 76 | int maxDistance(vector> &grid) 77 | { 78 | int n = grid.size(); 79 | int maxDist = bfs(n, grid); 80 | return maxDist == 0 ? -1 : maxDist; 81 | } 82 | }; 83 | 84 | // Time Complexity: O(N^2) 85 | // Space Complexity: O(N^2) -------------------------------------------------------------------------------- /2. February/Day11ShortestPathWithAlternatingColors.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day11ShortestPathWithAlternatingColors.cpp 3 | * @author Ginny Dang 4 | * @brief 1129. Shortest Path with Alternating Colors (https://leetcode.com/problems/shortest-path-with-alternating-colors/description/) 5 | * @version 0.1 6 | * @date 2023-02-11 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * @brief New thing I've learned from this challenge 14 | * How to create an unordered_map of pairs in C++? (https://www.geeksforgeeks.org/how-to-create-an-unordered_map-of-pairs-in-c/) 15 | */ 16 | 17 | class Solution 18 | { 19 | public: 20 | // A hash function used to hash a pair of any kind 21 | struct hash_pair 22 | { 23 | template 24 | size_t operator()(const pair &p) const 25 | { 26 | auto hash1 = hash{}(p.first); 27 | auto hash2 = hash{}(p.second); 28 | 29 | if (hash1 != hash2) 30 | return hash1 ^ hash2; 31 | 32 | // If hash1 == hash2, their XOR is zero. 33 | return hash1; 34 | } 35 | }; 36 | 37 | void bfs(vector>> &graph, int start, vector &weights) 38 | { 39 | queue> q; // Each element looks like {point, level, color} 40 | q.push({start, 0, -1}); 41 | unordered_map, bool, hash_pair> visited; 42 | 43 | visited[{start, 0}] = true; // 0 indicates a red edge 44 | visited[{start, 1}] = true; // 1 indicates a blue edge 45 | 46 | while (!q.empty()) 47 | { 48 | int point = q.front()[0]; 49 | int level = q.front()[1]; 50 | int color = q.front()[2]; 51 | q.pop(); 52 | 53 | for (auto &neighbor : graph[point]) 54 | { 55 | if (color == -1 || color != neighbor.second) 56 | { 57 | if (!visited.count(neighbor)) 58 | { 59 | visited[neighbor] = true; 60 | weights[neighbor.first] = min(weights[neighbor.first], level + 1); 61 | q.push({neighbor.first, level + 1, neighbor.second}); 62 | } 63 | } 64 | } 65 | } 66 | } 67 | 68 | vector shortestAlternatingPaths(int n, vector> &redEdges, vector> &blueEdges) 69 | { 70 | // Build a special graph 71 | vector>> graph(n, vector>()); 72 | //// Add all red edges. Each red edge is denoted as 0 73 | for (auto &redEdge : redEdges) 74 | graph[redEdge[0]].push_back({redEdge[1], 0}); 75 | //// Add all blue edges. Each blue edge is denoted as 1 76 | for (auto &blueEdge : blueEdges) 77 | graph[blueEdge[0]].push_back({blueEdge[1], 1}); 78 | 79 | // Initialize all weights as infinities except for the 1st one 80 | vector weights(n, INT_MAX); 81 | weights[0] = 0; 82 | 83 | // Apply BFS 84 | //// BFS 85 | bfs(graph, 0, weights); 86 | //// Reassign those weights that are uncalculable 87 | for (int i = 0; i < weights.size(); i++) 88 | if (weights[i] == INT_MAX) 89 | weights[i] = -1; 90 | //// Result 91 | return weights; 92 | } 93 | }; 94 | 95 | // Time Complexity: O(N + E) where N is the number of nodes and E is the total number of blue and red edges 96 | // Space Complexity: O(N + E) where N is the number of nodes and E is the total number of blue and red edges -------------------------------------------------------------------------------- /2. February/Day12MinimumFuelCostToReportToTheCapital.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day12MinimumFuelCostToReportToTheCapital.cpp 3 | * @author Ginny Dang 4 | * @brief 2477. Minimum Fuel Cost to Report to the Capital (https://leetcode.com/problems/minimum-fuel-cost-to-report-to-the-capital/description/) 5 | * @version 0.1 6 | * @date 2023-02-12 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | long long dfs(int start, int seats, vector> &graph, vector &numNodes, int parent = -1) 16 | { 17 | long long cost = 0; 18 | 19 | for (int neighbor : graph[start]) 20 | { 21 | if (neighbor == parent) 22 | continue; 23 | cost += dfs(neighbor, seats, graph, numNodes, start); 24 | cost += numNodes[neighbor] / seats; 25 | if (numNodes[neighbor] % seats != 0) 26 | cost++; 27 | numNodes[start] += numNodes[neighbor]; 28 | } 29 | 30 | return cost; 31 | } 32 | 33 | long long minimumFuelCost(vector> &roads, int seats) 34 | { 35 | // Init 36 | long long fuelCost = 0; 37 | int n = roads.size() + 1; 38 | vector numNodes(n, 1); // Number of nodes in each subtree 39 | 40 | // Build graph 41 | vector> graph(n, vector()); 42 | for (auto &road : roads) 43 | { 44 | graph[road[0]].push_back(road[1]); 45 | graph[road[1]].push_back(road[0]); 46 | } 47 | 48 | // Calculate costs to travel from 0 to any other nodes 49 | fuelCost += dfs(0, seats, graph, numNodes); 50 | return fuelCost; 51 | } 52 | }; 53 | 54 | // Time Complexity: O(N + E) 55 | // Space Complexity: O(N + E) -------------------------------------------------------------------------------- /2. February/Day13CountOddNumbersInAnIntervalRange.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day13CountOddNumbersInAnIntervalRange.cpp 3 | * @author Ginny Dang 4 | * @brief 1523. Count Odd Numbers in an Interval Range (https://leetcode.com/problems/count-odd-numbers-in-an-interval-range/description/) 5 | * @version 0.1 6 | * @date 2023-02-12 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * @brief Idea 14 | * - For each inclusive range containing more than 1 number, say n numbers, we always have n/2 pairs of 1 odd and 1 even. 15 | * - If n is odd, there's 1 standalone number not in a pair 16 | * -- If low is odd, then n is odd if and only if high is odd as well. Therefore, the number of odds in the range [low, high] is n/2 + 1, i.e., the standalone number is odd and is counted. 17 | * -- If low is even, then n is odd if and only if high is even as well. Therefore, the number of odds in the range [low, high] is n/2, i.e., the standalone number is even and is not counted. 18 | * - If n is even, the number of odds in the range [low, high] is equal to the number of pairs, i.e., n/2. 19 | */ 20 | 21 | class Solution 22 | { 23 | public: 24 | int countOdds(int low, int high) 25 | { 26 | int n = high - low + 1; // number of numbers in range [low, high] inclusive 27 | int pairs = n / 2; // number of pairs of 1 even number and 1 one odd number 28 | if (low % 2 == 1 && high % 2 == 1) 29 | return pairs + 1; 30 | return pairs; 31 | } 32 | }; 33 | 34 | // Time Complexity: O(1) 35 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /2. February/Day14AddBinary.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day14AddBinary.cpp 3 | * @author Ginny Dang 4 | * @brief 67. Add Binary (https://leetcode.com/problems/add-binary/description/) 5 | * @version 0.1 6 | * @date 2023-02-13 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | string addBinary(string a, string b) 16 | { 17 | int maxLength = max(a.length(), b.length()); 18 | while (a.length() != maxLength) 19 | a = '0' + a; 20 | while (b.length() != maxLength) 21 | b = '0' + b; 22 | 23 | int carry = 0; 24 | string answer = ""; 25 | for (int i = maxLength - 1; i > -1; i--) 26 | { 27 | int currSumDigit = int(a[i] - '0') + int(b[i] - '0') + carry; 28 | answer = to_string(currSumDigit % 2) + answer; 29 | carry = currSumDigit / 2; 30 | cout << currSumDigit << " " << carry << "\n"; 31 | } 32 | 33 | if (carry == 1) 34 | answer = '1' + answer; 35 | 36 | return answer; 37 | } 38 | }; 39 | 40 | // Time Complexity: O(max(M, N)) 41 | // Space Complexity: O(max(M, N)) -------------------------------------------------------------------------------- /2. February/Day15AddToArrayFormOfInteger.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day15AddToArrayFormOfInteger.cpp 3 | * @author Ginny Dang 4 | * @brief 989. Add to Array-Form of Integer (https://leetcode.com/problems/add-to-array-form-of-integer/description/) 5 | * @version 0.1 6 | * @date 2023-02-14 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | vector addToArrayForm(vector &num, int k) 16 | { 17 | int cur = k; 18 | int carry = 0; 19 | vector newNum; 20 | 21 | for (int i = num.size() - 1; i > -1; i--) 22 | { 23 | // cout << cur << "\n"; 24 | // cout << num[i] << " " << cur % 10 << " " << carry << "\n"; 25 | int currDigit = num[i] + (cur % 10) + carry; 26 | 27 | if (currDigit > 9 || i == 0) 28 | carry = currDigit / 10; 29 | else 30 | carry = 0; 31 | 32 | newNum.push_back(currDigit % 10); 33 | cur /= 10; 34 | // cout << cur << "\n" << "\n"; 35 | } 36 | 37 | cur += carry; 38 | while (cur / 10 != 0) 39 | { 40 | newNum.push_back(cur % 10); 41 | cur /= 10; 42 | } 43 | if (cur != 0) 44 | newNum.push_back(cur); 45 | 46 | reverse(newNum.begin(), newNum.end()); 47 | 48 | return newNum; 49 | } 50 | }; 51 | 52 | // Time Complexity: O(max(N,logK)) 53 | // Space Complexity: O(max(N,logK)) -------------------------------------------------------------------------------- /2. February/Day16MaximumDepthOfBinaryTree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day16MaximumDepthOfBinaryTree.cpp 3 | * @author Ginny Dang 4 | * @brief 104. Maximum Depth of Binary Tree (https://leetcode.com/problems/maximum-depth-of-binary-tree/description/) 5 | * @version 0.1 6 | * @date 2023-02-15 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * Definition for a binary tree node. 14 | * struct TreeNode { 15 | * int val; 16 | * TreeNode *left; 17 | * TreeNode *right; 18 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 19 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 20 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 21 | * }; 22 | */ 23 | class Solution 24 | { 25 | public: 26 | int findDepth(TreeNode *node, int depth, int maxDepth) 27 | { 28 | if (!node) 29 | return 0; 30 | else if (!node->left && !node->right) 31 | { 32 | maxDepth = max(maxDepth, depth); 33 | } 34 | else 35 | { 36 | int maxLeftDepth = findDepth(node->left, depth + 1, maxDepth); 37 | int maxRightDepth = findDepth(node->right, depth + 1, maxDepth); 38 | maxDepth = max(maxLeftDepth, maxRightDepth); 39 | } 40 | return maxDepth; 41 | } 42 | 43 | int maxDepth(TreeNode *root) 44 | { 45 | return findDepth(root, 1, 0); 46 | } 47 | }; 48 | 49 | // Time Complexity: O(N) 50 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /2. February/Day17MinimumDistanceBetweenBSTNodes.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day17MinimumDistanceBetweenBSTNodes.cpp 3 | * @author Ginny Dang 4 | * @brief 783. Minimum Distance Between BST Nodes (https://leetcode.com/problems/minimum-distance-between-bst-nodes/description/) 5 | * @version 0.1 6 | * @date 2023-02-17 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * Definition for a binary tree node. 14 | * struct TreeNode { 15 | * int val; 16 | * TreeNode *left; 17 | * TreeNode *right; 18 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 19 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 20 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 21 | * }; 22 | */ 23 | class Solution 24 | { 25 | public: 26 | pair findMostNodes(TreeNode *root, int &result) 27 | { 28 | if (!root) 29 | return {}; 30 | 31 | int minLeft = INT_MAX, maxLeft = INT_MIN; 32 | int minRight = INT_MAX, maxRight = INT_MIN; 33 | 34 | if (root->left) 35 | { 36 | pair leftPair = findMostNodes(root->left, result); 37 | minLeft = leftPair.first; 38 | maxLeft = leftPair.second; 39 | result = min(result, abs(root->val - maxLeft)); 40 | } 41 | else 42 | minLeft = root->val; 43 | 44 | if (root->right) 45 | { 46 | pair rightPair = findMostNodes(root->right, result); 47 | minRight = rightPair.first; 48 | maxRight = rightPair.second; 49 | result = min(result, abs(root->val - minRight)); 50 | } 51 | else 52 | maxRight = root->val; 53 | 54 | return {minLeft, maxRight}; 55 | } 56 | 57 | int minDiffInBST(TreeNode *root) 58 | { 59 | int result = INT_MAX; 60 | findMostNodes(root, result); 61 | return result; 62 | } 63 | }; 64 | 65 | // Time Complexity: O(N) 66 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /2. February/Day18InvertBinaryTree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day18InvertBinaryTree.cpp 3 | * @author Ginny Dang 4 | * @brief 226. Invert Binary Tree (https://leetcode.com/problems/invert-binary-tree/description/) 5 | * @version 0.1 6 | * @date 2023-02-17 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * Definition for a binary tree node. 14 | * struct TreeNode { 15 | * int val; 16 | * TreeNode *left; 17 | * TreeNode *right; 18 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 19 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 20 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 21 | * }; 22 | */ 23 | class Solution 24 | { 25 | public: 26 | TreeNode *invertTree(TreeNode *root) 27 | { 28 | if (!root || (!root->left && !root->right)) 29 | return root; 30 | if (root->left) 31 | invertTree(root->left); 32 | if (root->right) 33 | invertTree(root->right); 34 | TreeNode *temp = root->left; 35 | root->left = root->right; 36 | root->right = temp; 37 | return root; 38 | } 39 | }; 40 | 41 | // Time Complexity: O(N) 42 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /2. February/Day19BinaryTreeZigzagLevelOrderTraversal.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day19BinaryTreeZigzagLevelOrderTraversal.cpp 3 | * @author Ginny Dang 4 | * @brief 103. Binary Tree Zigzag Level Order Traversal (https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/description/) 5 | * @version 0.1 6 | * @date 2023-02-18 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * Definition for a binary tree node. 14 | * struct TreeNode { 15 | * int val; 16 | * TreeNode *left; 17 | * TreeNode *right; 18 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 19 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 20 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 21 | * }; 22 | */ 23 | class Solution 24 | { 25 | public: 26 | vector> zigzagLevelOrder(TreeNode *root) 27 | { 28 | if (!root) 29 | return vector>(); 30 | 31 | vector curLevel; 32 | curLevel.push_back(root); 33 | 34 | vector> zigzag; 35 | zigzag.push_back({root->val}); 36 | 37 | int direction = -1; 38 | 39 | while (curLevel.size()) 40 | { 41 | // Find all nodes of the next level 42 | vector temp(curLevel.size()); 43 | copy(curLevel.begin(), curLevel.end(), temp.begin()); 44 | curLevel.clear(); 45 | direction *= -1; 46 | for (auto &node : temp) 47 | { 48 | if (node->left) 49 | curLevel.push_back(node->left); 50 | if (node->right) 51 | curLevel.push_back(node->right); 52 | } 53 | // Append all node vals of the current level to zigzag based on direction 54 | vector tempVals; 55 | if (direction == 1) 56 | for (int i = curLevel.size() - 1; i > -1; i--) 57 | tempVals.push_back(curLevel[i]->val); 58 | else 59 | for (int i = 0; i < curLevel.size(); i++) 60 | tempVals.push_back(curLevel[i]->val); 61 | // Append the current level to the zigzag traversal 62 | if (tempVals.size()) 63 | zigzag.push_back(tempVals); 64 | } 65 | 66 | return zigzag; 67 | } 68 | }; 69 | 70 | // Time Complexity: O(N) 71 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /2. February/Day1GreatestCommonDivisorOfStrings.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day1GreatestCommonDivisorOfStrings.cpp 3 | * @author Ginny Dang 4 | * @brief 1071. Greatest Common Divisor of Strings (https://leetcode.com/problems/greatest-common-divisor-of-strings/description/) 5 | * @version 0.1 6 | * @date 2023-01-31 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | bool isDivisor(string t, string s) 16 | { 17 | if (s.length() % t.length() != 0) 18 | return false; 19 | 20 | for (int i = 0; i < s.length(); i += t.size()) 21 | { // O(N) 22 | string u = s.substr(i, t.length()); 23 | if (t.compare(u) != 0) 24 | return false; 25 | } 26 | 27 | return true; 28 | } 29 | 30 | string gcdOfStrings(string str1, string str2) 31 | { 32 | if (str1.length() < str2.length()) 33 | swap(str1, str2); 34 | 35 | for (int i = str2.length(); i >= 0; i--) 36 | { // O(N) 37 | if (str1.length() % (i + 1) == 0 && str2.length() % (i + 1) == 0) 38 | { 39 | string str3 = str2.substr(0, i + 1); 40 | if (isDivisor(str3, str2) && isDivisor(str3, str1)) 41 | return str3; 42 | /* str3 is the longest possible candidate and 43 | lengths of those strings which are shorter than it are divisors of str3.length 44 | If str3 is not the gcd of str1 and str2, 45 | those strings described above can't be either 46 | -> we can stop the check here */ 47 | break; 48 | } 49 | } 50 | 51 | return ""; 52 | } 53 | }; 54 | 55 | // Time Complexity: O(m+n) 56 | // Space Complexity: O(max(m,n)) -------------------------------------------------------------------------------- /2. February/Day20SearchInsertPosition.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day20SearchInsertPosition.cpp 3 | * @author Ginny Dang 4 | * @brief 35. Search Insert Position (https://leetcode.com/problems/search-insert-position/description/) 5 | * @version 0.1 6 | * @date 2023-02-19 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int searchInsert(vector &nums, int target) 16 | { 17 | if (target > nums[nums.size() - 1]) 18 | return nums.size(); 19 | else if (target < nums[0]) 20 | return 0; 21 | 22 | int left = 0, right = nums.size() - 1; 23 | while (left <= right) 24 | { 25 | int mid = left + (right - left) / 2; 26 | if (nums[mid] == target) 27 | return mid; 28 | else if (nums[mid] < target) 29 | { 30 | if (nums[mid + 1] > target) 31 | return mid + 1; 32 | left = mid + 1; 33 | } 34 | else 35 | { 36 | if (nums[mid - 1] < target) 37 | return mid; 38 | right = mid - 1; 39 | } 40 | } 41 | 42 | return -1; 43 | } 44 | }; 45 | 46 | // Time Complexity: O(logN) 47 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /2. February/Day21SingleElementInASortedArray.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day21SingleElementInASortedArray.cpp 3 | * @author Ginny Dang 4 | * @brief 540. Single Element in a Sorted Array (https://leetcode.com/problems/single-element-in-a-sorted-array/description/) 5 | * @version 0.1 6 | * @date 2023-02-20 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int singleNonDuplicate(vector &nums) 16 | { 17 | // Edge case 18 | /* Given the constraints, arrays with only 2 elements are considered invalid input */ 19 | if (nums.size() == 1) 20 | return nums[0]; 21 | 22 | // Normal cases 23 | int left = 0; 24 | int right = nums.size() - 1; 25 | 26 | while (left < right) 27 | { 28 | int mid = left + (right - left) / 2; 29 | bool halvesAreEven = (right - mid) % 2 == 0; 30 | // If mid’s partner is to the right 31 | if (nums[mid] == nums[mid + 1]) 32 | { 33 | // The halves were originally even 34 | if (halvesAreEven) 35 | left = mid + 2; 36 | // The halves were originally odd 37 | else 38 | right = mid - 1; 39 | } 40 | // If mid’s partner is to the left 41 | else if (nums[mid] == nums[mid - 1]) 42 | { 43 | // The halves were originally even 44 | if (halvesAreEven) 45 | right = mid - 2; 46 | // The halves were originally odd 47 | else 48 | left = mid + 1; 49 | } 50 | // If mid does not have a partner 51 | else 52 | return nums[mid]; 53 | } 54 | 55 | return nums[left]; 56 | } 57 | }; 58 | 59 | // Time Complexity: O(logN) 60 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /2. February/Day22CapacityToShipPackagesWithinDDays.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day22CapacityToShipPackagesWithinDDays.cpp 3 | * @author Ginny Dang 4 | * @brief 1011. Capacity To Ship Packages Within D Days (https://leetcode.com/problems/capacity-to-ship-packages-within-d-days/description/) 5 | * @version 0.1 6 | * @date 2023-02-21 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int countDays(int capacity, vector &weights) 16 | { 17 | int total = 0, count = 1; 18 | 19 | for (int weight : weights) 20 | { 21 | if (total + weight <= capacity) 22 | total += weight; 23 | else 24 | { 25 | total = weight; 26 | count++; 27 | } 28 | } 29 | 30 | return count; 31 | } 32 | 33 | int shipWithinDays(vector &weights, int days) 34 | { 35 | int left = *max_element(weights.begin(), weights.end()); 36 | int right = accumulate(weights.begin(), weights.end(), 0); 37 | 38 | while (left <= right) 39 | { 40 | int mid = left + (right - left) / 2; 41 | int possibleDaysNeeded = countDays(mid, weights); // O(N) 42 | if (possibleDaysNeeded <= days) 43 | right = mid - 1; 44 | else 45 | left = mid + 1; 46 | } 47 | 48 | return left; 49 | } 50 | }; 51 | 52 | // Time Complexity: O(N*log(M*N/D-M)) where N is the length of weights, M is the maximum element in weights, D is the number of days 53 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /2. February/Day23IPO.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day23IPO.cpp 3 | * @author Ginny Dang 4 | * @brief 502. IPO (https://leetcode.com/problems/ipo/description/) 5 | * @version 0.1 6 | * @date 2023-02-23 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int findMaximizedCapital(int k, int w, vector &profits, vector &capital) 16 | { 17 | int n = profits.size(); 18 | vector> projects; 19 | for (int i = 0; i < n; i++) 20 | projects.emplace_back(capital[i], profits[i]); 21 | sort(projects.begin(), projects.end()); 22 | 23 | priority_queue> pq; // {profits, capital} 24 | int lastPos = -1; 25 | for (int i = 0; i < n; i++) 26 | { 27 | if (projects[i].first <= w) 28 | { 29 | pq.push({projects[i].second, projects[i].first}); // when pushing into the max heap, it should be {profits[i], capital[i]} because we want to compare by profit and take the maximum one 30 | lastPos = i; 31 | } 32 | else 33 | break; 34 | } 35 | if (pq.empty()) 36 | return w; 37 | 38 | for (int i = 0; i < min(k, n); i++) 39 | { 40 | w += pq.top().first; 41 | pq.pop(); 42 | 43 | for (int j = lastPos + 1; j < n; j++) 44 | { 45 | if (projects[j].first <= w) 46 | { 47 | pq.push({projects[j].second, projects[j].first}); 48 | lastPos = j; 49 | } 50 | else 51 | break; 52 | } 53 | 54 | if (pq.empty()) 55 | break; 56 | } 57 | return w; 58 | } 59 | }; 60 | 61 | // Time Complexity: O(NlogN) 62 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /2. February/Day24MinimizeDeviationInArray.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day24MinimizeDeviationInArray.cpp 3 | * @author Ginny Dang 4 | * @brief 1675. Minimize Deviation in Array (https://leetcode.com/problems/minimize-deviation-in-array/description/?orderBy=most_votes) 5 | * @version 0.1 6 | * @date 2023-02-24 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int minimumDeviation(vector &nums) 16 | { 17 | priority_queue evens; // a max heap 18 | int minimum = INT_MAX; // keeps track of the smallest element in evens 19 | for (int num : nums) 20 | { 21 | if (num % 2 != 0) 22 | num *= 2; 23 | evens.push(num); 24 | minimum = min(minimum, num); 25 | } 26 | 27 | int minDeviat = INT_MAX; 28 | while (!evens.empty()) 29 | { 30 | int maximum = evens.top(); 31 | evens.pop(); 32 | minDeviat = min(minDeviat, maximum - minimum); 33 | if (maximum % 2 == 0) 34 | { 35 | evens.push(maximum / 2); 36 | minimum = min(minimum, maximum / 2); 37 | } 38 | else 39 | break; 40 | } 41 | return minDeviat; 42 | } 43 | }; 44 | 45 | // Time Complexity: O(Klog⁡(N)) = O(Nlog⁡(M)log⁡(N)) 46 | // Space Complexity: O(N) 47 | -------------------------------------------------------------------------------- /2. February/Day25BestTimeToBuyAndSellStock.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day25BestTimeToBuyAndSellStock.cpp 3 | * @author Ginny Dang 4 | * @brief 121. Best Time to Buy and Sell Stock (https://leetcode.com/problems/best-time-to-buy-and-sell-stock/description/) 5 | * @version 0.1 6 | * @date 2023-02-24 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int maxProfit(vector &prices) 16 | { 17 | int n = prices.size(); 18 | vector> profit(n, vector(3, INT_MAX)); 19 | 20 | for (int i = 0; i < n; i++) 21 | { 22 | // No sell or buy 23 | profit[i][0] = 0; 24 | // Buy 25 | if (i == 0) 26 | profit[i][1] = prices[i]; 27 | else 28 | profit[i][1] = min(profit[i - 1][1], prices[i]); 29 | // Sell after buy 30 | if (i == 0) 31 | profit[i][2] = 0; 32 | else 33 | profit[i][2] = max(prices[i] - profit[i][1], profit[i - 1][2]); 34 | } 35 | 36 | return profit[n - 1][2]; 37 | } 38 | }; 39 | 40 | // Time Complexity: O(N) 41 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /2. February/Day26EditDistance.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day26EditDistance.cpp 3 | * @author Ginny Dang 4 | * @brief 72. Edit Distance (https://leetcode.com/problems/edit-distance/description/) 5 | * @version 0.1 6 | * @date 2023-02-26 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | #define MAXM 500 13 | #define MAXN 500 14 | 15 | class Solution 16 | { 17 | public: 18 | int minDistance(string word1, string word2) 19 | { 20 | int m = word1.length(); 21 | int n = word2.length(); 22 | int L[MAXM + 1][MAXN + 1]; 23 | 24 | if (m == 0) 25 | return n; 26 | if (n == 0) 27 | return m; 28 | 29 | for (int i = 1; i <= m; i++) 30 | L[i][0] = i; 31 | 32 | for (int j = 1; j <= n; j++) 33 | L[0][j] = j; 34 | 35 | for (int i = 1; i <= m; i++) 36 | { 37 | for (int j = 1; j <= n; j++) 38 | { 39 | if (word1[i - 1] == word2[j - 1]) 40 | L[i][j] = L[i - 1][j - 1]; 41 | else 42 | L[i][j] = min(L[i - 1][j], min(L[i][j - 1], L[i - 1][j - 1])) + 1; 43 | } 44 | } 45 | 46 | return L[m][n]; 47 | } 48 | }; 49 | 50 | // Time Complexity: O(MN) 51 | // Space Complexity: O(MN) -------------------------------------------------------------------------------- /2. February/Day27ConstructQuadTree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day27ConstructQuadTree.cpp 3 | * @author Ginny Dang 4 | * @brief 427. Construct Quad Tree (https://leetcode.com/problems/construct-quad-tree/description/) 5 | * @version 0.1 6 | * @date 2023-02-27 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /* 13 | // Definition for a QuadTree node. 14 | class Node { 15 | public: 16 | bool val; 17 | bool isLeaf; 18 | Node* topLeft; 19 | Node* topRight; 20 | Node* bottomLeft; 21 | Node* bottomRight; 22 | 23 | Node() { 24 | val = false; 25 | isLeaf = false; 26 | topLeft = NULL; 27 | topRight = NULL; 28 | bottomLeft = NULL; 29 | bottomRight = NULL; 30 | } 31 | 32 | Node(bool _val, bool _isLeaf) { 33 | val = _val; 34 | isLeaf = _isLeaf; 35 | topLeft = NULL; 36 | topRight = NULL; 37 | bottomLeft = NULL; 38 | bottomRight = NULL; 39 | } 40 | 41 | Node(bool _val, bool _isLeaf, Node* _topLeft, Node* _topRight, Node* _bottomLeft, Node* _bottomRight) { 42 | val = _val; 43 | isLeaf = _isLeaf; 44 | topLeft = _topLeft; 45 | topRight = _topRight; 46 | bottomLeft = _bottomLeft; 47 | bottomRight = _bottomRight; 48 | } 49 | }; 50 | */ 51 | 52 | class Solution 53 | { 54 | public: 55 | Node *generateNode(vector> &grid, int x1, int y1, int length) 56 | { 57 | // If the grid size is 1 -> return a leaf node 58 | if (length == 1) 59 | return new Node(grid[x1][y1], true); 60 | 61 | // 4 sub-matrices 62 | Node *topLeft = generateNode(grid, x1, y1, length / 2); 63 | Node *topRight = generateNode(grid, x1, y1 + length / 2, length / 2); 64 | Node *bottomLeft = generateNode(grid, x1 + length / 2, y1, length / 2); 65 | Node *bottomRight = generateNode(grid, x1 + length / 2, y1 + length / 2, length / 2); 66 | 67 | // If these 4 nodes are leaf nodes and have the same value -> return a leaf node with that same value 68 | if (topLeft->isLeaf && topRight->isLeaf && bottomLeft->isLeaf && bottomRight->isLeaf && 69 | topLeft->val == topRight->val && topRight->val == bottomLeft->val && bottomLeft->val == bottomRight->val) 70 | return new Node(topLeft->val, true); 71 | 72 | // If these 4 nodes are not the same -> return a non-leaf node 73 | return new Node(false, false, topLeft, topRight, bottomLeft, bottomRight); 74 | } 75 | 76 | Node *construct(vector> &grid) 77 | { 78 | return generateNode(grid, 0, 0, grid.size()); 79 | } 80 | }; 81 | 82 | // Time Complexity: O(N^2) 83 | // Space Complexity: O(logN) -------------------------------------------------------------------------------- /2. February/Day28FindDuplicateSubtrees.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day28FindDuplicateSubtrees.cpp 3 | * @author Ginny Dang 4 | * @brief 652. Find Duplicate Subtrees (https://leetcode.com/problems/find-duplicate-subtrees/) 5 | * @version 0.1 6 | * @date 2023-02-27 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * Definition for a binary tree node. 14 | * struct TreeNode { 15 | * int val; 16 | * TreeNode *left; 17 | * TreeNode *right; 18 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 19 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 20 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 21 | * }; 22 | */ 23 | class Solution 24 | { 25 | public: 26 | vector findDuplicateSubtrees(TreeNode *root) 27 | { 28 | unordered_map tripletToId; 29 | unordered_map count; 30 | vector result; 31 | 32 | function traverse = [&tripletToId, &count, &result, &traverse](TreeNode *node) -> int 33 | { 34 | if (node == nullptr) 35 | return 0; 36 | 37 | string triplet = to_string(traverse(node->left)) + "," + to_string(node->val) + "," + to_string(traverse(node->right)); 38 | 39 | if (!tripletToId.count(triplet)) 40 | tripletToId[triplet] = tripletToId.size() + 1; 41 | 42 | int id = tripletToId[triplet]; 43 | count[id]++; 44 | if (count[id] == 2) 45 | result.push_back(node); 46 | 47 | return id; 48 | }; 49 | 50 | traverse(root); 51 | return result; 52 | } 53 | }; 54 | 55 | // Time Complexity: O(N) 56 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /2. February/Day2VerifyingAnAlienDictionary.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day2VerifyingAnAlienDictionary.cpp 3 | * @author Ginny Dang 4 | * @brief 953. Verifying an Alien Dictionary (https://leetcode.com/problems/verifying-an-alien-dictionary/description/) 5 | * @version 0.1 6 | * @date 2023-02-01 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | bool isAlienSorted(vector &words, string order) 16 | { 17 | unordered_map charToRank; 18 | for (int i = 0; i < order.length(); i++) 19 | charToRank.insert({order[i], i}); 20 | 21 | for (int i = 1; i < words.size(); i++) 22 | { 23 | string word1 = words[i - 1]; 24 | string word2 = words[i]; 25 | int minLength = min(word1.length(), word2.length()); 26 | for (int j = 0; j < minLength; j++) 27 | { 28 | // cout << word1[j] << " " << word2[j] << "\n"; 29 | if (charToRank[word1[j]] > charToRank[word2[j]]) 30 | return false; 31 | else if (charToRank[word1[j]] == charToRank[word2[j]]) 32 | { 33 | if (j == minLength - 1) 34 | if (word1.length() > word2.length()) 35 | return false; 36 | continue; 37 | } 38 | else 39 | break; 40 | } 41 | } 42 | return true; 43 | } 44 | }; 45 | 46 | // Time Complexity: O(N) 47 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /2. February/Day3ZigzagConversion.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day3ZigzagConversion.cpp 3 | * @author Ginny Dang 4 | * @brief 6. Zigzag Conversion (https://leetcode.com/problems/zigzag-conversion/description/) 5 | * @version 0.1 6 | * @date 2023-02-02 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | string convert(string s, int numRows) 16 | { 17 | if (numRows == 1) 18 | return s; 19 | string result; 20 | int increment = 2 * (numRows - 1); 21 | for (int i = 0; i < numRows; i++) 22 | { 23 | for (int j = i; j < s.length(); j += increment) 24 | { 25 | result += s[j]; 26 | if (i > 0 && i < numRows - 1 && j + increment - 2 * i < s.length()) 27 | result += s[j + increment - 2 * i]; 28 | } 29 | } 30 | return result; 31 | } 32 | }; 33 | 34 | // Time Complexity: O(M * N) 35 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /2. February/Day4PermutationInString.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day4PermutationInString.cpp 3 | * @author Ginny Dang 4 | * @brief 567. Permutation in String (https://leetcode.com/problems/permutation-in-string/description/) 5 | * @version 0.1 6 | * @date 2023-02-04 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | bool match(int s1Map[], int s2Map[]) 16 | { 17 | for (int i = 0; i < 26; i++) 18 | if (s1Map[i] > s2Map[i]) 19 | return false; 20 | return true; 21 | } 22 | 23 | bool checkInclusion(string s1, string s2) 24 | { 25 | if (s1.length() > s2.length()) 26 | return false; 27 | 28 | int s1Map[26] = {}; 29 | int s2Map[26] = {}; 30 | 31 | for (int i = 0; i < s1.length(); i++) 32 | { 33 | s1Map[s1[i] - 'a']++; 34 | s2Map[s2[i] - 'a']++; 35 | } 36 | 37 | for (int i = 0; i < s2.length() - s1.length(); i++) 38 | { 39 | if (match(s1Map, s2Map)) 40 | return true; 41 | 42 | s2Map[s2[i + s1.length()] - 'a']++; 43 | s2Map[s2[i] - 'a']--; 44 | } 45 | 46 | return match(s1Map, s2Map); 47 | } 48 | }; 49 | 50 | // Time Complexity: O(max(min(M, N), (M - N))) where M = s1.length(), N = s2.length() 51 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /2. February/Day5FindAllAnagramsInAString.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day5FindAllAnagramsInAString.cpp 3 | * @author Ginny Dang 4 | * @brief 438. Find All Anagrams in a String (https://leetcode.com/problems/find-all-anagrams-in-a-string/description/) 5 | * @version 0.1 6 | * @date 2023-02-05 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | bool match(int mapS[], int mapP[]) 16 | { 17 | for (int i = 0; i < 26; i++) 18 | if (mapS[i] != mapP[i]) 19 | return false; 20 | return true; 21 | } 22 | 23 | vector findAnagrams(string s, string p) 24 | { 25 | vector result; 26 | 27 | if (p.length() > s.length()) 28 | return result; 29 | 30 | int mapS[26] = {}; 31 | int mapP[26] = {}; 32 | 33 | for (char c : p) 34 | mapP[c - 'a']++; 35 | 36 | for (int i = 0; i < p.length(); i++) 37 | mapS[s[i] - 'a']++; 38 | 39 | for (int i = 1; i + p.length() <= s.length(); i++) 40 | { 41 | if (match(mapS, mapP)) 42 | result.push_back(i - 1); 43 | mapS[s[i - 1] - 'a']--; 44 | mapS[s[i + p.length() - 1] - 'a']++; 45 | } 46 | 47 | if (match(mapS, mapP)) 48 | result.push_back(s.length() - p.length()); 49 | 50 | return result; 51 | } 52 | }; 53 | 54 | // Time Complexity: O(26 * N) 55 | // Space Complexity: O(1) or O(26) to be exact -------------------------------------------------------------------------------- /2. February/Day6ShuffleTheArray.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day6ShuffleTheArray.cpp 3 | * @author Ginny Dang 4 | * @brief 1470. Shuffle the Array (https://leetcode.com/problems/shuffle-the-array/description/) 5 | * @version 0.1 6 | * @date 2023-02-05 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * @brief New algorithm learned from the Official Solution 14 | * - Iterate on the nums array from index i = n to 2 * n - 1: 15 | * -- Store the element y_(i+1), that is, nums[i] with x_(i+1) at index (i - n), using bit manipulation. 16 | * - Iterate from index n - 1 to 0, and at each index i: 17 | * -- Extract both firstNumber and secondNumber using bit manipulation and store them at their respective indices 2 * i and 2 * i + 1 in the nums array. 18 | * - Return the nums array. 19 | */ 20 | 21 | class Solution 22 | { 23 | public: 24 | vector shuffle(vector &nums, int n) 25 | { 26 | for (int i = n; i < 2 * n; i++) 27 | nums[i - n] |= (nums[i] << 10); // Storing 2 number at the same element 28 | 29 | int allOnes = pow(2, 10) - 1; // '0000000000 1111111111' in decimal. 30 | 31 | for (int i = n - 1; i >= 0; i--) 32 | { 33 | int firstNumber = nums[i] & allOnes; 34 | int secondNumber = nums[i] >> 10; 35 | 36 | nums[i * 2] = firstNumber; 37 | nums[i * 2 + 1] = secondNumber; 38 | } 39 | 40 | return nums; 41 | } 42 | }; 43 | 44 | // Time Complexity: O(N) 45 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /2. February/Day7FruitIntoBaskets.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day7FruitIntoBaskets.cpp 3 | * @author Ginny Dang 4 | * @brief 904. Fruit Into Baskets (https://leetcode.com/problems/fruit-into-baskets/description/) 5 | * @version 0.1 6 | * @date 2023-02-06 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int totalFruit(vector &fruits) 16 | { 17 | int left = 0; 18 | unordered_map unique; 19 | int maxLength = 0; 20 | 21 | for (int right = 0; right < fruits.size(); right++) 22 | { 23 | unique[fruits[right]]++; 24 | if (unique.size() > 2) 25 | { 26 | unique[fruits[left]]--; 27 | if (!unique[fruits[left]]) 28 | unique.erase(fruits[left]); 29 | left++; 30 | } 31 | maxLength = max(maxLength, right - left + 1); 32 | } 33 | 34 | return maxLength; 35 | } 36 | }; 37 | 38 | // Time Complexity: O(N) 39 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /2. February/Day8JumpGameII.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day8JumpGameII.cpp 3 | * @author Ginny Dang 4 | * @brief 45. Jump Game II (https://leetcode.com/problems/jump-game-ii/description/) 5 | * @version 0.1 6 | * @date 2023-02-07 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int jump(vector &nums) 16 | { 17 | int n = nums.size(); 18 | vector minJumps(n, INT_MAX); 19 | minJumps[0] = 0; // No need to jump to the starting point 20 | 21 | // Considering each pos i 22 | for (int i = 0; i < n; i++) 23 | { 24 | // Optimize by not considering all positions that sure cannot reach i with 1 jump 25 | int minJ; 26 | minJ = i > 1000 ? i - 1000 : 0; 27 | // Considering all positions j's before i 28 | for (int j = minJ; j < i; j++) 29 | { 30 | // Check if pos i can be reached fro the current pos j 31 | if (nums[j] >= (i - j)) 32 | minJumps[i] = min(minJumps[i], minJumps[j] + 1); 33 | // Otherwise, go to the next pos j to find min_jumps[i] 34 | } 35 | } 36 | 37 | return minJumps[n - 1]; 38 | } 39 | }; 40 | 41 | // Time Complexity: O(1000*N) or O(10^3 * 10^4) -> O(10^7) 42 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /2. February/Day9NamingACompany.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day9NamingACompany.cpp 3 | * @author Ginny Dang 4 | * @brief 2306. Naming a Company (https://leetcode.com/problems/naming-a-company/description/) 5 | * @version 0.1 6 | * @date 2023-02-08 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * @brief New algorithm learned from the Official Solution 14 | * - Group words in ideas by their initials in initial_group, an array of sets of length 26, and initialize answer as 0. 15 | * - Iterate over every pair of groups. For each group i and j, get the number of suffixes num_of_mutual that appears in both groups. 16 | * - We can swap every distinct suffix in group i with every distinct suffix in group j, increment answer by 2 * (len(group[i]) - num_of_mutual) * (len(group[j]) - num_of_mutual) 17 | * - Return answer. 18 | */ 19 | 20 | class Solution 21 | { 22 | public: 23 | long long distinctNames(vector &ideas) 24 | { 25 | long long answer = 0; 26 | unordered_set initialGroup[26]; 27 | 28 | for (string &idea : ideas) 29 | initialGroup[idea[0] - 'a'].insert(idea.substr(1)); 30 | 31 | for (int i = 0; i < 25; i++) 32 | { 33 | for (int j = i + 1; j < 26; j++) 34 | { 35 | int numOfMutual = 0; 36 | for (auto &ideaA : initialGroup[i]) 37 | if (initialGroup[j].count(ideaA)) 38 | numOfMutual++; 39 | 40 | answer += 2LL * (initialGroup[i].size() - numOfMutual) * (initialGroup[j].size() - numOfMutual); 41 | } 42 | } 43 | 44 | return answer; 45 | } 46 | }; 47 | 48 | // Time Complexity: O(M * N) where N is the number of words in ideas and M is the average length of a word. 49 | // Space Complexity: O(M * N) where N is the number of words in ideas and M is the average length of a word. -------------------------------------------------------------------------------- /3. March/Day10LinkedListRandomNode.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day10LinkedListRandomNode.cpp 3 | * @author Ginny Dang 4 | * @brief 382. Linked List Random Node (https://leetcode.com/problems/linked-list-random-node/description/) 5 | * @version 0.1 6 | * @date 2023-03-10 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * @brief New thing I've learned from this challenge 14 | * Reservoir Sampling method 15 | * References: https://www.youtube.com/watch?v=A1iwzSew5QY&t=1s 16 | */ 17 | 18 | /** 19 | * Definition for singly-linked list. 20 | * struct ListNode { 21 | * int val; 22 | * ListNode *next; 23 | * ListNode() : val(0), next(nullptr) {} 24 | * ListNode(int x) : val(x), next(nullptr) {} 25 | * ListNode(int x, ListNode *next) : val(x), next(next) {} 26 | * }; 27 | */ 28 | class Solution 29 | { 30 | ListNode *head; 31 | 32 | public: 33 | Solution(ListNode *head) 34 | { 35 | this->head = head; 36 | } 37 | 38 | int getRandom() 39 | { 40 | int scope = 1, chosenValue = 0; 41 | ListNode *curr = this->head; 42 | 43 | while (curr) 44 | { 45 | // Decide whether to include the element in the reservoir 46 | /* rand() % scope will be 0 only if rand() returns 0 or some multiple of scope */ 47 | if (rand() % scope == 0) 48 | chosenValue = curr->val; 49 | // Move to the next node 50 | scope++; 51 | curr = curr->next; 52 | } 53 | 54 | return chosenValue; 55 | } 56 | }; 57 | 58 | // Time Complexity: O(N) for getRandom() 59 | // Space Complexity: O(1) 60 | 61 | /** 62 | * Your Solution object will be instantiated and called as such: 63 | * Solution* obj = new Solution(head); 64 | * int param_1 = obj->getRandom(); 65 | */ -------------------------------------------------------------------------------- /3. March/Day11ConvertSortedListToBinarySearchTree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day11ConvertSortedListToBinarySearchTree.cpp 3 | * @author Ginny Dang 4 | * @brief 109. Convert Sorted List to Binary Search Tree (https://leetcode.com/problems/convert-sorted-list-to-binary-search-tree/description/) 5 | * @version 0.1 6 | * @date 2023-03-10 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * Definition for singly-linked list. 14 | * struct ListNode { 15 | * int val; 16 | * ListNode *next; 17 | * ListNode() : val(0), next(nullptr) {} 18 | * ListNode(int x) : val(x), next(nullptr) {} 19 | * ListNode(int x, ListNode *next) : val(x), next(next) {} 20 | * }; 21 | */ 22 | /** 23 | * Definition for a binary tree node. 24 | * struct TreeNode { 25 | * int val; 26 | * TreeNode *left; 27 | * TreeNode *right; 28 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 29 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 30 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 31 | * }; 32 | */ 33 | class Solution 34 | { 35 | public: 36 | // O(logN) 37 | TreeNode *buildBST(vector &nodeVals, int start, int end) 38 | { 39 | // Edge cases 40 | if (start == end) 41 | return new TreeNode(nodeVals[start]); 42 | else if (start > end) 43 | return NULL; 44 | 45 | // Normal cases 46 | int mid = (start + end) / 2; 47 | TreeNode *bst = new TreeNode(nodeVals[mid]); 48 | bst->left = buildBST(nodeVals, start, mid - 1); 49 | bst->right = buildBST(nodeVals, mid + 1, end); 50 | return bst; 51 | } 52 | 53 | // O(N) 54 | TreeNode *sortedListToBST(ListNode *head) 55 | { 56 | // Gather values of all nodes in the linked list 57 | vector nodeVals; 58 | ListNode *curr = head; 59 | while (curr) 60 | { 61 | nodeVals.push_back(curr->val); 62 | curr = curr->next; 63 | } 64 | 65 | // Build BST 66 | int n = nodeVals.size(); 67 | TreeNode *bst = buildBST(nodeVals, 0, n - 1); 68 | return bst; 69 | } 70 | }; 71 | 72 | // Time Complexity: O(N) 73 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /3. March/Day12MergeKSortedLists.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day12MergeKSortedLists.cpp 3 | * @author Ginny Dang 4 | * @brief 23. Merge k Sorted Lists (https://leetcode.com/problems/merge-k-sorted-lists/description/) 5 | * @version 0.1 6 | * @date 2023-03-11 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * Definition for singly-linked list. 14 | * struct ListNode { 15 | * int val; 16 | * ListNode *next; 17 | * ListNode() : val(0), next(nullptr) {} 18 | * ListNode(int x) : val(x), next(nullptr) {} 19 | * ListNode(int x, ListNode *next) : val(x), next(next) {} 20 | * }; 21 | */ 22 | class Solution 23 | { 24 | public: 25 | ListNode *mergeKLists(vector &lists) 26 | { 27 | // Define a custom comparison function 28 | auto cmp = [](pair a, pair b) 29 | { 30 | return a.first > b.first; 31 | }; 32 | 33 | // Create a heap of {value, index} pairs 34 | priority_queue, vector>, decltype(cmp)> minHeap(cmp); 35 | for (int i = 0; i < lists.size(); i++) 36 | if (lists[i]) 37 | minHeap.push({lists[i]->val, i}); 38 | 39 | // Merge lists 40 | ListNode *curr = new ListNode(); 41 | ListNode *dummy = curr; 42 | while (!minHeap.empty()) 43 | { 44 | int idx = minHeap.top().second; 45 | minHeap.pop(); 46 | 47 | curr->next = lists[idx]; 48 | curr = curr->next; 49 | lists[idx] = lists[idx]->next; 50 | 51 | if (lists[idx]) 52 | minHeap.push({lists[idx]->val, idx}); 53 | } 54 | 55 | return dummy->next; 56 | } 57 | }; 58 | 59 | // Time Complexity: O(Nlogk) where N is the number of nodes in the final linked list, k is the number of linked lists. 60 | // Space Complexity: O(N) for creating a new linked list. O(k) for the priority queue. N is the number of nodes in the final linked list, k is the number of linked lists. -------------------------------------------------------------------------------- /3. March/Day13SymmetricTree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day13SymmetricTree.cpp 3 | * @author Ginny Dang 4 | * @brief 101. Symmetric Tree (https://leetcode.com/problems/symmetric-tree/description/) 5 | * @version 0.1 6 | * @date 2023-03-12 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * Definition for a binary tree node. 14 | * struct TreeNode { 15 | * int val; 16 | * TreeNode *left; 17 | * TreeNode *right; 18 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 19 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 20 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 21 | * }; 22 | */ 23 | class Solution 24 | { 25 | public: 26 | bool compareSubtrees(TreeNode *root1, TreeNode *root2) 27 | { 28 | // Base cases 29 | if (!root1 && !root2) 30 | return true; 31 | else if (!root1 || !root2) 32 | return false; 33 | // Normal case 34 | else if (root1->val != root2->val) 35 | return false; 36 | else 37 | return compareSubtrees(root1->left, root2->right) && compareSubtrees(root1->right, root2->left); 38 | } 39 | 40 | bool isSymmetric(TreeNode *root) 41 | { 42 | // Root has no children 43 | if (!root->left && !root->right) 44 | return true; 45 | // Root has some children 46 | return compareSubtrees(root->left, root->right); 47 | } 48 | }; 49 | 50 | // Time Complexity: O(N) 51 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /3. March/Day14SumRootToLeafNumbers.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day14SumRootToLeafNumbers.cpp 3 | * @author Ginny Dang 4 | * @brief 129. Sum Root to Leaf Numbers (https://leetcode.com/problems/sum-root-to-leaf-numbers/description/) 5 | * @version 0.1 6 | * @date 2023-03-13 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * Definition for a binary tree node. 14 | * struct TreeNode { 15 | * int val; 16 | * TreeNode *left; 17 | * TreeNode *right; 18 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 19 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 20 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 21 | * }; 22 | */ 23 | class Solution 24 | { 25 | int allPathsSum = 0; 26 | 27 | public: 28 | void rootToLeaf(TreeNode *curNode, vector &curPath) 29 | { 30 | // curNode is NULL 31 | if (!curNode) 32 | return; 33 | // Add the curNode to curPath 34 | curPath.push_back(curNode->val); 35 | // curNode is the leaf node 36 | if (!curNode->left && !curNode->right) 37 | { 38 | string currPathSum = ""; 39 | for (int num : curPath) 40 | currPathSum += to_string(num); 41 | this->allPathsSum += stoi(currPathSum); 42 | } 43 | // cur_node is not the leaf node 44 | else 45 | { 46 | // Explore left branch of cur_node 47 | if (curNode->left) 48 | rootToLeaf(curNode->left, curPath); 49 | // Explore right branch of cur_node 50 | if (curNode->right) 51 | rootToLeaf(curNode->right, curPath); 52 | } 53 | // Backtrack 54 | curPath.pop_back(); 55 | } 56 | 57 | int sumNumbers(TreeNode *root) 58 | { 59 | vector curPath; 60 | rootToLeaf(root, curPath); 61 | return this->allPathsSum; 62 | } 63 | }; 64 | 65 | // Time Complexity: O(N) 66 | // Space Complexity: O(H) -------------------------------------------------------------------------------- /3. March/Day15.CheckCompletenessOfABinaryTree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day15.CheckCompletenessOfABinaryTree.cpp 3 | * @author Ginny Dang 4 | * @brief 958. Check Completeness of a Binary Tree (https://leetcode.com/problems/check-completeness-of-a-binary-tree/description/) 5 | * @version 0.1 6 | * @date 2023-03-15 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * @brief New thing I've learned from this challenge 14 | * - Check if a binary tree is a Complete Binary Tree using BFS 15 | * -- At each level, check whether the left and right child nodes of the current node exist 16 | * ---- If left != NULL and right = NULL 17 | * ------> Mark the node as the last node 18 | * ---- If right != NULL and left = NULL 19 | * ------> Return false as a binary tree cannot have a right child without a left child 20 | * ---- If there's any node found after the last node has been found or there's a node with only 1 child 21 | * ------> Return false as this is not a complete binary tree 22 | * ---- If we reach the end of the tree without any issues 23 | * ------> Return true. 24 | * -- Use a boolean variable to keep track of whether we have already found the last node 25 | */ 26 | 27 | /** 28 | * Definition for a binary tree node. 29 | * struct TreeNode { 30 | * int val; 31 | * TreeNode *left; 32 | * TreeNode *right; 33 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 34 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 35 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 36 | * }; 37 | */ 38 | class Solution 39 | { 40 | public: 41 | bool isCompleteTree(TreeNode *root) 42 | { 43 | // Base case: No node -> no level -> complete 44 | if (!root) 45 | return true; 46 | 47 | // Normal case: Check level by level from left to right with BFS 48 | queue q; 49 | q.push(root); 50 | bool lastNodeFound = false; 51 | 52 | while (!q.empty()) 53 | { 54 | TreeNode *curr = q.front(); 55 | q.pop(); 56 | 57 | if (curr->left) 58 | { 59 | if (lastNodeFound) 60 | return false; 61 | q.push(curr->left); 62 | } 63 | else 64 | lastNodeFound = true; 65 | 66 | if (curr->right) 67 | { 68 | if (lastNodeFound) 69 | return false; 70 | q.push(curr->right); 71 | } 72 | else 73 | lastNodeFound = true; 74 | } 75 | 76 | return true; 77 | } 78 | }; 79 | 80 | // Time Complexity: O(N) 81 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /3. March/Day16ConstructBinaryTreeFromInorderAndPostorderTraversal.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day16ConstructBinaryTreeFromInorderAndPostorderTraversal.cpp 3 | * @author Ginny Dang 4 | * @brief 106. Construct Binary Tree from Inorder and Postorder Traversal (https://leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/description/) 5 | * @version 0.1 6 | * @date 2023-03-15 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * Definition for a binary tree node. 14 | * struct TreeNode { 15 | * int val; 16 | * TreeNode *left; 17 | * TreeNode *right; 18 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 19 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 20 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 21 | * }; 22 | */ 23 | class Solution 24 | { 25 | private: 26 | int treeSize; 27 | unordered_map inMap; 28 | 29 | TreeNode *helpBuildTree(vector &inorder, int inStart, int inEnd, vector &postorder, int postStart, int postEnd) 30 | { 31 | // Base case 32 | if (inStart > inEnd) 33 | return NULL; 34 | // Normal cases 35 | //// Determine the current root node 36 | int curRootVal = postorder[postEnd]; 37 | int inRootPos = inMap[curRootVal]; 38 | TreeNode *curRoot = new TreeNode(curRootVal, NULL, NULL); 39 | // Define the range of the left and right subtrees of the current root 40 | //// Range of the left subtree in Inorder 41 | int inLeftStart = inStart; 42 | int inLeftEnd = inRootPos - 1; 43 | int leftTreeSize = (inLeftEnd - inLeftStart) + 1; 44 | //// Range of the right subtree in Inorder 45 | int inRightStart = inRootPos + 1; 46 | int inRightEnd = inEnd; 47 | //// Range of the left subtree in Postorder 48 | int postLeftStart = postStart; 49 | int postLeftEnd = postLeftStart + leftTreeSize - 1; 50 | //// Range of the right subtree in Postorder 51 | int postRightStart = postLeftEnd + 1; 52 | int postRightEnd = postEnd - 1; 53 | // Construct the left and right subtrees of the current root 54 | curRoot->left = helpBuildTree(inorder, inLeftStart, inLeftEnd, postorder, postLeftStart, postLeftEnd); 55 | curRoot->right = helpBuildTree(inorder, inRightStart, inRightEnd, postorder, postRightStart, postRightEnd); 56 | return curRoot; 57 | } 58 | 59 | public: 60 | TreeNode *buildTree(vector &inorder, vector &postorder) 61 | { 62 | // Edge case 63 | if (inorder.size() == 1) 64 | return new TreeNode(inorder[0], NULL, NULL); 65 | // Normal cases 66 | treeSize = inorder.size(); 67 | for (int i = 0; i < treeSize; i++) 68 | inMap[inorder[i]] = i; 69 | return helpBuildTree(inorder, 0, treeSize - 1, postorder, 0, treeSize - 1); 70 | } 71 | }; 72 | 73 | // Time Complexity: O(N) 74 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /3. March/Day17ImplementTriePrefixTree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day17ImplementTriePrefixTree.cpp 3 | * @author Ginny Dang 4 | * @brief 208. Implement Trie (Prefix Tree) (https://leetcode.com/problems/implement-trie-prefix-tree/description/) 5 | * @version 0.1 6 | * @date 2023-03-16 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Trie 13 | { 14 | private: 15 | // The nested structure representing a node 16 | struct TrieNode 17 | { 18 | // Properties 19 | unordered_map children; 20 | bool isWord; 21 | 22 | // Constructor 23 | TrieNode() : isWord(false) {} 24 | 25 | // Destructor 26 | ~TrieNode() 27 | { 28 | for (auto &child : children) 29 | delete child.second; 30 | } 31 | }; 32 | 33 | TrieNode *root; 34 | 35 | // Helper method to find the last node in the sequence of characters in the input string 36 | // O(L) where L is the length of the prefix 37 | const TrieNode *find(const string &prefix) const 38 | { 39 | const TrieNode *currNode = root; 40 | for (char ch : prefix) 41 | { 42 | if (!currNode->children.count(ch)) 43 | return nullptr; 44 | currNode = currNode->children.at(ch); 45 | } 46 | return currNode; 47 | } 48 | 49 | public: 50 | // Constructor 51 | Trie() 52 | { 53 | root = new TrieNode(); 54 | } 55 | 56 | // Destructor 57 | ~Trie() 58 | { 59 | delete root; 60 | } 61 | 62 | // Method to insert a word into the trie 63 | // O(L) where L is the length of the word 64 | void insert(string word) 65 | { 66 | TrieNode *currNode = root; 67 | for (char ch : word) 68 | { 69 | if (!currNode->children.count(ch)) 70 | currNode->children[ch] = new TrieNode(); 71 | currNode = currNode->children[ch]; 72 | } 73 | currNode->isWord = true; 74 | } 75 | 76 | // Method to search for a word in the trie 77 | // O(L) where L is the length of the word 78 | bool search(string word) 79 | { 80 | const TrieNode *node = find(word); 81 | return node && node->isWord; 82 | } 83 | 84 | // Method to check if prefix belongs to any existing word in the trie 85 | // O(L) where L is the length of the prefix 86 | bool startsWith(string prefix) 87 | { 88 | return find(prefix) != nullptr; 89 | } 90 | }; 91 | 92 | // Time Complexity: O(N) 93 | // Space Complexity: O(max_string_length) or O(2000) due to the given constraint 94 | 95 | /** 96 | * Your Trie object will be instantiated and called as such: 97 | * Trie* obj = new Trie(); 98 | * obj->insert(word); 99 | * bool param_2 = obj->search(word); 100 | * bool param_3 = obj->startsWith(prefix); 101 | */ -------------------------------------------------------------------------------- /3. March/Day18DesignBrowserHistory.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day18DesignBrowserHistory.cpp 3 | * @author Ginny Dang 4 | * @brief 1472. Design Browser History (https://leetcode.com/problems/design-browser-history/description/) 5 | * @version 0.1 6 | * @date 2023-03-17 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class BrowserHistory 13 | { 14 | private: 15 | vector curPages; 16 | int curIdx; 17 | int lastIdx; 18 | 19 | public: 20 | BrowserHistory(string homepage) 21 | { 22 | curPages.push_back(homepage); 23 | curIdx = 0; 24 | lastIdx = 0; 25 | } 26 | 27 | // O(1) 28 | void visit(string url) 29 | { 30 | curIdx++; 31 | if (curPages.size() > curIdx) 32 | curPages[curIdx] = url; 33 | else 34 | curPages.push_back(url); 35 | lastIdx = curIdx; 36 | } 37 | 38 | // O(1) 39 | string back(int steps) 40 | { 41 | curIdx = max(curIdx - steps, 0); 42 | return curPages[curIdx]; 43 | } 44 | 45 | // O(1) 46 | string forward(int steps) 47 | { 48 | curIdx = min(curIdx + steps, lastIdx); 49 | return curPages[curIdx]; 50 | } 51 | }; 52 | 53 | /** 54 | * Your BrowserHistory object will be instantiated and called as such: 55 | * BrowserHistory* obj = new BrowserHistory(homepage); 56 | * obj->visit(url); 57 | * string param_2 = obj->back(steps); 58 | * string param_3 = obj->forward(steps); 59 | */ 60 | 61 | // Time Complexity: O(1) 62 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /3. March/Day19DesignAddAndSearchWordsDataStructure.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day19DesignAddAndSearchWordsDataStructure.cpp 3 | * @author Ginny Dang 4 | * @brief 211. Design Add and Search Words Data Structure (https://leetcode.com/problems/design-add-and-search-words-data-structure/description/) 5 | * @version 0.1 6 | * @date 2023-03-18 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class WordDictionary 13 | { 14 | private: 15 | struct TrieNode 16 | { 17 | unordered_map children; 18 | int countWords; 19 | 20 | TrieNode() : countWords(0) {} 21 | 22 | ~TrieNode() 23 | { 24 | for (auto &child : children) 25 | delete child.second; 26 | } 27 | }; 28 | 29 | TrieNode *root; 30 | 31 | // O(26^3) 32 | bool dfs(TrieNode *currNode, int level, string &word) 33 | { 34 | if (level == word.length()) 35 | return currNode->countWords > 0; 36 | else 37 | { 38 | if (word[level] == '.') 39 | { 40 | for (const auto &child : currNode->children) 41 | if (dfs(child.second, level + 1, word)) 42 | return true; 43 | } 44 | else 45 | { 46 | if (currNode->children.count(word[level])) 47 | if (dfs(currNode->children[word[level]], level + 1, word)) 48 | return true; 49 | } 50 | } 51 | return false; 52 | } 53 | 54 | public: 55 | WordDictionary() 56 | { 57 | root = new TrieNode(); 58 | } 59 | 60 | ~WordDictionary() 61 | { 62 | delete root; 63 | } 64 | 65 | // O(25) 66 | void addWord(string word) 67 | { 68 | TrieNode *currNode = root; 69 | for (char letter : word) 70 | { 71 | if (!currNode->children.count(letter)) 72 | currNode->children[letter] = new TrieNode(); 73 | currNode = currNode->children[letter]; 74 | } 75 | currNode->countWords++; 76 | } 77 | 78 | // O(26^3) 79 | bool search(string word) 80 | { 81 | return dfs(root, 0, word); 82 | } 83 | }; 84 | 85 | // Time Complexity: O(26^3) for search(), O(N) for addWord() where N is the length of the input word 86 | // Space Complexity: O(N) 87 | 88 | /** 89 | * Your WordDictionary object will be instantiated and called as such: 90 | * WordDictionary* obj = new WordDictionary(); 91 | * obj->addWord(word); 92 | * bool param_2 = obj->search(word); 93 | */ 94 | -------------------------------------------------------------------------------- /3. March/Day1SortAnArray.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day1SortAnArray.cpp 3 | * @author Ginny Dang 4 | * @brief 912. Sort an Array (https://leetcode.com/problems/sort-an-array/) 5 | * @version 0.1 6 | * @date 2023-02-28 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * Merge Sort Solution - Short version 14 | * segment [l, r) 15 | * 16 | * merge_sort(arr, start, end) calls itself with smaller arrays merge_sort(arr, start, mid) and merge_sort(arr, mid+1, end). 17 | * The two subarrays are sorted when the recursive call ends so we end up with two sorted arrays, arr[start...mid] and arr[mid+1...end]. 18 | */ 19 | 20 | class Solution 21 | { 22 | private: 23 | void merge(vector &nums, int start, int mid, int end) 24 | { 25 | int size1 = mid - start + 1; 26 | int size2 = end - mid; 27 | int left[size1], right[size2]; 28 | 29 | for (int i = 0; i < size1; i++) 30 | left[i] = nums[i + start]; 31 | for (int j = 0; j < size2; j++) 32 | right[j] = nums[j + mid + 1]; 33 | 34 | // Merge sorted arrays left and right into arr[start...end] 35 | int l = 0; // ptr of left subarray 36 | int r = 0; // ptr of right subarray 37 | int a = start; // ptr of the full size arrays 38 | 39 | while (l < size1 && r < size2) 40 | { 41 | if (left[l] < right[r]) 42 | nums[a++] = left[l++]; 43 | else 44 | nums[a++] = right[r++]; 45 | } 46 | 47 | // Either left or right subarray will exhaust first, we'll copy the remaining to nums 48 | while (l < size1) 49 | nums[a++] = left[l++]; 50 | while (r < size2) 51 | nums[a++] = right[r++]; 52 | } 53 | 54 | private: 55 | void mergeSort(vector &nums, int start, int end) 56 | { 57 | if (start >= end) 58 | return; 59 | 60 | int mid = (start + end) / 2; 61 | 62 | mergeSort(nums, start, mid); 63 | mergeSort(nums, mid + 1, end); 64 | 65 | merge(nums, start, mid, end); 66 | } 67 | 68 | public: 69 | vector sortArray(vector &nums) 70 | { 71 | mergeSort(nums, 0, nums.size() - 1); 72 | return nums; 73 | } 74 | }; 75 | 76 | // Time Complexity: O(NlogN) 77 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /3. March/Day20CanPlaceFlowers.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day20CanPlaceFlowers.cpp 3 | * @author Ginny Dang 4 | * @brief 605. Can Place Flowers (https://leetcode.com/problems/can-place-flowers/description/) 5 | * @version 0.1 6 | * @date 2023-03-19 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | bool canPlaceFlowers(vector &flowerbed, int n) 16 | { 17 | int numPlots = flowerbed.size(); 18 | 19 | // Edge case 20 | if (numPlots == 1) 21 | { 22 | // Cannot place any flower in that only spot 23 | if (flowerbed[0] == 1) 24 | return n == 0; 25 | // Can only place 1 flower in that only spot 26 | else 27 | return n <= 1; 28 | } 29 | 30 | // Normal case 31 | if (flowerbed[0] == 0 && flowerbed[1] == 0) 32 | { 33 | flowerbed[0] = 1; 34 | n--; 35 | } 36 | 37 | if (flowerbed[numPlots - 1] == 0 && flowerbed[numPlots - 2] == 0) 38 | { 39 | flowerbed[numPlots - 1] = 1; 40 | n -= 1; 41 | } 42 | 43 | for (int i = 1; i < numPlots - 1; i++) 44 | { 45 | if (flowerbed[i] == 0 && flowerbed[i - 1] == 0 && flowerbed[i + 1] == 0) 46 | { 47 | flowerbed[i] = 1; 48 | n--; 49 | } 50 | } 51 | 52 | return n <= 0; 53 | } 54 | }; 55 | 56 | // Time Complexity: O(N) 57 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /3. March/Day21NumberOfZeroFilledSubarrays.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day21NumberOfZeroFilledSubarrays.cpp 3 | * @author Ginny Dang 4 | * @brief 2348. Number of Zero-Filled Subarrays (https://leetcode.com/problems/number-of-zero-filled-subarrays/description/) 5 | * @version 0.1 6 | * @date 2023-03-20 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * @brief Main formula 14 | * - Calculate the total number of subarrays of an array: 15 | * -- Total subarrays = n * (n + 1) / 2 16 | * --- n is the length of the array 17 | * --- There are n subarrays of length 1, 18 | * n-1 subarrays of length 2, 19 | * n-2 subarrays of length 3, 20 | * ..... 21 | * 1 subarray of length n. 22 | * => The total number of subarrays is the sum of these subarrays, which is equal to n * (n + 1) / 2. 23 | */ 24 | 25 | class Solution 26 | { 27 | public: 28 | long long zeroFilledSubarray(vector &nums) 29 | { 30 | long long result = 0; 31 | long long numConsecZeros = 0; 32 | int n = nums.size(); 33 | 34 | for (int i = 0; i < n; i++) 35 | { 36 | if (nums[i] == 0) 37 | numConsecZeros++; 38 | else 39 | { 40 | result += numConsecZeros * (numConsecZeros + 1) / 2; 41 | numConsecZeros = 0; 42 | } 43 | } 44 | 45 | if (numConsecZeros != 0) 46 | result += numConsecZeros * (numConsecZeros + 1) / 2; 47 | 48 | return result; 49 | } 50 | }; 51 | 52 | // Time Complexity: O(N) 53 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /3. March/Day22MinimumScoreOfAPathBetweenTwoCities.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day22MinimumScoreOfAPathBetweenTwoCities.cpp 3 | * @author Ginny Dang 4 | * @brief 2492. Minimum Score of a Path Between Two Cities (https://leetcode.com/problems/minimum-score-of-a-path-between-two-cities/description/) 5 | * @version 0.1 6 | * @date 2023-03-21 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int minScore(int n, vector> &roads) 16 | { 17 | int score = INT_MAX; 18 | 19 | // Build graph 20 | vector>> graph(n + 1); 21 | for (auto &road : roads) 22 | { 23 | graph[road[0]].push_back({road[1], road[2]}); 24 | graph[road[1]].push_back({road[0], road[2]}); 25 | } 26 | 27 | // Apply BFS 28 | vector visited(n + 1); 29 | queue q; 30 | 31 | q.push(1); 32 | visited[1] = true; 33 | 34 | while (!q.empty()) 35 | { 36 | int curr = q.front(); 37 | q.pop(); 38 | 39 | for (auto &road : graph[curr]) 40 | { 41 | score = min(score, road.second); 42 | if (!visited[road.first]) 43 | { 44 | visited[road.first] = true; 45 | q.push(road.first); 46 | } 47 | } 48 | } 49 | 50 | return score; 51 | } 52 | }; 53 | 54 | // Time Complexity: O(N + E) 55 | // Space Complexity: O(N + E) -------------------------------------------------------------------------------- /3. March/Day23NumberOfOperationsToMakeNetworkConnected.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day23NumberOfOperationsToMakeNetworkConnected.cpp 3 | * @author Ginny Dang 4 | * @brief 1319. Number of Operations to Make Network Connected (https://leetcode.com/problems/number-of-operations-to-make-network-connected/description/) 5 | * @version 0.1 6 | * @date 2023-03-22 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class DisjointSet 13 | { 14 | private: 15 | vector parent; 16 | vector size; 17 | 18 | public: 19 | DisjointSet(int n) 20 | { 21 | for (int i = 0; i < n; i++) 22 | parent.push_back(i); 23 | size.resize(n, 1); 24 | }; 25 | 26 | int findSet(int v) 27 | { 28 | return v == parent[v] ? v : parent[v] = findSet(parent[v]); 29 | } 30 | 31 | bool unionSets(int u, int v) 32 | { 33 | int parentU = findSet(u); 34 | int parentV = findSet(v); 35 | 36 | if (parentU == parentV) 37 | return false; 38 | 39 | if (size[parentU] > size[parentV]) 40 | swap(parentU, parentV); 41 | 42 | parent[parentU] = parentV; 43 | size[parentV] += size[parentU]; 44 | 45 | return true; 46 | } 47 | }; 48 | 49 | class Solution 50 | { 51 | public: 52 | int makeConnected(int n, vector> &connections) 53 | { 54 | DisjointSet dsu = DisjointSet(n); 55 | int good = 0; 56 | int bad = 0; 57 | 58 | for (auto &conn : connections) 59 | { 60 | int u = conn[0]; 61 | int v = conn[1]; 62 | 63 | if (dsu.unionSets(u, v)) 64 | good++; 65 | else 66 | bad++; 67 | } 68 | 69 | if (bad >= n - 1 - good) 70 | return n - 1 - good; 71 | return -1; 72 | } 73 | }; 74 | 75 | // Time Complexity: O(N + E) 76 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /3. March/Day24ReorderRoutesToMakeAllPathsLeadToTheCityZero.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day24ReorderRoutesToMakeAllPathsLeadToTheCityZero.cpp 3 | * @author Ginny Dang 4 | * @brief 1466. Reorder Routes to Make All Paths Lead to the City Zero (https://leetcode.com/problems/reorder-routes-to-make-all-paths-lead-to-the-city-zero/description/) 5 | * @version 0.1 6 | * @date 2023-03-23 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | private: 15 | static const int MAX = 50001; 16 | 17 | int dfs(int start, int numChanges, unordered_map *> &graph, unordered_map *> &outdegrees, bool (&visited)[MAX]) 18 | { 19 | visited[start] = true; 20 | 21 | for (int neighbor : *(graph[start])) 22 | { 23 | if (!visited[neighbor]) 24 | { 25 | if (outdegrees[start]->count(neighbor)) 26 | numChanges++; 27 | numChanges = dfs(neighbor, numChanges, graph, outdegrees, visited); 28 | } 29 | } 30 | 31 | return numChanges; 32 | } 33 | 34 | public: 35 | int minReorder(int n, vector> &connections) 36 | { 37 | int changes = 0; 38 | unordered_map *> outdegrees; 39 | unordered_map *> graph; 40 | bool visited[MAX] = {false}; 41 | 42 | for (auto &conn : connections) 43 | { 44 | int u = conn[0]; 45 | int v = conn[1]; 46 | 47 | if (!outdegrees.count(u)) 48 | outdegrees[u] = new unordered_set; 49 | 50 | if (!outdegrees.count(v)) 51 | outdegrees[v] = new unordered_set; 52 | 53 | outdegrees[u]->insert(v); 54 | if (!graph.count(u)) 55 | { 56 | graph[u] = new unordered_set; 57 | visited[u] = false; 58 | } 59 | 60 | graph[u]->insert(v); 61 | if (!graph.count(v)) 62 | { 63 | graph[v] = new unordered_set; 64 | visited[v] = false; 65 | } 66 | 67 | graph[v]->insert(u); 68 | } 69 | 70 | for (int i = 0; i < graph.size(); i++) 71 | if (!visited[i]) 72 | changes = dfs(0, changes, graph, outdegrees, visited); 73 | 74 | // Deallocate the memory to ensure that there are no memory leaks or null pointer errors 75 | for (auto &kv : outdegrees) 76 | delete kv.second; 77 | 78 | for (auto &kv : graph) 79 | delete kv.second; 80 | 81 | return changes; 82 | } 83 | }; 84 | 85 | // Time Complexity: O(N) 86 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /3. March/Day25CountUnreachablePairsOfNodesInAnUndirectedGraph.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day25CountUnreachablePairsOfNodesInAnUndirectedGraph.cpp 3 | * @author Ginny Dang 4 | * @brief 2316. Count Unreachable Pairs of Nodes in an Undirected Graph (https://leetcode.com/problems/count-unreachable-pairs-of-nodes-in-an-undirected-graph/description/) 5 | * @version 0.1 6 | * @date 2023-03-25 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int bfs(int start, vector> &graph, vector &visited) 16 | { 17 | int size = 0; 18 | queue q; 19 | 20 | visited[start] = true; 21 | q.push(start); 22 | 23 | while (!q.empty()) 24 | { 25 | int u = q.front(); 26 | q.pop(); 27 | size++; 28 | for (int v : graph[u]) 29 | { 30 | if (!visited[v]) 31 | { 32 | visited[v] = true; 33 | q.push(v); 34 | } 35 | } 36 | } 37 | 38 | return size; 39 | } 40 | 41 | long long count(int n, vector &sizes) 42 | { 43 | if (sizes.size() == 1) 44 | return 0; 45 | 46 | long long totalSizes = 0; 47 | long long sumSizes = 0; 48 | 49 | for (int size : sizes) 50 | { 51 | totalSizes += (long long)size * size; 52 | sumSizes += size; 53 | } 54 | 55 | return 0.5 * (sumSizes * sumSizes - totalSizes); 56 | } 57 | 58 | long long countPairs(int n, vector> &edges) 59 | { 60 | // Build graph 61 | vector> graph(n, vector()); 62 | for (auto &edge : edges) 63 | { 64 | graph[edge[0]].push_back(edge[1]); 65 | graph[edge[1]].push_back(edge[0]); 66 | } 67 | 68 | // Count the number of connected components within the graph 69 | vector visited(n, false); 70 | vector sizes; 71 | 72 | for (int i = 0; i < n; i++) 73 | if (!visited[i]) 74 | sizes.push_back(bfs(i, graph, visited)); 75 | 76 | // Find the number of pairs 77 | return count(n, sizes); 78 | } 79 | }; 80 | 81 | // Time Complexity: O(N + E) where N is the number of nodes, E is the number of edges 82 | // Space Complexity: O(N + E) where N is the number of nodes, E is the number of edges -------------------------------------------------------------------------------- /3. March/Day26LongestCycleInAGraph.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day26LongestCycleInAGraph.cpp 3 | * @author Ginny Dang 4 | * @brief 2360. Longest Cycle in a Graph (https://leetcode.com/problems/longest-cycle-in-a-graph/description/) 5 | * @version 0.1 6 | * @date 2023-03-26 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int cycleLength(int start, vector &level, vector &edges, int &prevLevel) 16 | { 17 | int length = -1; 18 | int curr = start; 19 | 20 | while (curr != -1) 21 | { 22 | if (level[curr] == 0) 23 | level[curr] = ++prevLevel; 24 | else if (level[curr] >= level[start]) 25 | { 26 | length = prevLevel - level[curr] + 1; 27 | break; 28 | } 29 | else 30 | break; 31 | 32 | curr = edges[curr]; // cur = cur->next 33 | } 34 | 35 | return length; 36 | } 37 | 38 | int longestCycle(vector &edges) 39 | { 40 | int n = edges.size(); 41 | vector level(n, 0); 42 | int result = -1; 43 | int prevLevel = 0; 44 | 45 | for (int i = 0; i < n; i++) 46 | if (level[i] == 0) 47 | result = max(result, cycleLength(i, level, edges, prevLevel)); 48 | 49 | return result; 50 | } 51 | }; 52 | 53 | // Time Complexity: O(N) 54 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /3. March/Day27MinimumPathSum.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day27MinimumPathSum.cpp 3 | * @author Ginny Dang 4 | * @brief 64. Minimum Path Sum (https://leetcode.com/problems/minimum-path-sum/description/) 5 | * @version 0.1 6 | * @date 2023-03-26 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int minPathSum(vector> &grid) 16 | { 17 | int m = grid.size(); 18 | int n = grid[0].size(); 19 | // vector> min_path_sum(m, vector(n, 0)); 20 | 21 | for (int i = 0; i < m; i++) 22 | { 23 | for (int j = 0; j < n; j++) 24 | { 25 | if (i == 0 && j == 0) 26 | grid[i][j] = grid[0][0]; 27 | else if (((i - 1 >= 0) && (i - 1 < m)) && ((j - 1 >= 0) && (j - 1 < n))) 28 | grid[i][j] = min(grid[i - 1][j], grid[i][j - 1]) + grid[i][j]; 29 | else if ((i - 1) < 0 || (i - 1) >= m) 30 | grid[i][j] = grid[i][j - 1] + grid[i][j]; 31 | else 32 | grid[i][j] = grid[i - 1][j] + grid[i][j]; 33 | } 34 | } 35 | 36 | return grid[m - 1][n - 1]; 37 | } 38 | }; 39 | 40 | // Time Complexity: O(MN) 41 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /3. March/Day28MinimumCostForTickets.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day28MinimumCostForTickets.cpp 3 | * @author Ginny Dang 4 | * @brief 983. Minimum Cost For Tickets (https://leetcode.com/problems/minimum-cost-for-tickets/description/) 5 | * @version 0.1 6 | * @date 2023-03-27 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int mincostTickets(vector &days, vector &costs) 16 | { 17 | int n = days.size(); 18 | vector memo(n, -1); 19 | int durations[] = {1, 7, 30}; 20 | 21 | return calcCost(n, 0, days, costs, memo, durations); 22 | } 23 | 24 | int calcCost(int &n, int i, vector &days, vector &costs, vector &memo, int (&durations)[3]) 25 | { 26 | if (i >= n) 27 | return 0; 28 | if (memo[i] != -1) 29 | return memo[i]; 30 | 31 | int ans = INT_MAX; 32 | int j = i; 33 | for (int k = 0; k < 3; k++) 34 | { 35 | while (j < n && days[j] < days[i] + durations[k]) 36 | j++; 37 | ans = min(ans, calcCost(n, j, days, costs, memo, durations) + costs[k]); 38 | } 39 | 40 | memo[i] = ans; 41 | return ans; 42 | } 43 | }; 44 | 45 | // Time Complexity: O(N) where N is the number of unique days 46 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /3. March/Day29ReducingDishes.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day29ReducingDishes.cpp 3 | * @author Ginny Dang 4 | * @brief 1402. Reducing Dishes (https://leetcode.com/problems/reducing-dishes/description/) 5 | * @version 0.1 6 | * @date 2023-03-29 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int maxSatisfaction(vector &satisfaction) 16 | { 17 | int n = satisfaction.size(); 18 | 19 | sort(satisfaction.begin(), satisfaction.end()); 20 | 21 | int curr = 0; 22 | int currSumA = 0; 23 | for (int i = 0; i < n; i++) 24 | { 25 | curr += satisfaction[i] * (i + 1); 26 | currSumA += satisfaction[i]; 27 | } 28 | 29 | int result = curr; 30 | for (int i = 0; i < n - 1; i++) 31 | { 32 | int next = curr - currSumA; 33 | result = max(result, next); 34 | curr = next; 35 | currSumA -= satisfaction[i]; 36 | } 37 | 38 | result = max(result, 0); 39 | return result; 40 | } 41 | }; 42 | 43 | // Time Complexity: O(N) 44 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /3. March/Day2StringCompression.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day2StringCompression.cpp 3 | * @author Ginny Dang 4 | * @brief 443. String Compression (https://leetcode.com/problems/string-compression/description/) 5 | * @version 0.1 6 | * @date 2023-03-02 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int compress(vector &chars) 16 | { 17 | if (chars.size() == 1) 18 | return 1; 19 | 20 | int groupStart = 0; 21 | int nextChar = 0; 22 | while (groupStart < chars.size()) 23 | { 24 | // Determine the current group and its length 25 | int groupEnd = groupStart; 26 | while (groupEnd + 1 < chars.size() && chars[groupStart] == chars[groupEnd + 1]) 27 | groupEnd++; 28 | int groupLength = groupEnd - groupStart + 1; 29 | string groupLengthStr = to_string(groupLength); 30 | 31 | // Compress the current group and add it to the chars array 32 | chars[nextChar++] = chars[groupStart]; 33 | if (groupLength != 1) 34 | for (int i = 0; i < groupLengthStr.size(); i++) 35 | chars[nextChar++] = groupLengthStr[i]; 36 | 37 | // Update the start and end of the new group 38 | groupStart = groupEnd + 1; 39 | } 40 | 41 | while (nextChar < chars.size()) 42 | chars.pop_back(); 43 | 44 | return chars.size(); 45 | } 46 | }; 47 | 48 | // Time Complexity: O(N) 49 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /3. March/Day30ScrambleString.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day30ScrambleString.cpp 3 | * @author Ginny Dang 4 | * @brief 87. Scramble String (https://leetcode.com/problems/scramble-string/description/) 5 | * @version 0.1 6 | * @date 2023-03-30 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | bool isScramble(string s1, string s2) 16 | { 17 | int n = s1.size(); 18 | vector dp(n + 1, vector(n, vector(n))); 19 | 20 | for (int i = 0; i < n; i++) 21 | for (int j = 0; j < n; j++) 22 | dp[1][i][j] = s1[i] == s2[j]; 23 | 24 | for (int length = 2; length < n + 1; length++) 25 | for (int i = 0; i < n + 1 - length; i++) 26 | for (int j = 0; j < n + 1 - length; j++) 27 | for (int newLength = 1; newLength < length; newLength++) 28 | if ((dp[newLength][i][j] && dp[length - newLength][i + newLength][j + newLength]) || (dp[newLength][i][j + length - newLength] && dp[length - newLength][i + newLength][j])) 29 | dp[length][i][j] = true; 30 | 31 | return dp[n][0][0]; 32 | } 33 | }; 34 | 35 | // Time complexity: O(n^4) 36 | // Space complexity: O(n^3) -------------------------------------------------------------------------------- /3. March/Day31NumberOfWaysOfCuttingAPizza.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day31NumberOfWaysOfCuttingAPizza.cpp 3 | * @author Ginny Dang 4 | * @brief 1444. Number of Ways of Cutting a Pizza (https://leetcode.com/problems/number-of-ways-of-cutting-a-pizza/description/) 5 | * @version 0.1 6 | * @date 2023-03-31 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int ways(vector &pizza, int k) 16 | { 17 | const int mod = 1e9 + 7; 18 | int rows = pizza.size(); 19 | int cols = pizza[0].size(); 20 | vector apples(rows + 1, vector(cols + 1)); 21 | vector f(rows, vector(cols)); 22 | 23 | for (int row = rows - 1; row > -1; row--) 24 | { 25 | for (int col = cols - 1; col > -1; col--) 26 | { 27 | apples[row][col] = (pizza[row][col] == 'A') + apples[row + 1][col] + apples[row][col + 1] - apples[row + 1][col + 1]; 28 | f[row][col] = (apples[row][col] > 0); 29 | } 30 | } 31 | 32 | for (int remain = 1; remain < k; remain++) 33 | { 34 | vector g(rows, vector(cols)); 35 | 36 | for (int row = 0; row < rows; row++) 37 | { 38 | for (int col = 0; col < cols; col++) 39 | { 40 | for (int nextRow = row + 1; nextRow < rows; nextRow++) 41 | if (apples[row][col] - apples[nextRow][col] > 0) 42 | (g[row][col] += f[nextRow][col]) %= mod; // prevent overflow 43 | 44 | for (int nextCol = col + 1; nextCol < cols; nextCol++) 45 | if (apples[row][col] - apples[row][nextCol] > 0) 46 | (g[row][col] += f[row][nextCol]) %= mod; // prevent overflow 47 | } 48 | } 49 | 50 | f = g; 51 | } 52 | 53 | return f[0][0]; 54 | } 55 | }; 56 | 57 | // Time complexity: O(k * m * n * (m + n)) where m is the number of rows and n is the number of columns 58 | // Space complexity: O(m * n) where m is the number of rows and n is the number of columns -------------------------------------------------------------------------------- /3. March/Day3FindTheIndexOfTheFirstOccurrenceInAString.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day3FindTheIndexOfTheFirstOccurrenceInAString.cpp 3 | * @author Ginny Dang 4 | * @brief 28. Find the Index of the First Occurrence in a String (https://leetcode.com/problems/find-the-index-of-the-first-occurrence-in-a-string/description/) 5 | * @version 0.1 6 | * @date 2023-03-02 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int strStr(string haystack, string needle) 16 | { 17 | int m = haystack.length(); 18 | int n = needle.length(); 19 | 20 | for (int i = 0; i < m; i++) 21 | { 22 | for (int j = 0; j < n; j++) 23 | { 24 | if ((i + j >= m) || (haystack[i + j] != needle[j])) 25 | break; 26 | if (j + 1 == n) 27 | return i; 28 | } 29 | } 30 | 31 | return -1; 32 | } 33 | }; 34 | 35 | // Time Complexity: O(M*N) 36 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /3. March/Day4CountSubarraysWithFixedBounds.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day4CountSubarraysWithFixedBounds.cpp 3 | * @author Ginny Dang 4 | * @brief 2444. Count Subarrays With Fixed Bounds (https://leetcode.com/problems/count-subarrays-with-fixed-bounds/description/) 5 | * @version 0.1 6 | * @date 2023-03-03 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | long long countSubarrays(vector &nums, int minK, int maxK) 16 | { 17 | long long count = 0; 18 | int lastMinK = -1; 19 | int lastMaxK = -1; 20 | int lastOutOfRange = -1; 21 | 22 | for (int end = 0; end < nums.size(); end++) 23 | { 24 | if (nums[end] == minK) 25 | lastMinK = end; 26 | if (nums[end] == maxK) 27 | lastMaxK = end; 28 | if (nums[end] > maxK || nums[end] < minK) 29 | lastOutOfRange = end; 30 | 31 | count += max(min(lastMinK, lastMaxK) - lastOutOfRange, 0); 32 | } 33 | 34 | return count; 35 | } 36 | }; 37 | 38 | // Time Complexity: O(N) 39 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /3. March/Day5JumpGameIV.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day5JumpGameIV.cpp 3 | * @author Ginny Dang 4 | * @brief 1345. Jump Game IV (https://leetcode.com/problems/jump-game-iv/description/) 5 | * @version 0.1 6 | * @date 2023-03-05 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * @brief New thing I've learned from this challenge 14 | * Why "imaginary" graph? 15 | * - If we had an actual graph, for each node, we will store all of its connections of 3 types. However: 16 | * - Types 1 and 2 are trivial to determine -> No need to store in the graph 17 | * - Type 3 connections are too costly to store 18 | * => There's no actual graph built here. 19 | * - Instead, they key player here is the queue. Each node only needs to present in the queue once. 20 | */ 21 | 22 | class Solution 23 | { 24 | public: 25 | int minJumps(vector &arr) 26 | { 27 | int n = arr.size(); 28 | if (n <= 1) 29 | return 0; 30 | 31 | // Build value-positions map 32 | unordered_map> valuePosMap; 33 | for (int i = 0; i < n; i++) 34 | valuePosMap[arr[i]].push_back(i); 35 | 36 | // BFS on the "imaginary" graph to find the shortest path from 0 -> n - 1 37 | queue q; 38 | vector stepsToReach(n, -1); 39 | 40 | q.push(0); 41 | stepsToReach[0] = 0; 42 | 43 | while (!q.empty()) 44 | { 45 | int u = q.front(); 46 | q.pop(); 47 | 48 | // Handle type 1 connections 49 | if (u - 1 >= 0 && stepsToReach[u - 1] == -1) 50 | { 51 | q.push(u - 1); 52 | stepsToReach[u - 1] = stepsToReach[u] + 1; 53 | } 54 | 55 | // Handle type 2 connections 56 | if (u + 1 < n && stepsToReach[u + 1] == -1) 57 | { 58 | q.push(u + 1); 59 | stepsToReach[u + 1] = stepsToReach[u] + 1; 60 | } 61 | 62 | // Handle type 3 connections 63 | vector valuePos = valuePosMap[arr[u]]; 64 | while (!valuePos.empty()) 65 | { 66 | int lastPos = valuePos[valuePos.size() - 1]; 67 | valuePos.pop_back(); 68 | if (lastPos != u && stepsToReach[lastPos] == -1) 69 | { 70 | q.push(lastPos); 71 | stepsToReach[lastPos] = stepsToReach[u] + 1; 72 | } 73 | } 74 | valuePosMap[arr[u]].clear(); 75 | } 76 | 77 | return stepsToReach[n - 1]; 78 | } 79 | }; 80 | 81 | // Time Complexity: O(N) 82 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /3. March/Day6KthMissingPositiveNumber.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day6KthMissingPositiveNumber.cpp 3 | * @author Ginny Dang 4 | * @brief 1539. Kth Missing Positive Number (https://leetcode.com/problems/kth-missing-positive-number/description/) 5 | * @version 0.1 6 | * @date 2023-03-05 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int findKthPositive(vector &arr, int k) 16 | { 17 | int n = arr.size(); 18 | if (k < arr[0]) 19 | return k; 20 | 21 | k -= arr[0] - 1; 22 | 23 | for (int i = 0; i < n - 1; i++) 24 | { 25 | int missingNums = arr[i + 1] - arr[i] - 1; // The number of missing positive integers between arr[i] and arr[i + 1] 26 | if (k <= missingNums) 27 | return arr[i] + k; 28 | else 29 | k -= missingNums; 30 | } 31 | 32 | return arr[n - 1] + k; 33 | } 34 | }; 35 | 36 | // Time Complexity: O(N) 37 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /3. March/Day7MinimumTimeToCompleteTrips.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day7MinimumTimeToCompleteTrips.cpp 3 | * @author Ginny Dang 4 | * @brief 2187. Minimum Time to Complete Trips (https://leetcode.com/problems/minimum-time-to-complete-trips/description/) 5 | * @version 0.1 6 | * @date 2023-03-06 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | long long minimumTime(vector &time, int totalTrips) 16 | { 17 | long long left = *min_element(time.begin(), time.end()); 18 | long long right = (long long)*max_element(time.begin(), time.end()) * totalTrips; 19 | long long minTime = LONG_LONG_MAX; 20 | 21 | // find the smallest amount of time in which all buses can complete a number of trips >= totalTrips in the sorted range [left, right] 22 | // numTrips(l) <= ... <= numTrips(i) <= numTrips(i + 1) <= ... <= numTrips(right) 23 | while (left <= right) 24 | { 25 | long long mid = left + (right - left) / 2; 26 | long long trips = 0; 27 | for (int t : time) 28 | trips += mid / t; 29 | if (trips >= totalTrips) 30 | { 31 | right = mid - 1; 32 | minTime = mid; 33 | } 34 | else 35 | left = mid + 1; 36 | } 37 | 38 | return minTime; 39 | } 40 | }; 41 | 42 | // Time Complexity: O(NlogN) 43 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /3. March/Day8KokoEatingBananas.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day8KokoEatingBananas.cpp 3 | * @author Ginny Dang 4 | * @brief 875. Koko Eating Bananas (https://leetcode.com/problems/koko-eating-bananas/description/) 5 | * @version 0.1 6 | * @date 2023-03-07 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | bool canEatInTime(vector &piles, int k, int h) 16 | { 17 | long long hours = 0; 18 | 19 | for (int pile : piles) 20 | { 21 | long long div = (long long)pile / k; 22 | hours += div; 23 | if (pile % k != 0) 24 | hours += 1; 25 | } 26 | 27 | return hours <= h; 28 | } 29 | 30 | int minEatingSpeed(vector &piles, int h) 31 | { 32 | int left = 1; 33 | int right = *max_element(piles.begin(), piles.end()); 34 | 35 | while (left <= right) 36 | { 37 | int mid = left + (right - left) / 2; 38 | if (canEatInTime(piles, mid, h)) 39 | right = mid - 1; 40 | else 41 | left = mid + 1; 42 | } 43 | 44 | return left; 45 | } 46 | }; 47 | 48 | // Time Complexity: O(NlogM). N is the number of piles and M is the range of K (left to right) 49 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /3. March/Day9LinkedListCycleII.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day9LinkedListCycleII.cpp 3 | * @author Ginny Dang 4 | * @brief 142. Linked List Cycle II (https://leetcode.com/problems/linked-list-cycle-ii/description/) 5 | * @version 0.1 6 | * @date 2023-03-08 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * Definition for singly-linked list. 14 | * struct ListNode { 15 | * int val; 16 | * ListNode *next; 17 | * ListNode(int x) : val(x), next(NULL) {} 18 | * }; 19 | */ 20 | class Solution 21 | { 22 | public: 23 | ListNode *detectCycle(ListNode *head) 24 | { 25 | if (!head) 26 | return NULL; 27 | 28 | ListNode *fast = head; 29 | ListNode *slow = head; 30 | ListNode *meet = NULL; 31 | while (fast->next && fast->next->next && slow->next) 32 | { 33 | fast = fast->next->next; 34 | slow = slow->next; 35 | if (fast == slow) 36 | { 37 | meet = slow; 38 | break; 39 | } 40 | } 41 | 42 | if (!meet) 43 | return NULL; 44 | 45 | ListNode *start = head; 46 | while (start != meet) 47 | { 48 | start = start->next; 49 | meet = meet->next; 50 | } 51 | return start; 52 | } 53 | }; 54 | 55 | // Time Complexity: O(N) 56 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /4. April/Day10ValidParentheses.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day10ValidParentheses.cpp 3 | * @author Ginny Dang 4 | * @brief 20. Valid Parentheses (https://leetcode.com/problems/valid-parentheses/description/) 5 | * @version 0.1 6 | * @date 2023-04-09 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | private: 15 | char opening(char c) 16 | { 17 | if (c == ')') 18 | return '('; 19 | if (c == ']') 20 | return '['; 21 | if (c == '}') 22 | return '{'; 23 | return '\n'; // Default returned value for the compiler to run, with the given constraints, this value will never be returned 24 | } 25 | 26 | public: 27 | bool isValid(string s) 28 | { 29 | stack S; 30 | for (int i = 0; i < s.length(); i++) 31 | { 32 | if (s[i] == '(' || s[i] == '{' || s[i] == '[') 33 | S.push(s[i]); 34 | else 35 | { 36 | if (S.empty()) 37 | return false; 38 | char c = S.top(); 39 | if (c != opening(s[i])) 40 | return false; 41 | S.pop(); 42 | } 43 | } 44 | return S.empty(); 45 | } 46 | }; 47 | 48 | // Time Complexity: O(N) 49 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /4. April/Day11RemovingStarsFromAString.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day11RemovingStarsFromAString.cpp 3 | * @author Ginny Dang 4 | * @brief 2390. Removing Stars From a String (https://leetcode.com/problems/removing-stars-from-a-string/description/) 5 | * @version 0.1 6 | * @date 2023-04-10 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | string removeStars(string s) 16 | { 17 | vector stack; 18 | 19 | for (char c : s) 20 | { 21 | if (c == '*') 22 | { 23 | if (!stack.empty()) 24 | stack.pop_back(); 25 | } 26 | else 27 | stack.push_back(c); 28 | } 29 | 30 | return string(stack.begin(), stack.end()); 31 | } 32 | }; 33 | 34 | // Time Complexity: O(N) 35 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /4. April/Day12SimplifyPath.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day12SimplifyPath.cpp 3 | * @author Ginny Dang 4 | * @brief 71. Simplify Path (https://leetcode.com/problems/simplify-path/description/) 5 | * @version 0.1 6 | * @date 2023-04-11 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | private: 15 | vector split(const string &s, char delimiter) 16 | { 17 | vector tokens; 18 | string token; 19 | istringstream tokenStream(s); 20 | 21 | while (getline(tokenStream, token, delimiter)) 22 | tokens.push_back(token); 23 | 24 | return tokens; 25 | } 26 | 27 | public: 28 | string simplifyPath(string path) 29 | { 30 | vector splittedPaths = split(path, '/'); 31 | vector levels; 32 | string canonicalPath = "/"; 33 | 34 | for (auto &path : splittedPaths) 35 | { 36 | cout << path << "\n"; 37 | if (path == "" || path == ".") 38 | continue; 39 | else if (path == "..") 40 | { 41 | if (levels.size() != 0) 42 | levels.pop_back(); 43 | } 44 | else 45 | levels.push_back(path); 46 | } 47 | 48 | for (int i = 0; i < levels.size(); i++) 49 | { 50 | canonicalPath += levels[i]; 51 | if (i != levels.size() - 1) 52 | canonicalPath += "/"; 53 | } 54 | 55 | return canonicalPath; 56 | } 57 | }; 58 | 59 | // Time Complexity: O(N) 60 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /4. April/Day13ValidateStackSequences.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day13ValidateStackSequences.cpp 3 | * @author Ginny Dang 4 | * @brief 946. Validate Stack Sequences (https://leetcode.com/problems/validate-stack-sequences/description/) 5 | * @version 0.1 6 | * @date 2023-04-12 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | bool validateStackSequences(vector &pushed, vector &popped) 16 | { 17 | vector stack; 18 | int front = 0; 19 | 20 | for (int num : pushed) 21 | { 22 | stack.push_back(num); 23 | 24 | while (!stack.empty() && stack[stack.size() - 1] == popped[front]) 25 | { 26 | stack.pop_back(); 27 | front++; 28 | } 29 | } 30 | 31 | return stack.empty(); 32 | } 33 | }; 34 | 35 | // Time Complexity: O(N) 36 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /4. April/Day14LongestPalindromicSubsequence.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day14LongestPalindromicSubsequence.cpp 3 | * @author Ginny Dang 4 | * @brief 516. Longest Palindromic Subsequence (https://leetcode.com/problems/longest-palindromic-subsequence/description/) 5 | * @version 0.1 6 | * @date 2023-04-13 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | private: 15 | int topDownDp(string &s, int left, int right, vector> &lps) 16 | { 17 | if (lps[left][right] != 0) 18 | return lps[left][right]; 19 | 20 | if (left == right) 21 | lps[left][right] = 1; 22 | else if (right - left == 1) 23 | { 24 | if (s[left] == s[right]) 25 | lps[left][right] = 2; 26 | else 27 | lps[left][right] = 1; 28 | } 29 | else if (left < right) 30 | { 31 | if (s[left] != s[right]) 32 | lps[left][right] = max(topDownDp(s, left + 1, right, lps), topDownDp(s, left, right - 1, lps)); 33 | else 34 | lps[left][right] = 2 + topDownDp(s, left + 1, right - 1, lps); 35 | } 36 | 37 | return lps[left][right]; 38 | } 39 | 40 | public: 41 | int longestPalindromeSubseq(string s) 42 | { 43 | int n = s.length(); 44 | vector> lps(n, vector(n)); 45 | return topDownDp(s, 0, n - 1, lps); 46 | } 47 | }; 48 | 49 | // Time Complexity: O(n^2) 50 | // Space Complexity: O(n^2) -------------------------------------------------------------------------------- /4. April/Day15MaximumValueOfKCoinsFromPiles.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day15MaximumValueOfKCoinsFromPiles.cpp 3 | * @author Ginny Dang 4 | * @brief 2218. Maximum Value of K Coins From Piles (https://leetcode.com/problems/maximum-value-of-k-coins-from-piles/description/) 5 | * @version 0.1 6 | * @date 2023-04-14 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int maxValueOfCoins(vector> &piles, int k) 16 | { 17 | int n = piles.size(); 18 | vector> dp(n + 1, vector(k + 1)); 19 | 20 | for (int i = 1; i <= n; i++) 21 | { 22 | for (int coins = 0; coins <= k; coins++) 23 | { 24 | int currSum = 0; 25 | for (int currCoins = 0; currCoins <= min((int)piles[i - 1].size(), coins); currCoins++) 26 | { 27 | if (currCoins > 0) 28 | currSum += piles[i - 1][currCoins - 1]; 29 | dp[i][coins] = max(dp[i][coins], dp[i - 1][coins - currCoins] + currSum); 30 | } 31 | } 32 | } 33 | 34 | return dp[n][k]; 35 | } 36 | }; 37 | 38 | // Time Complexity: O(k * s) 39 | // Space Complexity: O(n * k) -------------------------------------------------------------------------------- /4. April/Day16NumberOfWaysToFormATargetStringGivenADictionary.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day16NumberOfWaysToFormATargetStringGivenADictionary.cpp 3 | * @author Ginny Dang 4 | * @brief 1639. Number of Ways to Form a Target String Given a Dictionary (https://leetcode.com/problems/number-of-ways-to-form-a-target-string-given-a-dictionary/description/) 5 | * @version 0.1 6 | * @date 2023-04-16 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int numWays(vector &words, string target) 16 | { 17 | const int alphabet = 26; 18 | const int mod = 1e9 + 7; 19 | 20 | int m = target.size(); 21 | int k = words[0].size(); 22 | 23 | vector> count(alphabet, vector(k)); 24 | for (int i = 0; i < k; i++) 25 | for (const string &word : words) 26 | count[word[i] - 'a'][i]++; 27 | 28 | vector> dp(m + 1, vector(k + 1)); 29 | dp[0][0] = 1; 30 | for (int i = 0; i <= m; i++) 31 | { 32 | for (int j = 0; j < k; j++) 33 | { 34 | if (i < m) 35 | { 36 | dp[i + 1][j + 1] += count[target[i] - 'a'][j] * dp[i][j]; 37 | dp[i + 1][j + 1] %= mod; 38 | } 39 | dp[i][j + 1] += dp[i][j]; 40 | dp[i][j + 1] %= mod; 41 | } 42 | } 43 | 44 | return dp[m][k]; 45 | } 46 | }; 47 | 48 | // Time Complexity: O(n * k + m * k) 49 | // Space Complexity: O(m * k) or O(26k + m * k) to be exact -------------------------------------------------------------------------------- /4. April/Day17KidsWithTheGreatestNumberOfCandies.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day17KidsWithTheGreatestNumberOfCandies.cpp 3 | * @author Ginny Dang 4 | * @brief 1431. Kids With the Greatest Number of Candies (https://leetcode.com/problems/kids-with-the-greatest-number-of-candies/description/) 5 | * @version 0.1 6 | * @date 2023-04-16 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | vector kidsWithCandies(vector &candies, int extraCandies) 16 | { 17 | int n = candies.size(); 18 | vector result(n, false); 19 | 20 | int maxCandies = *max_element(candies.begin(), candies.end()); 21 | for (int i = 0; i < n; i++) 22 | if (candies[i] + extraCandies >= maxCandies) 23 | result[i] = true; 24 | 25 | return result; 26 | } 27 | }; 28 | 29 | // Time Complexity: O(N) 30 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /4. April/Day18MergeStringsAlternately.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day18MergeStringsAlternately.cpp 3 | * @author Ginny Dang 4 | * @brief 1768. Merge Strings Alternately (https://leetcode.com/problems/merge-strings-alternately/description/) 5 | * @version 0.1 6 | * @date 2023-04-17 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | string mergeAlternately(string word1, string word2) 16 | { 17 | string result = ""; 18 | int n = min(word1.length(), word2.length()); 19 | int ptr = 0; 20 | 21 | while (ptr < n) 22 | { 23 | result += word1[ptr]; 24 | result += word2[ptr]; 25 | ptr++; 26 | } 27 | 28 | if (ptr <= word1.length() - 1) 29 | result += word1.substr(ptr); 30 | 31 | if (ptr <= word2.length() - 1) 32 | result += word2.substr(ptr); 33 | 34 | return result; 35 | } 36 | }; 37 | 38 | // Time Complexity: O(M + N) where M and N are the lengths of 2 words 39 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /4. April/Day19LongestZigZagPathInABinaryTree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day19LongestZigZagPathInABinaryTree.cpp 3 | * @author Ginny Dang 4 | * @brief 1372. Longest ZigZag Path in a Binary Tree (https://leetcode.com/problems/longest-zigzag-path-in-a-binary-tree/description/) 5 | * @version 0.1 6 | * @date 2023-04-18 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * Definition for a binary tree node. 14 | * struct TreeNode { 15 | * int val; 16 | * TreeNode *left; 17 | * TreeNode *right; 18 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 19 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 20 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 21 | * }; 22 | */ 23 | class Solution 24 | { 25 | private: 26 | int zigzagLength = 0; 27 | 28 | void dfs(TreeNode *node, bool turnLeft, int steps) 29 | { 30 | if (node == nullptr) 31 | return; 32 | 33 | zigzagLength = max(zigzagLength, steps); 34 | 35 | if (turnLeft) 36 | { 37 | dfs(node->left, false, steps + 1); 38 | dfs(node->right, true, 1); 39 | } 40 | else 41 | { 42 | dfs(node->left, false, 1); 43 | dfs(node->right, true, steps + 1); 44 | } 45 | } 46 | 47 | public: 48 | int longestZigZag(TreeNode *root) 49 | { 50 | dfs(root, false, 0); 51 | dfs(root, true, 0); 52 | 53 | return zigzagLength; 54 | } 55 | }; 56 | 57 | // Time Complexity: O(N) 58 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /4. April/Day1BinarySearch.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day1BinarySearch.cpp 3 | * @author Ginny Dang 4 | * @brief 704. Binary Search (https://leetcode.com/problems/binary-search/description/) 5 | * @version 0.1 6 | * @date 2023-03-31 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int search(vector &nums, int target) 16 | { 17 | int left = 0; 18 | int right = nums.size() - 1; 19 | 20 | while (left <= right) 21 | { 22 | int mid = left + (right - left) / 2; 23 | 24 | if (nums[mid] == target) 25 | return mid; 26 | else if (nums[mid] > target) 27 | right = mid - 1; 28 | else 29 | left = mid + 1; 30 | } 31 | 32 | return -1; 33 | } 34 | }; 35 | 36 | // Time Complexity: O(logN) 37 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /4. April/Day20MaximumWidthOfBinaryTree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day20MaximumWidthOfBinaryTree.cpp 3 | * @author Ginny Dang 4 | * @brief 662. Maximum Width of Binary Tree (https://leetcode.com/problems/maximum-width-of-binary-tree/description/) 5 | * @version 0.1 6 | * @date 2023-04-20 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int widthOfBinaryTree(TreeNode *root) 16 | { 17 | if (root == nullptr) 18 | return 0; 19 | 20 | int maxWidth = 0; 21 | list> queue; 22 | queue.push_back({root, 0}); 23 | 24 | while (!queue.empty()) 25 | { 26 | pair head = queue.front(); 27 | int currLevelSize = queue.size(); 28 | pair curr; 29 | 30 | for (int i = 0; i < currLevelSize; i++) 31 | { 32 | curr = queue.front(); 33 | queue.pop_front(); 34 | TreeNode *node = curr.first; 35 | 36 | if (node->left != nullptr) 37 | queue.push_back({node->left, static_cast(2LL * curr.second)}); 38 | 39 | if (node->right != nullptr) 40 | queue.push_back({node->right, static_cast(2LL * curr.second + 1)}); 41 | } 42 | 43 | maxWidth = max(maxWidth, static_cast(curr.second - head.second + 1LL)); 44 | } 45 | 46 | return maxWidth; 47 | } 48 | }; 49 | 50 | // Time Complexity: O(N) 51 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /4. April/Day21ProfitableSchemes.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day21ProfitableSchemes.cpp 3 | * @author Ginny Dang 4 | * @brief 879. Profitable Schemes (https://leetcode.com/problems/profitable-schemes/description/) 5 | * @version 0.1 6 | * @date 2023-04-20 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | private: 15 | int mod = 1e9 + 7; 16 | int memo[101][101][101]; 17 | 18 | int find(int pos, int count, int profit, int n, int minProfit, vector &group, vector &profits) 19 | { 20 | if (pos == group.size()) 21 | return profit >= minProfit; 22 | 23 | if (memo[pos][count][profit] != -1) 24 | return memo[pos][count][profit]; 25 | 26 | int numWays = find(pos + 1, count, profit, n, minProfit, group, profits); 27 | if (count + group[pos] <= n) 28 | numWays += find(pos + 1, count + group[pos], min(minProfit, profit + profits[pos]), n, minProfit, group, profits); 29 | 30 | return memo[pos][count][profit] = numWays % mod; 31 | } 32 | 33 | public: 34 | int profitableSchemes(int n, int minProfit, vector &group, vector &profit) 35 | { 36 | memset(memo, -1, sizeof(memo)); 37 | return find(0, 0, 0, n, minProfit, group, profit); 38 | } 39 | }; 40 | 41 | // Time Complexity: O(N * M * K) 42 | // Space Complexity: O(N * M * K) -------------------------------------------------------------------------------- /4. April/Day22MinimumInsertionStepsToMakeAStringPalindrome.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day22MinimumInsertionStepsToMakeAStringPalindrome.cpp 3 | * @author Ginny Dang 4 | * @brief 1312. Minimum Insertion Steps to Make a String Palindrome (https://leetcode.com/problems/minimum-insertion-steps-to-make-a-string-palindrome/description/) 5 | * @version 0.1 6 | * @date 2023-04-22 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | private: 15 | int lcs(string &s1, string &s2, int m, int n, vector> &memo) 16 | { 17 | if (m == 0 || n == 0) 18 | return 0; 19 | 20 | if (memo[m][n] != -1) 21 | return memo[m][n]; 22 | 23 | if (s1[m - 1] == s2[n - 1]) 24 | return memo[m][n] = 1 + lcs(s1, s2, m - 1, n - 1, memo); 25 | 26 | return memo[m][n] = max(lcs(s1, s2, m - 1, n, memo), lcs(s1, s2, m, n - 1, memo)); 27 | } 28 | 29 | public: 30 | int minInsertions(string s) 31 | { 32 | int n = s.length(); 33 | string reversedS = s; 34 | reverse(reversedS.begin(), reversedS.end()); 35 | vector> memo(n + 1, vector(n + 1)); 36 | 37 | for (int i = 0; i <= n; i++) 38 | for (int j = 0; j <= n; j++) 39 | memo[i][j] = -1; 40 | 41 | return n - lcs(s, reversedS, n, n, memo); 42 | } 43 | }; 44 | 45 | // Time Complexity: O(N^2) 46 | // Space Complexity: O(N^2) -------------------------------------------------------------------------------- /4. April/Day23RestoreTheArray.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day23RestoreTheArray.cpp 3 | * @author Ginny Dang 4 | * @brief 1416. Restore The Array (https://leetcode.com/problems/restore-the-array/description/) 5 | * @version 0.1 6 | * @date 2023-04-23 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /** 13 | * @brief Note: 14 | * - I was not able to come up with the solution to this problem. 15 | * - I refered to this post https://leetcode.com/problems/restore-the-array/solutions/585552/java-c-dfs-memoization-clean-code/?orderBy=most_votes 16 | */ 17 | 18 | class Solution 19 | { 20 | private: 21 | int mod = 1e9 + 7; 22 | int dfs(const string &s, long k, int i, vector &dp) 23 | { 24 | if (i == s.size()) 25 | return 1; 26 | if (s[i] == '0') 27 | return 0; 28 | if (dp[i] != -1) 29 | return dp[i]; 30 | int ans = 0; 31 | long num = 0; 32 | 33 | for (int j = i; j < s.size(); j++) 34 | { 35 | num = num * 10 + s[j] - '0'; 36 | if (num > k) 37 | break; 38 | ans += dfs(s, k, j + 1, dp); 39 | ans %= mod; 40 | } 41 | return dp[i] = ans; 42 | } 43 | 44 | public: 45 | int numberOfArrays(string s, int k) 46 | { 47 | vector dp(s.size(), -1); 48 | return dfs(s, k, 0, dp); 49 | } 50 | }; 51 | 52 | // Time Complexity: O(n * log10(k)) 53 | // Space Complexity: O(n) -------------------------------------------------------------------------------- /4. April/Day24LastStoneWeight.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day24LastStoneWeight.cpp 3 | * @author Ginny Dang 4 | * @brief 1046. Last Stone Weight (https://leetcode.com/problems/last-stone-weight/description/) 5 | * @version 0.1 6 | * @date 2023-04-23 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int lastStoneWeight(vector &stones) 16 | { 17 | priority_queue, less> hq; 18 | 19 | for (int stone : stones) 20 | hq.push(stone); 21 | 22 | while (hq.size() != 1) 23 | { 24 | int top0 = hq.top(); 25 | hq.pop(); 26 | int top1 = hq.top(); 27 | int newTop = top0 - top1; 28 | hq.pop(); 29 | hq.push(newTop); 30 | } 31 | 32 | return hq.top(); 33 | } 34 | }; 35 | 36 | // Time Complexity: O(N) 37 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /4. April/Day25SmallestNumberInInfiniteSet.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day25SmallestNumberInInfiniteSet.cpp 3 | * @author Ginny Dang 4 | * @brief 2336. Smallest Number in Infinite Set (https://leetcode.com/problems/smallest-number-in-infinite-set/description/) 5 | * @version 0.1 6 | * @date 2023-04-24 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class SmallestInfiniteSet 13 | { 14 | private: 15 | unordered_set isPresent; 16 | priority_queue, greater> addedInts; 17 | int currInt; 18 | 19 | public: 20 | SmallestInfiniteSet() 21 | { 22 | currInt = 1; 23 | } 24 | 25 | int popSmallest() 26 | { 27 | int ans; 28 | 29 | if (!addedInts.empty()) 30 | { 31 | ans = addedInts.top(); 32 | isPresent.erase(ans); 33 | addedInts.pop(); 34 | } 35 | else 36 | { 37 | ans = currInt; 38 | currInt += 1; 39 | } 40 | 41 | return ans; 42 | } 43 | 44 | void addBack(int num) 45 | { 46 | if (currInt <= num || isPresent.find(num) != isPresent.end()) 47 | return; 48 | 49 | addedInts.push(num); 50 | isPresent.insert(num); 51 | } 52 | }; 53 | 54 | // Time Complexity: O((m+n)*logn) 55 | // Space Complexity: O(n) 56 | 57 | /** 58 | * Your SmallestInfiniteSet object will be instantiated and called as such: 59 | * SmallestInfiniteSet* obj = new SmallestInfiniteSet(); 60 | * int param_1 = obj->popSmallest(); 61 | * obj->addBack(num); 62 | */ -------------------------------------------------------------------------------- /4. April/Day26AddDigits.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day26AddDigits.cpp 3 | * @author Ginny Dang 4 | * @brief 258. Add Digits (https://leetcode.com/problems/add-digits/description/) 5 | * @version 0.1 6 | * @date 2023-04-25 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int addDigits(int num) 16 | { 17 | if (num == 0) 18 | return 0; 19 | if (num % 9 == 0) 20 | return 9; 21 | return num % 9; 22 | } 23 | }; 24 | 25 | // Time Complexity: O(1) 26 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /4. April/Day27BulbSwitcher.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day27BulbSwitcher.cpp 3 | * @author Ginny Dang 4 | * @brief 319. Bulb Switcher (https://leetcode.com/problems/bulb-switcher/description/) 5 | * @version 0.1 6 | * @date 2023-04-26 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int bulbSwitch(int n) 16 | { 17 | return sqrt(n); 18 | } 19 | }; 20 | 21 | // Time Complexity: O(1) 22 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /4. April/Day28SimilarStringGroups.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day28SimilarStringGroups.cpp 3 | * @author Ginny Dang 4 | * @brief 839. Similar String Groups (https://leetcode.com/problems/similar-string-groups/description/) 5 | * @version 0.1 6 | * @date 2023-04-28 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | private: 15 | void bfs(int node, vector> &adj, vector &visit) 16 | { 17 | queue q; 18 | 19 | q.push(node); 20 | visit[node] = true; 21 | 22 | while (!q.empty()) 23 | { 24 | node = q.front(); 25 | q.pop(); 26 | 27 | for (int neighbor : adj[node]) 28 | { 29 | if (!visit[neighbor]) 30 | { 31 | visit[neighbor] = true; 32 | q.push(neighbor); 33 | } 34 | } 35 | } 36 | } 37 | 38 | bool isSimilar(string &a, string &b) 39 | { 40 | int diff = 0; 41 | 42 | for (int i = 0; i < a.size(); i++) 43 | if (a[i] != b[i]) 44 | diff++; 45 | 46 | return diff == 0 || diff == 2; 47 | } 48 | 49 | public: 50 | int numSimilarGroups(vector &strs) 51 | { 52 | int n = strs.size(); 53 | vector> adj(n); 54 | 55 | for (int i = 0; i < n; i++) 56 | { 57 | for (int j = i + 1; j < n; j++) 58 | { 59 | if (isSimilar(strs[i], strs[j])) 60 | { 61 | adj[i].push_back(j); 62 | adj[j].push_back(i); 63 | } 64 | } 65 | } 66 | 67 | vector visit(n); 68 | int count = 0; 69 | 70 | for (int i = 0; i < n; i++) 71 | { 72 | if (!visit[i]) 73 | { 74 | bfs(i, adj, visit); 75 | count++; 76 | } 77 | } 78 | 79 | return count; 80 | } 81 | }; 82 | 83 | // Time Complexity: O(n^2 * m) 84 | // Space Complexity: O(n^2) -------------------------------------------------------------------------------- /4. April/Day29CheckingExistenceOfEdgeLengthLimitedPaths.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day29CheckingExistenceOfEdgeLengthLimitedPaths.cpp 3 | * @author Ginny Dang 4 | * @brief 1697. Checking Existence of Edge Length Limited Paths (https://leetcode.com/problems/checking-existence-of-edge-length-limited-paths/description/) 5 | * @version 0.1 6 | * @date 2023-04-29 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class DisjointSet 13 | { 14 | public: 15 | vector parent; 16 | vector rank; 17 | 18 | DisjointSet(int size) 19 | { 20 | parent = vector(size); 21 | rank = vector(size); 22 | 23 | for (int i = 0; i < size; i++) 24 | parent[i] = i; 25 | } 26 | 27 | int find(int u) 28 | { 29 | if (parent[u] != u) 30 | parent[u] = find(parent[u]); 31 | 32 | return parent[u]; 33 | } 34 | 35 | void join(int u, int v) 36 | { 37 | int parentU = find(u); 38 | int parentV = find(v); 39 | 40 | if (parentU == parentV) 41 | return; 42 | 43 | if (rank[parentU] > rank[parentV]) 44 | parent[parentV] = parentU; 45 | else if (rank[parentU] < rank[parentV]) 46 | parent[parentU] = parentV; 47 | else 48 | { 49 | parent[parentU] = parentV; 50 | rank[parentV]++; 51 | } 52 | } 53 | 54 | bool areConnected(int u, int v) 55 | { 56 | int parentU = find(u); 57 | int parentV = find(v); 58 | 59 | return parentU == parentV; 60 | } 61 | }; 62 | 63 | class Solution 64 | { 65 | private: 66 | bool static compare(vector &a, vector &b) 67 | { 68 | return a[2] < b[2]; 69 | } 70 | 71 | public: 72 | vector distanceLimitedPathsExist(int n, vector> &edgeList, vector> &queries) 73 | { 74 | DisjointSet dsu(n); 75 | int queriesCount = queries.size(); 76 | vector answer(queriesCount); 77 | vector> queriesWithIndex(queriesCount); 78 | 79 | for (int i = 0; i < queriesCount; ++i) 80 | { 81 | queriesWithIndex[i] = queries[i]; 82 | queriesWithIndex[i].push_back(i); 83 | } 84 | 85 | sort(edgeList.begin(), edgeList.end(), compare); 86 | sort(queriesWithIndex.begin(), queriesWithIndex.end(), compare); 87 | 88 | int edgesIndex = 0; 89 | for (auto &query : queriesWithIndex) 90 | { 91 | int p = query[0]; 92 | int q = query[1]; 93 | int limit = query[2]; 94 | int queryOriginalIndex = query[3]; 95 | 96 | while (edgesIndex < edgeList.size() && edgeList[edgesIndex][2] < limit) 97 | { 98 | int u = edgeList[edgesIndex][0]; 99 | int v = edgeList[edgesIndex][1]; 100 | dsu.join(u, v); 101 | edgesIndex += 1; 102 | } 103 | 104 | answer[queryOriginalIndex] = dsu.areConnected(p, q); 105 | } 106 | 107 | return answer; 108 | } 109 | }; 110 | 111 | // Time Complexity: O(n + eloge + qlogq) 112 | // Space Complexity: O(n + q) -------------------------------------------------------------------------------- /4. April/Day2SuccessfulPairsOfSpellsAndPotions.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day2SuccessfulPairsOfSpellsAndPotions.cpp 3 | * @author Ginny Dang 4 | * @brief 2300. Successful Pairs of Spells and Potions (https://leetcode.com/problems/successful-pairs-of-spells-and-potions/description/) 5 | * @version 0.1 6 | * @date 2023-04-01 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | private: 15 | int countPairs(int currSpell, vector &potions, int numPotions, long long success) 16 | { 17 | int left = 0; 18 | int right = numPotions - 1; 19 | int smallestPotionPos = -1; 20 | 21 | while (left <= right) 22 | { 23 | int mid = left + (right - left) / 2; 24 | 25 | if ((long long)currSpell * potions[mid] < success) 26 | left = mid + 1; 27 | else 28 | { 29 | if ((mid - 1 < 0) || (mid - 1 >= 0 && (long long)currSpell * potions[mid - 1] < success)) 30 | { 31 | smallestPotionPos = mid; 32 | break; 33 | } 34 | else if (mid - 1 >= 0 && (long long)currSpell * potions[mid - 1] >= success) 35 | right = mid - 1; 36 | } 37 | } 38 | 39 | return smallestPotionPos == -1 ? 0 : numPotions - smallestPotionPos; 40 | } 41 | 42 | public: 43 | vector successfulPairs(vector &spells, vector &potions, long long success) 44 | { 45 | int n = spells.size(); 46 | int m = potions.size(); 47 | vector result(n, 0); 48 | 49 | sort(potions.begin(), potions.end()); // O(MlogM) 50 | 51 | for (int i = 0; i < n; i++) 52 | { 53 | if (spells[i] >= success) 54 | result[i] = m; 55 | else 56 | result[i] = countPairs(spells[i], potions, m, success); 57 | } 58 | 59 | return result; 60 | } 61 | }; 62 | 63 | // Time Complexity: O(max(M, N)logM) 64 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /4. April/Day30RemoveMaxNumberOfEdgesToKeepGraphFullyTraversable.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day30RemoveMaxNumberOfEdgesToKeepGraphFullyTraversable.cpp 3 | * @author Ginny Dang 4 | * @brief 1579. Remove Max Number of Edges to Keep Graph Fully Traversable (https://leetcode.com/problems/remove-max-number-of-edges-to-keep-graph-fully-traversable/description/) 5 | * @version 0.1 6 | * @date 2023-04-30 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class DisjointSet 13 | { 14 | private: 15 | vector parent; 16 | vector componentSize; 17 | int components; 18 | 19 | public: 20 | DisjointSet(int n) 21 | { 22 | components = n; 23 | 24 | for (int i = 0; i <= n; i++) 25 | { 26 | parent.push_back(i); 27 | componentSize.push_back(1); 28 | } 29 | } 30 | 31 | int findParent(int x) 32 | { 33 | if (parent[x] == x) 34 | return x; 35 | 36 | return parent[x] = findParent(parent[x]); 37 | } 38 | 39 | int performUnion(int x, int y) 40 | { 41 | x = findParent(x); 42 | y = findParent(y); 43 | 44 | if (x == y) 45 | return 0; 46 | 47 | if (componentSize[x] > componentSize[y]) 48 | { 49 | componentSize[x] += componentSize[y]; 50 | parent[y] = x; 51 | } 52 | else 53 | { 54 | componentSize[y] += componentSize[x]; 55 | parent[x] = y; 56 | } 57 | 58 | components--; 59 | return 1; 60 | } 61 | 62 | bool isConnected() 63 | { 64 | return components == 1; 65 | } 66 | }; 67 | 68 | class Solution 69 | { 70 | public: 71 | int maxNumEdgesToRemove(int n, vector> &edges) 72 | { 73 | DisjointSet Alice(n); 74 | DisjointSet Bob(n); 75 | int edgesRequired = 0; 76 | 77 | for (vector &edge : edges) 78 | if (edge[0] == 3) 79 | edgesRequired += (Alice.performUnion(edge[1], edge[2]) | Bob.performUnion(edge[1], edge[2])); 80 | 81 | for (vector &edge : edges) 82 | { 83 | if (edge[0] == 1) 84 | edgesRequired += Alice.performUnion(edge[1], edge[2]); 85 | else if (edge[0] == 2) 86 | edgesRequired += Bob.performUnion(edge[1], edge[2]); 87 | } 88 | 89 | if (Alice.isConnected() && Bob.isConnected()) 90 | return edges.size() - edgesRequired; 91 | 92 | return -1; 93 | } 94 | }; 95 | 96 | // Time Complexity: O(E * alpha(N)) 97 | // Space Complexity: O(N) -------------------------------------------------------------------------------- /4. April/Day3BoatsToSavePeople.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day3BoatsToSavePeople.cpp 3 | * @author Ginny Dang 4 | * @brief 881. Boats to Save People (https://leetcode.com/problems/boats-to-save-people/description/) 5 | * @version 0.1 6 | * @date 2023-04-03 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int numRescueBoats(vector &people, int limit) 16 | { 17 | sort(people.begin(), people.end()); 18 | 19 | int numBoats = 0; 20 | int left = 0; 21 | int right = people.size() - 1; 22 | 23 | while (left <= right) 24 | { 25 | if (people[left] + people[right] <= limit) 26 | left++; 27 | right--; 28 | numBoats++; 29 | } 30 | 31 | return numBoats; 32 | } 33 | }; 34 | 35 | // Time Complexity: O(Nlog⁡N) 36 | // Space Complexity: O(log⁡N) -------------------------------------------------------------------------------- /4. April/Day4OptimalPartitionOfString.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day4OptimalPartitionOfString.cpp 3 | * @author Ginny Dang 4 | * @brief 2405. Optimal Partition of String (https://leetcode.com/problems/optimal-partition-of-string/description/) 5 | * @version 0.1 6 | * @date 2023-04-03 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int partitionString(string s) 16 | { 17 | vector lastSeen(26, -1); // stores the most recent position of each character 18 | int count = 1; // number of substrings formed so far 19 | int substringStart = 0; // the starting index of the substring currently under consideration 20 | 21 | for (int i = 0; i < s.length(); i++) 22 | { 23 | if (lastSeen[s[i] - 'a'] >= substringStart) 24 | { 25 | count++; 26 | substringStart = i; 27 | } 28 | lastSeen[s[i] - 'a'] = i; 29 | } 30 | 31 | return count; 32 | } 33 | }; 34 | 35 | // Time complexity: O(n) 36 | // Space complexity: O(1) or O(26) to be exact -------------------------------------------------------------------------------- /4. April/Day5MinimizeMaximumOfArray.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day5MinimizeMaximumOfArray.cpp 3 | * @author Ginny Dang 4 | * @brief 2439. Minimize Maximum of Array (https://leetcode.com/problems/minimize-maximum-of-array/description/) 5 | * @version 0.1 6 | * @date 2023-04-04 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | public: 15 | int minimizeArrayValue(vector &nums) 16 | { 17 | int n = nums.size(); 18 | long long ans = 0; 19 | long long prefixSum = 0; 20 | 21 | for (int i = 0; i < n; i++) 22 | { 23 | prefixSum += nums[i]; 24 | ans = max(ans, (prefixSum + i) / (i + 1)); 25 | } 26 | 27 | return ans; 28 | } 29 | }; 30 | 31 | // Time Complexity: O(n) 32 | // Space Complexity: O(1) -------------------------------------------------------------------------------- /4. April/Day6NumberOfClosedIslands.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day6NumberOfClosedIslands.cpp 3 | * @author Ginny Dang 4 | * @brief 1254. Number of Closed Islands (https://leetcode.com/problems/number-of-closed-islands/description/) 5 | * @version 0.1 6 | * @date 2023-04-05 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | private: 15 | int dr[4] = {0, 0, -1, 1}; 16 | int dc[4] = {-1, 1, 0, 0}; 17 | 18 | bool bfs(vector> &grid, int row, int col, int rows, int cols) 19 | { 20 | bool isClosed = true; 21 | queue> q; 22 | 23 | grid[row][col] = -1; 24 | q.push({row, col}); 25 | 26 | while (!q.empty()) 27 | { 28 | int curRow = q.front().first, curCol = q.front().second; 29 | q.pop(); 30 | 31 | if ((curRow == 0) || (curRow == rows - 1) || (curCol == 0) || (curCol == cols - 1)) 32 | isClosed = false; 33 | 34 | for (int i = 0; i < 4; i++) 35 | { 36 | int nextRow = curRow + dr[i], nextCol = curCol + dc[i]; 37 | if ((0 <= nextRow && nextRow < rows) && (0 <= nextCol && nextCol < cols) && grid[nextRow][nextCol] == 0) 38 | { 39 | grid[nextRow][nextCol] = -1; 40 | q.push({nextRow, nextCol}); 41 | } 42 | } 43 | } 44 | 45 | return isClosed; 46 | } 47 | 48 | public: 49 | int closedIsland(vector> &grid) 50 | { 51 | int result = 0; 52 | int m = grid.size(); 53 | int n = grid[0].size(); 54 | 55 | for (int i = 0; i < m; i++) 56 | for (int j = 0; j < n; j++) 57 | if (grid[i][j] == 0) 58 | result += bfs(grid, i, j, m, n); 59 | 60 | return result; 61 | } 62 | }; 63 | 64 | // Time Complexity: O(m*n) 65 | // Space Complexity: O(m*n) -------------------------------------------------------------------------------- /4. April/Day7NumberOfEnclaves.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day7NumberOfEnclaves.cpp 3 | * @author Ginny Dang 4 | * @brief 1020. Number of Enclaves (https://leetcode.com/problems/number-of-enclaves/description/) 5 | * @version 0.1 6 | * @date 2023-04-06 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | private: 15 | int dr[4] = {0, 0, -1, 1}; 16 | int dc[4] = {-1, 1, 0, 0}; 17 | 18 | int bfs(vector> &grid, int row, int col, int rows, int cols) 19 | { 20 | bool isClosed = true; 21 | int numCells = 0; 22 | queue> q; 23 | 24 | grid[row][col] = -1; 25 | q.push({row, col}); 26 | numCells++; 27 | 28 | while (!q.empty()) 29 | { 30 | int curRow = q.front().first, curCol = q.front().second; 31 | q.pop(); 32 | 33 | if ((curRow == 0) || (curRow == rows - 1) || (curCol == 0) || (curCol == cols - 1)) 34 | isClosed = false; 35 | 36 | for (int i = 0; i < 4; i++) 37 | { 38 | int nextRow = curRow + dr[i], nextCol = curCol + dc[i]; 39 | if ((0 <= nextRow && nextRow < rows) && (0 <= nextCol && nextCol < cols) && (grid[nextRow][nextCol] == 1)) 40 | { 41 | grid[nextRow][nextCol] = -1; 42 | q.push({nextRow, nextCol}); 43 | numCells++; 44 | } 45 | } 46 | } 47 | 48 | return isClosed ? numCells : 0; 49 | } 50 | 51 | public: 52 | int numEnclaves(vector> &grid) 53 | { 54 | int result = 0; 55 | int m = grid.size(); 56 | int n = grid[0].size(); 57 | 58 | for (int i = 0; i < m; i++) 59 | for (int j = 0; j < n; j++) 60 | if (grid[i][j] == 1) 61 | result += bfs(grid, i, j, m, n); 62 | 63 | return result; 64 | } 65 | }; 66 | 67 | // Time Complexity: O(m*n) 68 | // Space Complexity: O(m*n) -------------------------------------------------------------------------------- /4. April/Day8CloneGraph.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day8CloneGraph.cpp 3 | * @author Ginny Dang 4 | * @brief 133. Clone Graph (https://leetcode.com/problems/clone-graph/description/) 5 | * @version 0.1 6 | * @date 2023-04-07 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | /* 13 | // Definition for a Node. 14 | class Node { 15 | public: 16 | int val; 17 | vector neighbors; 18 | Node() { 19 | val = 0; 20 | neighbors = vector(); 21 | } 22 | Node(int _val) { 23 | val = _val; 24 | neighbors = vector(); 25 | } 26 | Node(int _val, vector _neighbors) { 27 | val = _val; 28 | neighbors = _neighbors; 29 | } 30 | }; 31 | */ 32 | 33 | class Solution 34 | { 35 | private: 36 | Node *clonedNodes[101]; 37 | 38 | void dfs(Node *u) 39 | { 40 | clonedNodes[u->val] = new Node(u->val); 41 | clonedNodes[u->val]->neighbors = vector(); 42 | 43 | for (auto v : u->neighbors) 44 | { 45 | if (!clonedNodes[v->val]) 46 | dfs(v); 47 | Node *newU = clonedNodes[u->val]; 48 | Node *newV = clonedNodes[v->val]; 49 | newU->neighbors.push_back(newV); 50 | } 51 | } 52 | 53 | public: 54 | Node *cloneGraph(Node *node) 55 | { 56 | if (!node) 57 | return NULL; 58 | 59 | dfs(node); 60 | 61 | return clonedNodes[node->val]; 62 | } 63 | }; 64 | 65 | // Time Complexity : O(N + M) 66 | // Space Complexity : O(N) -------------------------------------------------------------------------------- /4. April/Day9LargestColorValueInADirectedGraph.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Day9LargestColorValueInADirectedGraph.cpp 3 | * @author Ginny Dang 4 | * @brief 1857. Largest Color Value in a Directed Graph (https://leetcode.com/problems/largest-color-value-in-a-directed-graph/description/) 5 | * @version 0.1 6 | * @date 2023-04-09 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | 12 | class Solution 13 | { 14 | private: 15 | int dfs(int node, string &colors, vector> &graph, vector> &count, vector &visited, vector &inStack) 16 | { 17 | if (inStack[node]) 18 | return INT_MAX; 19 | if (visited[node]) 20 | return count[node][colors[node] - 'a']; 21 | 22 | inStack[node] = true; 23 | visited[node] = true; 24 | 25 | for (auto &neighbor : graph[node]) 26 | { 27 | if (dfs(neighbor, colors, graph, count, visited, inStack) == INT_MAX) 28 | return INT_MAX; 29 | 30 | for (int i = 0; i < 26; i++) 31 | count[node][i] = max(count[node][i], count[neighbor][i]); 32 | } 33 | 34 | count[node][colors[node] - 'a']++; 35 | inStack[node] = false; 36 | 37 | return count[node][colors[node] - 'a']; 38 | } 39 | 40 | public: 41 | int largestPathValue(string colors, vector> &edges) 42 | { 43 | int n = colors.length(); 44 | int m = edges.size(); 45 | vector> graph(n); 46 | for (auto &edge : edges) 47 | graph[edge[0]].push_back(edge[1]); 48 | 49 | vector> count(n, vector(26)); 50 | vector visited(n); 51 | vector inStack(n); 52 | int result = 0; // maximum frequency of a color in a the graph 53 | for (int i = 0; i < n; i++) 54 | result = max(result, dfs(i, colors, graph, count, visited, inStack)); 55 | 56 | return result == INT_MAX ? -1 : result; 57 | } 58 | }; 59 | 60 | // Time complexity: O(m + n) or O(26m + 26n) to be exact 61 | // Space complexity: O(m + n) or O(m + 26n) to be exact -------------------------------------------------------------------------------- /images/AppBreweryWallpaper 8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ginny100/Leetcode-2023/084487241ba004a14fc90aecbae3fa3a58486f72/images/AppBreweryWallpaper 8.png -------------------------------------------------------------------------------- /images/AppBreweryWallpaper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ginny100/Leetcode-2023/084487241ba004a14fc90aecbae3fa3a58486f72/images/AppBreweryWallpaper.png --------------------------------------------------------------------------------