From 596ea574469cc49624208002a0a913668959afa7 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Mon, 21 Oct 2024 19:33:40 +0300 Subject: [PATCH 1/6] Added tasks 3324-3327 --- .../Solution.java | 26 ++++++ .../readme.md | 42 +++++++++ .../Solution.java | 37 ++++++++ .../readme.md | 36 ++++++++ .../Solution.java | 43 +++++++++ .../readme.md | 40 +++++++++ .../Solution.java | 88 +++++++++++++++++++ .../readme.md | 61 +++++++++++++ .../SolutionTest.java | 26 ++++++ .../SolutionTest.java | 18 ++++ .../SolutionTest.java | 23 +++++ .../SolutionTest.java | 22 +++++ 12 files changed, 462 insertions(+) create mode 100644 src/main/java/g3301_3400/s3324_find_the_sequence_of_strings_appeared_on_the_screen/Solution.java create mode 100644 src/main/java/g3301_3400/s3324_find_the_sequence_of_strings_appeared_on_the_screen/readme.md create mode 100644 src/main/java/g3301_3400/s3325_count_substrings_with_k_frequency_characters_i/Solution.java create mode 100644 src/main/java/g3301_3400/s3325_count_substrings_with_k_frequency_characters_i/readme.md create mode 100644 src/main/java/g3301_3400/s3326_minimum_division_operations_to_make_array_non_decreasing/Solution.java create mode 100644 src/main/java/g3301_3400/s3326_minimum_division_operations_to_make_array_non_decreasing/readme.md create mode 100644 src/main/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/Solution.java create mode 100644 src/main/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/readme.md create mode 100644 src/test/java/g3301_3400/s3324_find_the_sequence_of_strings_appeared_on_the_screen/SolutionTest.java create mode 100644 src/test/java/g3301_3400/s3325_count_substrings_with_k_frequency_characters_i/SolutionTest.java create mode 100644 src/test/java/g3301_3400/s3326_minimum_division_operations_to_make_array_non_decreasing/SolutionTest.java create mode 100644 src/test/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/SolutionTest.java diff --git a/src/main/java/g3301_3400/s3324_find_the_sequence_of_strings_appeared_on_the_screen/Solution.java b/src/main/java/g3301_3400/s3324_find_the_sequence_of_strings_appeared_on_the_screen/Solution.java new file mode 100644 index 000000000..ad61d325a --- /dev/null +++ b/src/main/java/g3301_3400/s3324_find_the_sequence_of_strings_appeared_on_the_screen/Solution.java @@ -0,0 +1,26 @@ +package g3301_3400.s3324_find_the_sequence_of_strings_appeared_on_the_screen; + +// #Medium #2024_10_21_Time_6_ms_(100.00%)_Space_55.6_MB_(100.00%) + +import java.util.ArrayList; +import java.util.List; + +public class Solution { + public List stringSequence(String t) { + List ans = new ArrayList<>(); + int l = t.length(); + StringBuilder cur = new StringBuilder(); + for (int i = 0; i < l; i++) { + char tCh = t.charAt(i); + cur.append('a'); + ans.add(cur.toString()); + while (cur.charAt(i) != tCh) { + char lastCh = cur.charAt(i); + char nextCh = (char) (lastCh == 'z' ? 'a' : lastCh + 1); + cur.setCharAt(i, nextCh); + ans.add(cur.toString()); + } + } + return ans; + } +} diff --git a/src/main/java/g3301_3400/s3324_find_the_sequence_of_strings_appeared_on_the_screen/readme.md b/src/main/java/g3301_3400/s3324_find_the_sequence_of_strings_appeared_on_the_screen/readme.md new file mode 100644 index 000000000..40579fd0e --- /dev/null +++ b/src/main/java/g3301_3400/s3324_find_the_sequence_of_strings_appeared_on_the_screen/readme.md @@ -0,0 +1,42 @@ +3324\. Find the Sequence of Strings Appeared on the Screen + +Medium + +You are given a string `target`. + +Alice is going to type `target` on her computer using a special keyboard that has **only two** keys: + +* Key 1 appends the character `"a"` to the string on the screen. +* Key 2 changes the **last** character of the string on the screen to its **next** character in the English alphabet. For example, `"c"` changes to `"d"` and `"z"` changes to `"a"`. + +**Note** that initially there is an _empty_ string `""` on the screen, so she can **only** press key 1. + +Return a list of _all_ strings that appear on the screen as Alice types `target`, in the order they appear, using the **minimum** key presses. + +**Example 1:** + +**Input:** target = "abc" + +**Output:** ["a","aa","ab","aba","abb","abc"] + +**Explanation:** + +The sequence of key presses done by Alice are: + +* Press key 1, and the string on the screen becomes `"a"`. +* Press key 1, and the string on the screen becomes `"aa"`. +* Press key 2, and the string on the screen becomes `"ab"`. +* Press key 1, and the string on the screen becomes `"aba"`. +* Press key 2, and the string on the screen becomes `"abb"`. +* Press key 2, and the string on the screen becomes `"abc"`. + +**Example 2:** + +**Input:** target = "he" + +**Output:** ["a","b","c","d","e","f","g","h","ha","hb","hc","hd","he"] + +**Constraints:** + +* `1 <= target.length <= 400` +* `target` consists only of lowercase English letters. \ No newline at end of file diff --git a/src/main/java/g3301_3400/s3325_count_substrings_with_k_frequency_characters_i/Solution.java b/src/main/java/g3301_3400/s3325_count_substrings_with_k_frequency_characters_i/Solution.java new file mode 100644 index 000000000..2b3ba34a7 --- /dev/null +++ b/src/main/java/g3301_3400/s3325_count_substrings_with_k_frequency_characters_i/Solution.java @@ -0,0 +1,37 @@ +package g3301_3400.s3325_count_substrings_with_k_frequency_characters_i; + +// #Medium #2024_10_21_Time_2009_ms_(100.00%)_Space_45.2_MB_(100.00%) + +import java.util.HashMap; +import java.util.PriorityQueue; + +public class Solution { + public int numberOfSubstrings(String s, int k) { + int charCount = 0; + HashMap map = new HashMap<>(); + for (int right = 0; right < s.length(); right++) { + char curr = s.charAt(right); + map.put(curr, map.getOrDefault(curr, 0) + 1); + PriorityQueue queue = new PriorityQueue<>((a, b) -> b - a); + for (char ele : map.keySet()) { + queue.offer(map.get(ele)); + } + HashMap currMap = new HashMap<>(map); + for (int left = 0; left <= right; left++) { + int maxEle = queue.peek(); + if (maxEle < k) { + break; + } + charCount += 1; + char leftChar = s.charAt(left); + int leftCharCount = currMap.get(leftChar); + currMap.put(leftChar, leftCharCount - 1); + queue.remove(leftCharCount); + if (leftCharCount > 1) { + queue.offer(leftCharCount - 1); + } + } + } + return charCount; + } +} diff --git a/src/main/java/g3301_3400/s3325_count_substrings_with_k_frequency_characters_i/readme.md b/src/main/java/g3301_3400/s3325_count_substrings_with_k_frequency_characters_i/readme.md new file mode 100644 index 000000000..d13f50198 --- /dev/null +++ b/src/main/java/g3301_3400/s3325_count_substrings_with_k_frequency_characters_i/readme.md @@ -0,0 +1,36 @@ +3325\. Count Substrings With K-Frequency Characters I + +Medium + +Given a string `s` and an integer `k`, return the total number of substrings of `s` where **at least one** character appears **at least** `k` times. + +**Example 1:** + +**Input:** s = "abacb", k = 2 + +**Output:** 4 + +**Explanation:** + +The valid substrings are: + +* `"aba"` (character `'a'` appears 2 times). +* `"abac"` (character `'a'` appears 2 times). +* `"abacb"` (character `'a'` appears 2 times). +* `"bacb"` (character `'b'` appears 2 times). + +**Example 2:** + +**Input:** s = "abcde", k = 1 + +**Output:** 15 + +**Explanation:** + +All substrings are valid because every character appears at least once. + +**Constraints:** + +* `1 <= s.length <= 3000` +* `1 <= k <= s.length` +* `s` consists only of lowercase English letters. \ No newline at end of file diff --git a/src/main/java/g3301_3400/s3326_minimum_division_operations_to_make_array_non_decreasing/Solution.java b/src/main/java/g3301_3400/s3326_minimum_division_operations_to_make_array_non_decreasing/Solution.java new file mode 100644 index 000000000..c1216ba05 --- /dev/null +++ b/src/main/java/g3301_3400/s3326_minimum_division_operations_to_make_array_non_decreasing/Solution.java @@ -0,0 +1,43 @@ +package g3301_3400.s3326_minimum_division_operations_to_make_array_non_decreasing; + +// #Medium #2024_10_21_Time_19_ms_(100.00%)_Space_69.1_MB_(100.00%) + +public class Solution { + private static final int MAXI = 1000001; + private static final int[] SIEVE = new int[MAXI]; + private static boolean precompute = false; + + private void compute() { + if (precompute) { + return; + } + for (int i = 2; i < MAXI; i++) { + if (i * i > MAXI) { + break; + } + for (int j = i * i; j < MAXI; j += i) { + SIEVE[j] = Math.max(SIEVE[j], Math.max(i, j / i)); + } + } + precompute = true; + } + + public int minOperations(int[] nums) { + compute(); + int op = 0; + int n = nums.length; + for (int i = n - 2; i >= 0; i--) { + while (nums[i] > nums[i + 1]) { + if (SIEVE[nums[i]] == 0) { + return -1; + } + nums[i] /= SIEVE[nums[i]]; + op++; + } + if (nums[i] > nums[i + 1]) { + return -1; + } + } + return op; + } +} diff --git a/src/main/java/g3301_3400/s3326_minimum_division_operations_to_make_array_non_decreasing/readme.md b/src/main/java/g3301_3400/s3326_minimum_division_operations_to_make_array_non_decreasing/readme.md new file mode 100644 index 000000000..a43b41a5a --- /dev/null +++ b/src/main/java/g3301_3400/s3326_minimum_division_operations_to_make_array_non_decreasing/readme.md @@ -0,0 +1,40 @@ +3326\. Minimum Division Operations to Make Array Non Decreasing + +Medium + +You are given an integer array `nums`. + +Any **positive** divisor of a natural number `x` that is **strictly less** than `x` is called a **proper divisor** of `x`. For example, 2 is a _proper divisor_ of 4, while 6 is not a _proper divisor_ of 6. + +You are allowed to perform an **operation** any number of times on `nums`, where in each **operation** you select any _one_ element from `nums` and divide it by its **greatest** **proper divisor**. + +Return the **minimum** number of **operations** required to make the array **non-decreasing**. + +If it is **not** possible to make the array _non-decreasing_ using any number of operations, return `-1`. + +**Example 1:** + +**Input:** nums = [25,7] + +**Output:** 1 + +**Explanation:** + +Using a single operation, 25 gets divided by 5 and `nums` becomes `[5, 7]`. + +**Example 2:** + +**Input:** nums = [7,7,6] + +**Output:** \-1 + +**Example 3:** + +**Input:** nums = [1,1,1,1] + +**Output:** 0 + +**Constraints:** + +* 1 <= nums.length <= 105 +* 1 <= nums[i] <= 106 \ No newline at end of file diff --git a/src/main/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/Solution.java b/src/main/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/Solution.java new file mode 100644 index 000000000..a64b3de6a --- /dev/null +++ b/src/main/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/Solution.java @@ -0,0 +1,88 @@ +package g3301_3400.s3327_check_if_dfs_strings_are_palindromes; + +// #Hard #2024_10_21_Time_244_ms_(100.00%)_Space_96.3_MB_(100.00%) + +import java.util.ArrayList; + +public class Solution { + private StringBuilder dfsString; + + private int[] fillManacher(String s) { + int n = s.length(); + s = "$" + s + "@"; + int[] p = new int[n + 2]; + int center = 0; + int right = 0; + for (int i = 1; i <= n; i++) { + int mirror = 2 * center - i; + if (i < right) { + p[i] = Math.min(right - i, p[mirror]); + } + while (s.charAt(i + p[i]) == s.charAt(i - p[i])) { + p[i]++; + } + if (i + p[i] > right) { + center = i; + right = i + p[i]; + } + } + return p; + } + + private int[] manacher() { + StringBuilder temp = new StringBuilder(); + for (int i = 0; i < dfsString.length(); i++) { + temp.append("#"); + temp.append(dfsString.charAt(i)); + } + temp.append("#"); + return fillManacher(String.valueOf(temp)); + // return Arrays.copyOfRange(arr, 1, arr.length - 1); + } + + private void dfs( + int node, int parent, ArrayList> adj, int[][] range, String s) { + int start = dfsString.length(); + + for (int neigh : adj.get(node)) { + if (neigh == parent) { + continue; + } + dfs(neigh, node, adj, range, s); + } + dfsString.append(s.charAt(node)); + int end = dfsString.length() - 1; + range[node] = new int[] {start, end}; + } + + public boolean[] findAnswer(int[] parent, String s) { + dfsString = new StringBuilder(); + int n = parent.length; + ArrayList> adj = new ArrayList<>(); + for (int i = 0; i < n; i++) { + adj.add(new ArrayList<>()); + } + for (int i = 0; i < n; i++) { + if (parent[i] == -1) { + continue; + } + adj.get(parent[i]).add(i); + } + int[][] range = new int[n][2]; + dfs(0, -1, adj, range, s); + int[] manacherArr = manacher(); + boolean[] ans = new boolean[n]; + for (int i = 0; i < n; i++) { + int[] currRange = range[i]; + int length = currRange[1] - currRange[0] + 1; + // +2 because the string has $# in the starting and in the end + int palindromeStart = 2 * currRange[0] + 2; + int palindromeEnd = 2 * currRange[1] + 2; + int center = (palindromeStart + palindromeEnd) / 2; + // represents the palindrome length having center at center. + int palindromeLength = manacherArr[center]; + ans[i] = palindromeLength >= length; + } + return ans; + } +} diff --git a/src/main/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/readme.md b/src/main/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/readme.md new file mode 100644 index 000000000..789a9c56b --- /dev/null +++ b/src/main/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/readme.md @@ -0,0 +1,61 @@ +3327\. Check if DFS Strings Are Palindromes + +Hard + +You are given a tree rooted at node 0, consisting of `n` nodes numbered from `0` to `n - 1`. The tree is represented by an array `parent` of size `n`, where `parent[i]` is the parent of node `i`. Since node 0 is the root, `parent[0] == -1`. + +You are also given a string `s` of length `n`, where `s[i]` is the character assigned to node `i`. + +Consider an empty string `dfsStr`, and define a recursive function `dfs(int x)` that takes a node `x` as a parameter and performs the following steps in order: + +* Iterate over each child `y` of `x` **in increasing order of their numbers**, and call `dfs(y)`. +* Add the character `s[x]` to the end of the string `dfsStr`. + +**Note** that `dfsStr` is shared across all recursive calls of `dfs`. + +You need to find a boolean array `answer` of size `n`, where for each index `i` from `0` to `n - 1`, you do the following: + +* Empty the string `dfsStr` and call `dfs(i)`. +* If the resulting string `dfsStr` is a **palindrome**, then set `answer[i]` to `true`. Otherwise, set `answer[i]` to `false`. + +Return the array `answer`. + +A **palindrome** is a string that reads the same forward and backward. + +**Example 1:** + +![](https://assets.leetcode.com/uploads/2024/09/01/tree1drawio.png) + +**Input:** parent = [-1,0,0,1,1,2], s = "aababa" + +**Output:** [true,true,false,true,true,true] + +**Explanation:** + +* Calling `dfs(0)` results in the string `dfsStr = "abaaba"`, which is a palindrome. +* Calling `dfs(1)` results in the string `dfsStr = "aba"`, which is a palindrome. +* Calling `dfs(2)` results in the string `dfsStr = "ab"`, which is **not** a palindrome. +* Calling `dfs(3)` results in the string `dfsStr = "a"`, which is a palindrome. +* Calling `dfs(4)` results in the string `dfsStr = "b"`, which is a palindrome. +* Calling `dfs(5)` results in the string `dfsStr = "a"`, which is a palindrome. + +**Example 2:** + +![](https://assets.leetcode.com/uploads/2024/09/01/tree2drawio-1.png) + +**Input:** parent = [-1,0,0,0,0], s = "aabcb" + +**Output:** [true,true,true,true,true] + +**Explanation:** + +Every call on `dfs(x)` results in a palindrome string. + +**Constraints:** + +* `n == parent.length == s.length` +* 1 <= n <= 105 +* `0 <= parent[i] <= n - 1` for all `i >= 1`. +* `parent[0] == -1` +* `parent` represents a valid tree. +* `s` consists only of lowercase English letters. \ No newline at end of file diff --git a/src/test/java/g3301_3400/s3324_find_the_sequence_of_strings_appeared_on_the_screen/SolutionTest.java b/src/test/java/g3301_3400/s3324_find_the_sequence_of_strings_appeared_on_the_screen/SolutionTest.java new file mode 100644 index 000000000..704d87513 --- /dev/null +++ b/src/test/java/g3301_3400/s3324_find_the_sequence_of_strings_appeared_on_the_screen/SolutionTest.java @@ -0,0 +1,26 @@ +package g3301_3400.s3324_find_the_sequence_of_strings_appeared_on_the_screen; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.util.List; +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void stringSequence() { + assertThat( + new Solution().stringSequence("abc"), + equalTo(List.of("a", "aa", "ab", "aba", "abb", "abc"))); + } + + @Test + void stringSequence2() { + assertThat( + new Solution().stringSequence("he"), + equalTo( + List.of( + "a", "b", "c", "d", "e", "f", "g", "h", "ha", "hb", "hc", "hd", + "he"))); + } +} diff --git a/src/test/java/g3301_3400/s3325_count_substrings_with_k_frequency_characters_i/SolutionTest.java b/src/test/java/g3301_3400/s3325_count_substrings_with_k_frequency_characters_i/SolutionTest.java new file mode 100644 index 000000000..998c319eb --- /dev/null +++ b/src/test/java/g3301_3400/s3325_count_substrings_with_k_frequency_characters_i/SolutionTest.java @@ -0,0 +1,18 @@ +package g3301_3400.s3325_count_substrings_with_k_frequency_characters_i; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void numberOfSubstrings() { + assertThat(new Solution().numberOfSubstrings("abacb", 2), equalTo(4)); + } + + @Test + void numberOfSubstrings2() { + assertThat(new Solution().numberOfSubstrings("abcde", 1), equalTo(15)); + } +} diff --git a/src/test/java/g3301_3400/s3326_minimum_division_operations_to_make_array_non_decreasing/SolutionTest.java b/src/test/java/g3301_3400/s3326_minimum_division_operations_to_make_array_non_decreasing/SolutionTest.java new file mode 100644 index 000000000..45a5a3734 --- /dev/null +++ b/src/test/java/g3301_3400/s3326_minimum_division_operations_to_make_array_non_decreasing/SolutionTest.java @@ -0,0 +1,23 @@ +package g3301_3400.s3326_minimum_division_operations_to_make_array_non_decreasing; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void minOperations() { + assertThat(new Solution().minOperations(new int[] {25, 7}), equalTo(1)); + } + + @Test + void minOperations2() { + assertThat(new Solution().minOperations(new int[] {7, 7, 6}), equalTo(-1)); + } + + @Test + void minOperations3() { + assertThat(new Solution().minOperations(new int[] {1, 1, 1, 1}), equalTo(0)); + } +} diff --git a/src/test/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/SolutionTest.java b/src/test/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/SolutionTest.java new file mode 100644 index 000000000..06756a6b9 --- /dev/null +++ b/src/test/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/SolutionTest.java @@ -0,0 +1,22 @@ +package g3301_3400.s3327_check_if_dfs_strings_are_palindromes; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void findAnswer() { + assertThat( + new Solution().findAnswer(new int[] {-1, 0, 0, 1, 1, 2}, "aababa"), + equalTo(new boolean[] {true, true, false, true, true, true})); + } + + @Test + void findAnswer2() { + assertThat( + new Solution().findAnswer(new int[] {-1, 0, 0, 0, 0}, "aabcb"), + equalTo(new boolean[] {true, true, true, true, true})); + } +} From e2b570f6c101bd42d63237f3c985c70cb911e386 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Mon, 21 Oct 2024 19:41:48 +0300 Subject: [PATCH 2/6] Fixed sonar --- .../Solution.java | 5 +++-- .../Solution.java | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/g3301_3400/s3325_count_substrings_with_k_frequency_characters_i/Solution.java b/src/main/java/g3301_3400/s3325_count_substrings_with_k_frequency_characters_i/Solution.java index 2b3ba34a7..604444592 100644 --- a/src/main/java/g3301_3400/s3325_count_substrings_with_k_frequency_characters_i/Solution.java +++ b/src/main/java/g3301_3400/s3325_count_substrings_with_k_frequency_characters_i/Solution.java @@ -3,6 +3,7 @@ // #Medium #2024_10_21_Time_2009_ms_(100.00%)_Space_45.2_MB_(100.00%) import java.util.HashMap; +import java.util.Map; import java.util.PriorityQueue; public class Solution { @@ -13,8 +14,8 @@ public int numberOfSubstrings(String s, int k) { char curr = s.charAt(right); map.put(curr, map.getOrDefault(curr, 0) + 1); PriorityQueue queue = new PriorityQueue<>((a, b) -> b - a); - for (char ele : map.keySet()) { - queue.offer(map.get(ele)); + for (Map.Entry ele : map.entrySet()) { + queue.offer(ele.getValue()); } HashMap currMap = new HashMap<>(map); for (int left = 0; left <= right; left++) { diff --git a/src/main/java/g3301_3400/s3326_minimum_division_operations_to_make_array_non_decreasing/Solution.java b/src/main/java/g3301_3400/s3326_minimum_division_operations_to_make_array_non_decreasing/Solution.java index c1216ba05..519d71658 100644 --- a/src/main/java/g3301_3400/s3326_minimum_division_operations_to_make_array_non_decreasing/Solution.java +++ b/src/main/java/g3301_3400/s3326_minimum_division_operations_to_make_array_non_decreasing/Solution.java @@ -7,7 +7,7 @@ public class Solution { private static final int[] SIEVE = new int[MAXI]; private static boolean precompute = false; - private void compute() { + private static void compute() { if (precompute) { return; } From 1376a529fd9da0f5158d6e415a0131b013193393 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Tue, 22 Oct 2024 11:23:00 +0300 Subject: [PATCH 3/6] Improved tags --- .../Solution.java | 2 +- .../Solution.java | 43 +++---- .../Solution.java | 2 +- .../Solution.java | 110 +++++++----------- 4 files changed, 61 insertions(+), 96 deletions(-) diff --git a/src/main/java/g3301_3400/s3324_find_the_sequence_of_strings_appeared_on_the_screen/Solution.java b/src/main/java/g3301_3400/s3324_find_the_sequence_of_strings_appeared_on_the_screen/Solution.java index ad61d325a..5123c440a 100644 --- a/src/main/java/g3301_3400/s3324_find_the_sequence_of_strings_appeared_on_the_screen/Solution.java +++ b/src/main/java/g3301_3400/s3324_find_the_sequence_of_strings_appeared_on_the_screen/Solution.java @@ -1,6 +1,6 @@ package g3301_3400.s3324_find_the_sequence_of_strings_appeared_on_the_screen; -// #Medium #2024_10_21_Time_6_ms_(100.00%)_Space_55.6_MB_(100.00%) +// #Medium #String #Simulation #2024_10_22_Time_6_ms_(92.04%)_Space_55.7_MB_(44.25%) import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/g3301_3400/s3325_count_substrings_with_k_frequency_characters_i/Solution.java b/src/main/java/g3301_3400/s3325_count_substrings_with_k_frequency_characters_i/Solution.java index 604444592..cc6a26463 100644 --- a/src/main/java/g3301_3400/s3325_count_substrings_with_k_frequency_characters_i/Solution.java +++ b/src/main/java/g3301_3400/s3325_count_substrings_with_k_frequency_characters_i/Solution.java @@ -1,38 +1,23 @@ package g3301_3400.s3325_count_substrings_with_k_frequency_characters_i; -// #Medium #2024_10_21_Time_2009_ms_(100.00%)_Space_45.2_MB_(100.00%) - -import java.util.HashMap; -import java.util.Map; -import java.util.PriorityQueue; +// #Medium #String #Hash_Table #Sliding_Window #2024_10_22_Time_1_ms_(100.00%)_Space_42_MB_(98.69%) public class Solution { public int numberOfSubstrings(String s, int k) { - int charCount = 0; - HashMap map = new HashMap<>(); - for (int right = 0; right < s.length(); right++) { - char curr = s.charAt(right); - map.put(curr, map.getOrDefault(curr, 0) + 1); - PriorityQueue queue = new PriorityQueue<>((a, b) -> b - a); - for (Map.Entry ele : map.entrySet()) { - queue.offer(ele.getValue()); - } - HashMap currMap = new HashMap<>(map); - for (int left = 0; left <= right; left++) { - int maxEle = queue.peek(); - if (maxEle < k) { - break; - } - charCount += 1; - char leftChar = s.charAt(left); - int leftCharCount = currMap.get(leftChar); - currMap.put(leftChar, leftCharCount - 1); - queue.remove(leftCharCount); - if (leftCharCount > 1) { - queue.offer(leftCharCount - 1); - } + int left = 0; + int result = 0; + int[] count = new int[26]; + for (int i = 0; i < s.length(); i++) { + char ch = s.charAt(i); + count[ch - 'a']++; + + while (count[ch - 'a'] == k) { + result += s.length() - i; + char atLeft = s.charAt(left); + count[atLeft - 'a']--; + left++; } } - return charCount; + return result; } } diff --git a/src/main/java/g3301_3400/s3326_minimum_division_operations_to_make_array_non_decreasing/Solution.java b/src/main/java/g3301_3400/s3326_minimum_division_operations_to_make_array_non_decreasing/Solution.java index 519d71658..bb460a10e 100644 --- a/src/main/java/g3301_3400/s3326_minimum_division_operations_to_make_array_non_decreasing/Solution.java +++ b/src/main/java/g3301_3400/s3326_minimum_division_operations_to_make_array_non_decreasing/Solution.java @@ -1,6 +1,6 @@ package g3301_3400.s3326_minimum_division_operations_to_make_array_non_decreasing; -// #Medium #2024_10_21_Time_19_ms_(100.00%)_Space_69.1_MB_(100.00%) +// #Medium #Array #Math #Greedy #Number_Theory #2024_10_22_Time_20_ms_(97.34%)_Space_73.1_MB_(5.03%) public class Solution { private static final int MAXI = 1000001; diff --git a/src/main/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/Solution.java b/src/main/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/Solution.java index a64b3de6a..ad09b20d3 100644 --- a/src/main/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/Solution.java +++ b/src/main/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/Solution.java @@ -1,87 +1,67 @@ package g3301_3400.s3327_check_if_dfs_strings_are_palindromes; -// #Hard #2024_10_21_Time_244_ms_(100.00%)_Space_96.3_MB_(100.00%) +// #Hard #Array #String #Hash_Table #Tree #Hash_Function #Depth_First_Search +// #2024_10_22_Time_159_ms_(90.40%)_Space_93.9_MB_(80.80%) import java.util.ArrayList; +import java.util.List; public class Solution { - private StringBuilder dfsString; + private final List> e = new ArrayList<>(); + private final StringBuilder stringBuilder = new StringBuilder(); + private String s; + private int now; + private int n; + private int[] l; + private int[] r; + private int[] p; + private char[] c; - private int[] fillManacher(String s) { - int n = s.length(); - s = "$" + s + "@"; - int[] p = new int[n + 2]; - int center = 0; - int right = 0; - for (int i = 1; i <= n; i++) { - int mirror = 2 * center - i; - if (i < right) { - p[i] = Math.min(right - i, p[mirror]); - } - while (s.charAt(i + p[i]) == s.charAt(i - p[i])) { - p[i]++; - } - if (i + p[i] > right) { - center = i; - right = i + p[i]; - } + private void dfs(int x) { + l[x] = now + 1; + for (int v : e.get(x)) { + dfs(v); } - return p; + stringBuilder.append(s.charAt(x)); + r[x] = ++now; } - private int[] manacher() { - StringBuilder temp = new StringBuilder(); - for (int i = 0; i < dfsString.length(); i++) { - temp.append("#"); - temp.append(dfsString.charAt(i)); + private void manacher() { + c[0] = '~'; + c[1] = '#'; + for (int i = 1; i <= n; ++i) { + c[2 * i + 1] = '#'; + c[2 * i] = stringBuilder.charAt(i - 1); } - temp.append("#"); - return fillManacher(String.valueOf(temp)); - // return Arrays.copyOfRange(arr, 1, arr.length - 1); - } - - private void dfs( - int node, int parent, ArrayList> adj, int[][] range, String s) { - int start = dfsString.length(); - - for (int neigh : adj.get(node)) { - if (neigh == parent) { - continue; + for (int i = 1, mid = 0, r = 0; i <= 2 * n + 1; ++i) { + if (i <= r) p[i] = Math.min(p[(mid << 1) - i], r - i + 1); + while (c[i - p[i]] == c[i + p[i]]) ++p[i]; + if (p[i] + i > r) { + r = p[i] + i - 1; + mid = i; } - dfs(neigh, node, adj, range, s); } - dfsString.append(s.charAt(node)); - int end = dfsString.length() - 1; - range[node] = new int[] {start, end}; } public boolean[] findAnswer(int[] parent, String s) { - dfsString = new StringBuilder(); - int n = parent.length; - ArrayList> adj = new ArrayList<>(); - for (int i = 0; i < n; i++) { - adj.add(new ArrayList<>()); + n = parent.length; + this.s = s; + for (int i = 0; i < n; ++i) { + e.add(new ArrayList<>()); } - for (int i = 0; i < n; i++) { - if (parent[i] == -1) { - continue; - } - adj.get(parent[i]).add(i); + for (int i = 1; i < n; ++i) { + e.get(parent[i]).add(i); } - int[][] range = new int[n][2]; - dfs(0, -1, adj, range, s); - int[] manacherArr = manacher(); + l = new int[n]; + r = new int[n]; + dfs(0); + c = new char[2 * n + 10]; + p = new int[2 * n + 10]; + manacher(); boolean[] ans = new boolean[n]; - for (int i = 0; i < n; i++) { - int[] currRange = range[i]; - int length = currRange[1] - currRange[0] + 1; - // +2 because the string has $# in the starting and in the end - int palindromeStart = 2 * currRange[0] + 2; - int palindromeEnd = 2 * currRange[1] + 2; - int center = (palindromeStart + palindromeEnd) / 2; - // represents the palindrome length having center at center. - int palindromeLength = manacherArr[center]; - ans[i] = palindromeLength >= length; + for (int i = 0; i < n; ++i) { + int mid = (2 * r[i] - 2 * l[i] + 1) / 2 + 2 * l[i]; + ans[i] = p[mid] - 1 >= r[i] - l[i] + 1; } return ans; } From 1e4263a544028fb6f9130a19676adeee7e314ac2 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Tue, 22 Oct 2024 11:25:45 +0300 Subject: [PATCH 4/6] Fixed style --- .../Solution.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/Solution.java b/src/main/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/Solution.java index ad09b20d3..bb380b6b1 100644 --- a/src/main/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/Solution.java +++ b/src/main/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/Solution.java @@ -26,7 +26,7 @@ private void dfs(int x) { r[x] = ++now; } - private void manacher() { + private void matcher() { c[0] = '~'; c[1] = '#'; for (int i = 1; i <= n; ++i) { @@ -34,8 +34,12 @@ private void manacher() { c[2 * i] = stringBuilder.charAt(i - 1); } for (int i = 1, mid = 0, r = 0; i <= 2 * n + 1; ++i) { - if (i <= r) p[i] = Math.min(p[(mid << 1) - i], r - i + 1); - while (c[i - p[i]] == c[i + p[i]]) ++p[i]; + if (i <= r) { + p[i] = Math.min(p[(mid << 1) - i], r - i + 1); + } + while (c[i - p[i]] == c[i + p[i]]) { + ++p[i]; + } if (p[i] + i > r) { r = p[i] + i - 1; mid = i; @@ -57,7 +61,7 @@ public boolean[] findAnswer(int[] parent, String s) { dfs(0); c = new char[2 * n + 10]; p = new int[2 * n + 10]; - manacher(); + matcher(); boolean[] ans = new boolean[n]; for (int i = 0; i < n; ++i) { int mid = (2 * r[i] - 2 * l[i] + 1) / 2 + 2 * l[i]; From f67aeb6ac02b64f646be539c2b31ddbc84a47940 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Tue, 22 Oct 2024 11:29:05 +0300 Subject: [PATCH 5/6] Fixed sonar --- .../Solution.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/main/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/Solution.java b/src/main/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/Solution.java index bb380b6b1..0362a1706 100644 --- a/src/main/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/Solution.java +++ b/src/main/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/Solution.java @@ -33,17 +33,21 @@ private void matcher() { c[2 * i + 1] = '#'; c[2 * i] = stringBuilder.charAt(i - 1); } - for (int i = 1, mid = 0, r = 0; i <= 2 * n + 1; ++i) { - if (i <= r) { - p[i] = Math.min(p[(mid << 1) - i], r - i + 1); + int j = 1; + int mid = 0; + int r = 0; + while (j <= 2 * n + 1) { + if (j <= r) { + p[j] = Math.min(p[(mid << 1) - j], r - j + 1); } - while (c[i - p[i]] == c[i + p[i]]) { - ++p[i]; + while (c[j - p[j]] == c[j + p[j]]) { + ++p[j]; } - if (p[i] + i > r) { - r = p[i] + i - 1; - mid = i; + if (p[j] + j > r) { + r = p[j] + j - 1; + mid = j; } + ++j; } } From 4afbbbe8bc0c7fa9c46757ea0117d04e93166355 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Tue, 22 Oct 2024 11:33:35 +0300 Subject: [PATCH 6/6] Fixed sonar --- .../Solution.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/Solution.java b/src/main/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/Solution.java index 0362a1706..17355bcf9 100644 --- a/src/main/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/Solution.java +++ b/src/main/java/g3301_3400/s3327_check_if_dfs_strings_are_palindromes/Solution.java @@ -35,16 +35,16 @@ private void matcher() { } int j = 1; int mid = 0; - int r = 0; + int localR = 0; while (j <= 2 * n + 1) { - if (j <= r) { - p[j] = Math.min(p[(mid << 1) - j], r - j + 1); + if (j <= localR) { + p[j] = Math.min(p[(mid << 1) - j], localR - j + 1); } while (c[j - p[j]] == c[j + p[j]]) { ++p[j]; } - if (p[j] + j > r) { - r = p[j] + j - 1; + if (p[j] + j > localR) { + localR = p[j] + j - 1; mid = j; } ++j;