diff --git a/solution/0800-0899/0878.Nth Magical Number/Solution.java b/solution/0800-0899/0878.Nth Magical Number/Solution.java index 08e2efd135108..c62d32ea227dd 100644 --- a/solution/0800-0899/0878.Nth Magical Number/Solution.java +++ b/solution/0800-0899/0878.Nth Magical Number/Solution.java @@ -1,21 +1,26 @@ class Solution { - private static final int MOD = (int) 1e9 + 7; public int nthMagicalNumber(int n, int a, int b) { - int c = a * b / gcd(a, b); - long l = 0, r = (long) (a + b) * n; - while (l < r) { - long mid = l + r >>> 1; - if (mid / a + mid / b - mid / c >= n) { - r = mid; + long lcm = lcm(a, b); + long ans = 0; + // binary search + for (long l = 0, r = (long) n * Math.min(a, b), m = 0; l <= r;) { + m = (l + r) / 2; + if (m / a + m / b - m /lcm >= n) { + ans = m; + r = m - 1; } else { - l = mid + 1; + l = m + 1; } } - return (int) (l % MOD); + return (int) (ans % 1000000007); } - private int gcd(int a, int b) { + public static long gcd(long a, long b) { return b == 0 ? a : gcd(b, a % b); } -} \ No newline at end of file + + public static long lcm(long a, long b) { + return (long) a / gcd(a, b) * b; + } +} diff --git a/solution/1000-1099/1074.Number of Submatrices That Sum to Target/Solution.py b/solution/1000-1099/1074.Number of Submatrices That Sum to Target/Solution.py index 2ca477bc01e9c..6c149048da36b 100644 --- a/solution/1000-1099/1074.Number of Submatrices That Sum to Target/Solution.py +++ b/solution/1000-1099/1074.Number of Submatrices That Sum to Target/Solution.py @@ -1,21 +1,32 @@ class Solution: - def numSubmatrixSumTarget(self, matrix: List[List[int]], target: int) -> int: - def f(nums: List[int]) -> int: - d = defaultdict(int) - d[0] = 1 - cnt = s = 0 - for x in nums: - s += x - cnt += d[s - target] - d[s] += 1 - return cnt + def numSubmatrixSumTarget(self, matrix, target): + """ + :type matrix: List[List[int]] + :type target: int + :rtype: int + """ + m = len(matrix) + n = len(matrix[0]) + ans = 0 + for i in range(m): + col = [0] * n + for j in range(i, m): + for k in range(n): + col[k] += matrix[j][k] + ans += self.f(col, target) + return ans - m, n = len(matrix), len(matrix[0]) - ans = 0 - for i in range(m): - col = [0] * n - for j in range(i, m): - for k in range(n): - col[k] += matrix[j][k] - ans += f(col) - return ans + def f(self, nums, target): + """ + :type nums: List[int] + :type target: int + :rtype: int + """ + d = {0: 1} # map to store prefix sum counts + s = 0 + cnt = 0 + for x in nums: + s += x + cnt += d.get(s - target, 0) # count subarray sums equal to target + d[s] = d.get(s, 0) + 1 # update prefix sum count + return cnt diff --git a/solution/1200-1299/1224.Maximum Equal Frequency/Solution.java b/solution/1200-1299/1224.Maximum Equal Frequency/Solution.java index a45f3c42ef31f..e41cfcf46a798 100644 --- a/solution/1200-1299/1224.Maximum Equal Frequency/Solution.java +++ b/solution/1200-1299/1224.Maximum Equal Frequency/Solution.java @@ -1,28 +1,28 @@ -class Solution { - private static int[] cnt = new int[100010]; - private static int[] ccnt = new int[100010]; +import java.util.HashMap; +import java.util.Map; +class Solution { public int maxEqualFreq(int[] nums) { - Arrays.fill(cnt, 0); - Arrays.fill(ccnt, 0); - int ans = 0; - int mx = 0; - for (int i = 1; i <= nums.length; ++i) { - int v = nums[i - 1]; - if (cnt[v] > 0) { - --ccnt[cnt[v]]; + Map count = new HashMap<>(); // Use HashMap to store the frequency of each number + Map freqCount = new HashMap<>(); // Use HashMap to store the frequency of each frequency + int maxFreq = 0, ans = 0; + for (int i = 0; i < nums.length; i++) { + int num = nums[i]; + if (count.containsKey(num)) { + freqCount.put(count.get(num), freqCount.getOrDefault(count.get(num), 0) - 1); // Decrement the count of the previous frequency } - ++cnt[v]; - mx = Math.max(mx, cnt[v]); - ++ccnt[cnt[v]]; - if (mx == 1) { - ans = i; - } else if (ccnt[mx] * mx + ccnt[mx - 1] * (mx - 1) == i && ccnt[mx] == 1) { - ans = i; - } else if (ccnt[mx] * mx + 1 == i && ccnt[1] == 1) { - ans = i; + count.put(num, count.getOrDefault(num, 0) + 1); // Increment the count of the current number + maxFreq = Math.max(maxFreq, count.get(num)); // Update the maximum frequency + freqCount.put(count.get(num), freqCount.getOrDefault(count.get(num), 0) + 1); // Increment the count of the current frequency + + if (maxFreq == 1) { + ans = i + 1; // Update the answer if all elements have the same frequency (1) + } else if (freqCount.get(maxFreq) * maxFreq + (freqCount.getOrDefault(maxFreq - 1, 0) * (maxFreq - 1)) == i + 1 && freqCount.get(maxFreq) == 1) { + ans = i + 1; // Update the answer if there's only one element with the maximum frequency and all other elements have a frequency one less than the maximum + } else if (freqCount.get(maxFreq) * maxFreq + 1 == i + 1 && freqCount.get(1) == 1) { + ans = i + 1; // Update the answer if there's only one element with a frequency of 1 and all other elements have the maximum frequency } } return ans; } -} \ No newline at end of file +} diff --git a/solution/1300-1399/1330.Reverse Subarray To Maximize Array Value/Solution.java b/solution/1300-1399/1330.Reverse Subarray To Maximize Array Value/Solution.java index 8d3cec383ebda..d674750d2c1bf 100644 --- a/solution/1300-1399/1330.Reverse Subarray To Maximize Array Value/Solution.java +++ b/solution/1300-1399/1330.Reverse Subarray To Maximize Array Value/Solution.java @@ -1,30 +1,31 @@ class Solution { - public int maxValueAfterReverse(int[] nums) { - int n = nums.length; - int s = 0; - for (int i = 0; i < n - 1; ++i) { - s += Math.abs(nums[i] - nums[i + 1]); - } - int ans = s; - for (int i = 0; i < n - 1; ++i) { - ans = Math.max( - ans, s + Math.abs(nums[0] - nums[i + 1]) - Math.abs(nums[i] - nums[i + 1])); - ans = Math.max( - ans, s + Math.abs(nums[n - 1] - nums[i]) - Math.abs(nums[i] - nums[i + 1])); - } - int[] dirs = {1, -1, -1, 1, 1}; - final int inf = 1 << 30; - for (int k = 0; k < 4; ++k) { - int k1 = dirs[k], k2 = dirs[k + 1]; - int mx = -inf, mi = inf; - for (int i = 0; i < n - 1; ++i) { - int a = k1 * nums[i] + k2 * nums[i + 1]; - int b = Math.abs(nums[i] - nums[i + 1]); - mx = Math.max(mx, a - b); - mi = Math.min(mi, a + b); - } - ans = Math.max(ans, s + Math.max(0, mx - mi)); - } - return ans; + + public int maxValueAfterReverse(int[] nums) { + int n = nums.length; + int s = 0; + for (int i = 0; i < n - 1; ++i) { + s += Math.abs(nums[i] - nums[i + 1]); } -} \ No newline at end of file + int ans = s; + for (int i = 0; i < n - 1; ++i) { + ans = Math.max( + ans, s + Math.abs(nums[0] - nums[i + 1]) - Math.abs(nums[i] - nums[i + 1])); + ans = Math.max( + ans, s + Math.abs(nums[n - 1] - nums[i]) - Math.abs(nums[i] - nums[i + 1])); + } + int[] dirs = {1, -1, -1, 1, 1}; + final int inf = 1 << 30; + for (int k = 0; k < 4; ++k) { + int k1 = dirs[k], k2 = dirs[k + 1]; + int mx = -inf, mi = inf; + for (int i = 0; i < n - 1; ++i) { + int a = k1 * nums[i] + k2 * nums[i + 1]; + int b = Math.abs(nums[i] - nums[i + 1]); + mx = Math.max(mx, a - b); + mi = Math.min(mi, a + b); + } + ans = Math.max(ans, s + Math.max(0, mx - mi)); + } + return ans; + } +} diff --git a/solution/1900-1999/1900.The Earliest and Latest Rounds Where Players Compete/Solution.java b/solution/1900-1999/1900.The Earliest and Latest Rounds Where Players Compete/Solution.java new file mode 100644 index 0000000000000..50cddb93b4293 --- /dev/null +++ b/solution/1900-1999/1900.The Earliest and Latest Rounds Where Players Compete/Solution.java @@ -0,0 +1,35 @@ +import java.util.*; + +public class Solution { + private Map, int[]> memo = new HashMap<>(); + + public int[] earliestAndLatest(int n, int firstPlayer, int secondPlayer) { + return dp(firstPlayer, n - secondPlayer + 1, n); + } + + private int[] dp(int l, int r, int k) { + if (l == r) return new int[]{1, 1}; + if (l > r) return dp(r, l, k); + + List key = Arrays.asList(l, r, k); + if (memo.containsKey(key)) return memo.get(key); + + int earliest = Integer.MAX_VALUE; + int latest = Integer.MIN_VALUE; + + // Enumerate all possible positions + for (int i = 1; i <= l; ++i) { + for (int j = l - i + 1; j <= r - i + 1; ++j) { + if (!(l + r - k / 2 <= i + j && i + j <= (k + 1) / 2)) continue; + + int[] result = dp(i, j, (k + 1) / 2); + earliest = Math.min(earliest, result[0] + 1); + latest = Math.max(latest, result[1] + 1); + } + } + + int[] result = new int[]{earliest, latest}; + memo.put(key, result); + return result; + } +} diff --git a/solution/1900-1999/1938.Maximum Genetic Difference Query/Solution.java b/solution/1900-1999/1938.Maximum Genetic Difference Query/Solution.java new file mode 100644 index 0000000000000..5c5710d1f0cd2 --- /dev/null +++ b/solution/1900-1999/1938.Maximum Genetic Difference Query/Solution.java @@ -0,0 +1,116 @@ +import java.util.*; + +class TrieNode { + TrieNode[] children; + int count; + + public TrieNode() { + this.children = new TrieNode[2]; + this.count = 0; + } +} + +class Trie { + private final TrieNode root; + + public Trie() { + this.root = new TrieNode(); + } + + public void insert(int num) { + TrieNode node = root; + for (int i = 17; i >= 0; i--) { + int bit = (num >> i) & 1; + if (node.children[bit] == null) { + node.children[bit] = new TrieNode(); + } + node = node.children[bit]; + node.count++; + } + } + + public void remove(int num) { + TrieNode node = root; + for (int i = 17; i >= 0; i--) { + int bit = (num >> i) & 1; + node = node.children[bit]; + node.count--; + } + } + + public int maxXOR(int num) { + TrieNode node = root; + int max_xor = 0; + for (int i = 17; i >= 0; i--) { + int bit = (num >> i) & 1; + int toggled_bit = 1 - bit; + if (node.children[toggled_bit] != null && node.children[toggled_bit].count > 0) { + max_xor |= (1 << i); + node = node.children[toggled_bit]; + } else { + node = node.children[bit]; + } + } + return max_xor; + } +} + +class Solution { + public int[] maxGeneticDifference(int[] parents, int[][] queries) { + int n = parents.length; + + // Build the tree as an adjacency list + Map> tree = new HashMap<>(); + int root = -1; + + for (int i = 0; i < n; i++) { + if (parents[i] == -1) { + root = i; + } else { + tree.computeIfAbsent(parents[i], k -> new ArrayList<>()).add(i); + } + } + + // Group queries by node + Map> queryMap = new HashMap<>(); + for (int i = 0; i < queries.length; i++) { + int node = queries[i][0]; + int val = queries[i][1]; + queryMap.computeIfAbsent(node, k -> new ArrayList<>()).add(new int[]{val, i}); + } + + // Result array + int[] res = new int[queries.length]; + + // Trie to store and query the path genetic values + Trie trie = new Trie(); + + // Depth-first search to solve the queries + dfs(root, tree, queryMap, trie, res); + + return res; + } + + private void dfs(int node, Map> tree, Map> queryMap, Trie trie, int[] res) { + trie.insert(node); + + // Handle queries for this node + if (queryMap.containsKey(node)) { + for (int[] query : queryMap.get(node)) { + int val = query[0]; + int idx = query[1]; + res[idx] = trie.maxXOR(val); + } + } + + // Recurse for children + if (tree.containsKey(node)) { + for (int child : tree.get(node)) { + dfs(child, tree, queryMap, trie, res); + } + } + + // Remove the node after processing its subtree + trie.remove(node); + } +} diff --git a/solution/1900-1999/1938.Maximum Genetic Difference Query/Solution.py b/solution/1900-1999/1938.Maximum Genetic Difference Query/Solution.py new file mode 100644 index 0000000000000..976d87cf9e27c --- /dev/null +++ b/solution/1900-1999/1938.Maximum Genetic Difference Query/Solution.py @@ -0,0 +1,79 @@ +from collections import defaultdict + +class TrieNode: + def __init__(self): + self.children = {} + self.count = 0 + +class Trie: + def __init__(self): + self.root = TrieNode() + + def insert(self, num): + node = self.root + for i in range(17, -1, -1): + bit = (num >> i) & 1 + if bit not in node.children: + node.children[bit] = TrieNode() + node = node.children[bit] + node.count += 1 + + def remove(self, num): + node = self.root + for i in range(17, -1, -1): + bit = (num >> i) & 1 + if bit in node.children: + node = node.children[bit] + node.count -= 1 + + def maxXOR(self, num): + node = self.root + max_xor = 0 + for i in range(17, -1, -1): + bit = (num >> i) & 1 + toggled_bit = 1 - bit + if toggled_bit in node.children and node.children[toggled_bit].count > 0: + max_xor |= (1 << i) + node = node.children[toggled_bit] + else: + node = node.children[bit] + return max_xor + +class Solution: + def maxGeneticDifference(self, parents, queries): + n = len(parents) + + # Build the tree as an adjacency list + tree = defaultdict(list) + root = -1 + for i in range(n): + if parents[i] == -1: + root = i + else: + tree[parents[i]].append(i) + + # Group queries by the node + query_map = defaultdict(list) + for idx, (node, val) in enumerate(queries): + query_map[node].append((val, idx)) + + # Result array + res = [0] * len(queries) + + # Trie to store and query the path genetic values + trie = Trie() + + # Depth-first search to solve the queries + def dfs(node): + trie.insert(node) + if node in query_map: + for val, idx in query_map[node]: + res[idx] = trie.maxXOR(val) + for child in tree[node]: + dfs(child) + trie.remove(node) + + # Start DFS from the root + dfs(root) + + return res diff --git a/solution/1900-1999/1948.Delete Duplicate Folders in System/Solution.java b/solution/1900-1999/1948.Delete Duplicate Folders in System/Solution.java new file mode 100644 index 0000000000000..26b73b90592c0 --- /dev/null +++ b/solution/1900-1999/1948.Delete Duplicate Folders in System/Solution.java @@ -0,0 +1,117 @@ +import java.util.*; + +class TrieNode { + Map children; + Integer id; + + public TrieNode() { + this.children = new HashMap<>(); + this.id = null; + } +} + +public class Solution { + public List> deleteDuplicateFolder(List> paths) { + TrieNode root = new TrieNode(); + + // Step 1: Build Trie (Tree) + for (List path : paths) { + TrieNode node = root; + for (String folder : path) { + node = node.children.computeIfAbsent(folder, k -> new TrieNode()); + } + } + + // Step 2: Assign unique IDs to subtrees + Map> subtreeMap = new HashMap<>(); + + getSubtreeId(root, subtreeMap); + + // Step 3: Mark duplicates + Set duplicates = new HashSet<>(); + for (List nodes : subtreeMap.values()) { + if (nodes.size() > 1) { // If more than one node has the same structure, mark as duplicate + duplicates.addAll(nodes); + } + } + + // Step 4: Collect remaining paths + List> ans = new ArrayList<>(); + collectRemainingPaths(root, new ArrayList<>(), duplicates, ans); + + return ans; + } + + private String getSubtreeId(TrieNode node, Map> subtreeMap) { + if (node.children.isEmpty()) { + return ""; // Empty subtree has no ID + } + + // Sort children lexicographically and form a string representing the subtree + List subtreeList = new ArrayList<>(); + for (Map.Entry entry : node.children.entrySet()) { + String folder = entry.getKey(); + TrieNode child = entry.getValue(); + subtreeList.add(folder + "(" + getSubtreeId(child, subtreeMap) + ")"); + } + Collections.sort(subtreeList); + + // Create a unique string representation of the subtree + String subtree = String.join(",", subtreeList); + + // Map the subtree representation to the node + subtreeMap.computeIfAbsent(subtree, k -> new ArrayList<>()).add(node); + + return subtree; + } + + private void collectRemainingPaths(TrieNode node, List path, Set duplicates, List> ans) { + if (duplicates.contains(node)) { + return; // Skip this subtree because it is marked for deletion + } + + if (!path.isEmpty()) { + ans.add(new ArrayList<>(path)); + } + + for (Map.Entry entry : node.children.entrySet()) { + path.add(entry.getKey()); + collectRemainingPaths(entry.getValue(), path, duplicates, ans); + path.remove(path.size() - 1); + } + } + + public static void main(String[] args) { + Solution sol = new Solution(); + + List> paths1 = Arrays.asList( + Arrays.asList("a"), + Arrays.asList("c"), + Arrays.asList("d"), + Arrays.asList("a", "b"), + Arrays.asList("c", "b"), + Arrays.asList("d", "a") + ); + + List> result1 = sol.deleteDuplicateFolder(paths1); + for (List path : result1) { + System.out.println(path); + } + + List> paths2 = Arrays.asList( + Arrays.asList("a"), + Arrays.asList("c"), + Arrays.asList("a", "b"), + Arrays.asList("c", "b"), + Arrays.asList("a", "b", "x"), + Arrays.asList("a", "b", "x", "y"), + Arrays.asList("w"), + Arrays.asList("w", "y") + ); + + List> result2 = sol.deleteDuplicateFolder(paths2); + for (List path : result2) { + System.out.println(path); + } + } +} diff --git a/solution/1900-1999/1948.Delete Duplicate Folders in System/Solution.py b/solution/1900-1999/1948.Delete Duplicate Folders in System/Solution.py new file mode 100644 index 0000000000000..3871b18fcac6f --- /dev/null +++ b/solution/1900-1999/1948.Delete Duplicate Folders in System/Solution.py @@ -0,0 +1,52 @@ +from collections import defaultdict + +class TrieNode: + def __init__(self): + self.children = defaultdict(TrieNode) + self.id = None + +class Solution: + def deleteDuplicateFolder(self, paths): + # Step 1: Build a Trie (Tree) to represent the file system structure + root = TrieNode() + + for path in paths: + node = root + for folder in path: + node = node.children[folder] + + # Step 2: Assign unique IDs to the subtrees for easier comparison + subtree_map = defaultdict(list) + def get_id(node): + if not node.children: + return 0 # Empty subtree + subtree_tuple = tuple((name, get_id(child)) for name, child in sorted(node.children.items())) + subtree_id = hash(subtree_tuple) + subtree_map[subtree_id].append(node) + return subtree_id + + get_id(root) + + # Step 3: Mark duplicate subtrees by examining the subtree map + duplicates = set() + for nodes in subtree_map.values(): + if len(nodes) > 1: # If more than one node has the same subtree ID, mark as duplicate + for node in nodes: + duplicates.add(node) + + # Step 4: Reconstruct the remaining paths + ans = [] + + def collect_paths(node, path): + if node in duplicates: + return # Skip this subtree because it's marked for deletion + if path: + ans.append(path[:]) + for folder, child in sorted(node.children.items()): + path.append(folder) + collect_paths(child, path) + path.pop() + + collect_paths(root, []) + + return ans diff --git a/solution/2000-2099/2014.Longest Subsequence Repeated k Times/Solution.java b/solution/2000-2099/2014.Longest Subsequence Repeated k Times/Solution.java new file mode 100644 index 0000000000000..a468db531301b --- /dev/null +++ b/solution/2000-2099/2014.Longest Subsequence Repeated k Times/Solution.java @@ -0,0 +1,88 @@ +import java.util.*; + +public class Solution { + public String longestSubsequenceRepeatedK(String s, int k) { + // Step 1: Frequency counter for each character in the string + Map freq = new HashMap<>(); + for (char c : s.toCharArray()) { + freq.put(c, freq.getOrDefault(c, 0) + 1); + } + + // Step 2: Collect all characters with at least k frequency + List candidates = new ArrayList<>(); + for (Map.Entry entry : freq.entrySet()) { + if (entry.getValue() >= k) { + candidates.add(entry.getKey()); + } + } + + // Step 4: Breadth-First Search (BFS) to generate subsequences + Queue queue = new LinkedList<>(); + queue.offer(""); // Start with an empty sequence + String longest = ""; + + while (!queue.isEmpty()) { + String curr = queue.poll(); + + // Try appending each candidate character to the current subsequence + for (char ch : candidates) { + String newSubseq = curr + ch; + + // Check if the new subsequence is repeatable k times + if (canBeRepeatedKTimes(newSubseq, s, k)) { + queue.offer(newSubseq); + + // Update longest if newSubseq is longer or lexicographically larger + if (newSubseq.length() > longest.length() || + (newSubseq.length() == longest.length() && newSubseq.compareTo(longest) > 0)) { + longest = newSubseq; + } + } + } + } + + return longest; + } + + // Helper function to check if a subsequence can be repeated k times + private boolean canBeRepeatedKTimes(String subseq, String s, int k) { + int i = 0, count = 0; + for (char ch : s.toCharArray()) { + if (ch == subseq.charAt(i)) { + i++; + if (i == subseq.length()) { + i = 0; + count++; + if (count == k) { + return true; + } + } + } + } + return false; + } + + public static void main(String[] args) { + Solution sol = new Solution(); + + // Test case 1 + String s1 = "letsleetcode"; + int k1 = 2; + System.out.println(sol.longestSubsequenceRepeatedK(s1, k1)); // Output: "let" + + // Test case 2 + String s2 = "bb"; + int k2 = 2; + System.out.println(sol.longestSubsequenceRepeatedK(s2, k2)); // Output: "b" + + // Test case 3 + String s3 = "ab"; + int k3 = 2; + System.out.println(sol.longestSubsequenceRepeatedK(s3, k3)); // Output: "" + + // Test case 4 + String s4 = "bbabbabbbbabaababab"; + int k4 = 3; + System.out.println(sol.longestSubsequenceRepeatedK(s4, k4)); // Output: "bbbb" + } +} diff --git a/solution/2000-2099/2014.Longest Subsequence Repeated k Times/Solution.py b/solution/2000-2099/2014.Longest Subsequence Repeated k Times/Solution.py new file mode 100644 index 0000000000000..cfb0673388756 --- /dev/null +++ b/solution/2000-2099/2014.Longest Subsequence Repeated k Times/Solution.py @@ -0,0 +1,52 @@ +from collections import Counter, deque + +class Solution: + def longestSubsequenceRepeatedK(self, s: str, k: int) -> str: + # Step 1: Frequency counter for each character in the string + freq = Counter(s) + + # Step 2: Collect all characters with at least k frequency + candidates = [ch for ch, count in freq.items() if count >= k] + + # Step 3: Helper function to check if a given sequence can be repeated k times + def canBeRepeatedKTimes(subseq): + i = 0 + count = 0 + for ch in s: + if ch == subseq[i]: + i += 1 + if i == len(subseq): + i = 0 + count += 1 + if count == k: + return True + return False + + # Step 4: Breadth-First Search (BFS) to generate subsequences + queue = deque([""]) # Start with an empty sequence + longest = "" + + while queue: + curr = queue.popleft() + + # Try appending each candidate character to the current subsequence + for ch in candidates: + new_subseq = curr + ch + + # Check if the new subsequence is repeatable k times + if canBeRepeatedKTimes(new_subseq): + queue.append(new_subseq) + + # Update longest if new_subseq is longer or lexicographically larger + if len(new_subseq) > len(longest) or (len(new_subseq) == len(longest) and new_subseq > longest): + longest = new_subseq + + return longest + + +# Example usage: +sol = Solution() +print(sol.longestSubsequenceRepeatedK("letsleetcode", 2)) # Output: "let" +print(sol.longestSubsequenceRepeatedK("bb", 2)) # Output: "b" +print(sol.longestSubsequenceRepeatedK("ab", 2)) # Output: "" +print(sol.longestSubsequenceRepeatedK("bbabbabbbbabaababab", 3)) # Output: "bbbb"