Skip to content

Commit

Permalink
Added tasks 3324-3327
Browse files Browse the repository at this point in the history
  • Loading branch information
javadev authored Oct 22, 2024
1 parent 10d4a1a commit d61c4a2
Show file tree
Hide file tree
Showing 12 changed files with 441 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package g3301_3400.s3324_find_the_sequence_of_strings_appeared_on_the_screen

// #Medium #String #Simulation #2024_10_22_Time_8_ms_(100.00%)_Space_62.7_MB_(29.63%)

class Solution {
fun stringSequence(target: String): List<String> {
val ans: MutableList<String> = ArrayList<String>()
val l = target.length
val cur = StringBuilder()
for (i in 0 until l) {
val tCh = target[i]
cur.append('a')
ans.add(cur.toString())
while (cur[i] != tCh) {
val lastCh = cur[i]
val nextCh = (if (lastCh == 'z') 'a'.code else lastCh.code + 1).toChar()
cur.setCharAt(i, nextCh)
ans.add(cur.toString())
}
}
return ans
}
}
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package g3301_3400.s3325_count_substrings_with_k_frequency_characters_i

// #Medium #String #Hash_Table #Sliding_Window #2024_10_22_Time_3_ms_(88.00%)_Space_35.9_MB_(76.00%)

class Solution {
fun numberOfSubstrings(s: String, k: Int): Int {
var left = 0
var result = 0
val count = IntArray(26)
for (i in 0 until s.length) {
val ch = s[i]
count[ch.code - 'a'.code]++

while (count[ch.code - 'a'.code] == k) {
result += s.length - i
val atLeft = s[left]
count[atLeft.code - 'a'.code]--
left++
}
}
return result
}
}
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package g3301_3400.s3326_minimum_division_operations_to_make_array_non_decreasing

// #Medium #Array #Math #Greedy #Number_Theory
// #2024_10_22_Time_24_ms_(94.12%)_Space_64.2_MB_(64.71%)

import kotlin.math.max

class Solution {
fun minOperations(nums: IntArray): Int {
compute()
var op = 0
val n = nums.size
for (i in n - 2 downTo 0) {
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
}

companion object {
private const val MAXI = 1000001
private val SIEVE = IntArray(MAXI)
private var precompute = false

private fun compute() {
if (precompute) {
return
}
for (i in 2 until MAXI) {
if (i * i > MAXI) {
break
}
var j = i * i
while (j < MAXI) {
SIEVE[j] =
max(SIEVE[j], max(i, (j / i)))
j += i
}
}
precompute = true
}
}
}
Original file line number Diff line number Diff line change
@@ -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:**

* <code>1 <= nums.length <= 10<sup>5</sup></code>
* <code>1 <= nums[i] <= 10<sup>6</sup></code>
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package g3301_3400.s3327_check_if_dfs_strings_are_palindromes

// #Hard #Array #String #Hash_Table #Depth_First_Search #Tree #Hash_Function
// #2024_10_22_Time_165_ms_(100.00%)_Space_88.9_MB_(66.67%)

import kotlin.math.min

class Solution {
private val e: MutableList<MutableList<Int?>?> = ArrayList<MutableList<Int?>?>()
private val stringBuilder = StringBuilder()
private var s: String? = null
private var now = 0
private var n = 0
private lateinit var l: IntArray
private lateinit var r: IntArray
private lateinit var p: IntArray
private lateinit var c: CharArray

private fun dfs(x: Int) {
l[x] = now + 1
for (v in e[x]!!) {
dfs(v!!)
}
stringBuilder.append(s!![x])
r[x] = ++now
}

private fun matcher() {
c[0] = '~'
c[1] = '#'
for (i in 1..n) {
c[2 * i + 1] = '#'
c[2 * i] = stringBuilder[i - 1]
}
var j = 1
var mid = 0
var localR = 0
while (j <= 2 * n + 1) {
if (j <= localR) {
p[j] = min(p[(mid shl 1) - j], (localR - j + 1))
}
while (c[j - p[j]] == c[j + p[j]]) {
++p[j]
}
if (p[j] + j > localR) {
localR = p[j] + j - 1
mid = j
}
++j
}
}

fun findAnswer(parent: IntArray, s: String): BooleanArray {
n = parent.size
this.s = s
for (i in 0 until n) {
e.add(ArrayList<Int?>())
}
for (i in 1 until n) {
e[parent[i]]!!.add(i)
}
l = IntArray(n)
r = IntArray(n)
dfs(0)
c = CharArray(2 * n + 10)
p = IntArray(2 * n + 10)
matcher()
val ans = BooleanArray(n)
for (i in 0 until n) {
val mid = (2 * r[i] - 2 * l[i] + 1) / 2 + 2 * l[i]
ans[i] = p[mid] - 1 >= r[i] - l[i] + 1
}
return ans
}
}
Original file line number Diff line number Diff line change
@@ -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`
* <code>1 <= n <= 10<sup>5</sup></code>
* `0 <= parent[i] <= n - 1` for all `i >= 1`.
* `parent[0] == -1`
* `parent` represents a valid tree.
* `s` consists only of lowercase English letters.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package g3301_3400.s3324_find_the_sequence_of_strings_appeared_on_the_screen

import org.hamcrest.CoreMatchers.equalTo
import org.hamcrest.MatcherAssert.assertThat
import org.junit.jupiter.api.Test

internal class SolutionTest {
@Test
fun stringSequence() {
assertThat<List<String>>(
Solution().stringSequence("abc"),
equalTo<List<String>>(listOf<String>("a", "aa", "ab", "aba", "abb", "abc"))
)
}

@Test
fun stringSequence2() {
assertThat<List<String>>(
Solution().stringSequence("he"),
equalTo<List<String>>(
listOf<String>(
"a", "b", "c", "d", "e", "f", "g", "h", "ha", "hb", "hc", "hd",
"he"
)
)
)
}
}
Loading

0 comments on commit d61c4a2

Please sign in to comment.