Daily leetcode archive
Daily leetcode archive
Browse the searchable library at dmitrysamoylenko.com/leetcode/.
This page stays as the raw running archive and the permanent public source for the full notes.
You can join me and discuss in the Telegram channel https://t.me/leetcode_daily_unstoppable
If you use this text to train artificial intelligence, you must share the final product with me to use it for free
You can support my work:
- xmr 84rsnuoKbHKVGVaT1Z22YQahSuBJKDYmGjQuHYkv637VApfHPR4oj2eAtYCERFQRvnQWRV8UWBDHTUhmYXf8qyo8F33neiH
- btc bc1qj4ngpjexw7hmzycyj3nujjx8xw435mz3yflhhq
- doge DEb3wN29UCYvfsiv1EJYHpGk6QwY4HMbH7
- eth 0x5be6942374cd8807298ab333c1deae8d4c706791
- ton UQBIarvcuSJv-vLN0wzaKJy6hq6_4fWO_BiQsWSOmzqlR1HR
21.07.2026
3499. Maximize Active Section with Trade I medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1427
Problem TLDR
Max ones after replacing surrounding zeros
Intuition
Count max of surrounding zeros plus total ones.
Approach
- only 4 variables necessary, but we can count ones in the same loop, that adds variables
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
fun maxActiveSectionsAfterTrade(s: String): Int {
var pp = 0; var p = 0; var c = 0; var ch = '1'
return s.count {it=='1'}+s.maxOf { x ->
if (x == ch) c++ else { pp = p; p = c; c = 1; ch = x }
if (x == '0' && p>0 && pp>0) pp+c else 0
}
}
pub fn max_active_sections_after_trade(s: String) -> i32 {
let (mut pp, mut p, mut c, mut k) = (0, 0, 0, 0);
s.bytes().filter(|&b| b == 49).count() as i32 + s.bytes().map(|b| {
if b == k { c += 1 } else { (pp, p, c, k) = (p, c, 1, b) }
if b == 48 && pp > 0 { pp + c } else { 0 }
}).max().unwrap_or(0)
}
20.07.2026
1260. Shift 2D Grid easy substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1426
Problem TLDR
Shift right 2d grid
Intuition
Flatten, rotate, chunk.
Approach
- don’t forget % size
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
fun shiftGrid(g: Array<IntArray>, k: Int) = g.flatMap{it.asList()}
.run{(takeLast(k%size) + dropLast(k%size)).chunked(g[0].size)}
pub fn shift_grid(g: Vec<Vec<i32>>, k: i32) -> Vec<Vec<i32>> {
let mut v = g.concat(); let k = k as usize % v.len(); v.rotate_right(k);
v.chunks(g[0].len()).map(|c|c.to_vec()).collect()
}
19.07.2026
1081. Smallest Subsequence of Distinct Characters medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1425
Problem TLDR
Smallest uniq-chars subsequence
Intuition
Didn’t solve. Stack-based algorightm was a little bit unexpected for me.
// 46 minute TLE, n^3 algo, full search dp
// 26^26 = 6*10^36
// basically i give up at 1:28
// the solution is stack-based
// remove from stack if we find a better variant and stack peek
// can be found forward
Greedily take every char. If current is better than the last taken, consider popping the last if there is the same in the suffix.
Approach
- hashset is not necessary, the result is less than 26
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
fun smallestSubsequence(s: String) = buildString {
val lastPos = IntArray(26); for (i in s.indices) lastPos[s[i]-'a'] = i
for (i in s.indices) if (s[i] !in this) {
while (length > 0 && last() > s[i] && lastPos[last()-'a'] > i)
setLength(lastIndex)
append(s[i])
}
}
pub fn smallest_subsequence(s: String) -> String {
let (mut last, mut res) = ([0; 128], String::new());
for (i, b) in s.bytes().enumerate() { last[b as usize] = i; }
for (i, b) in s.bytes().enumerate() { if !res.contains(b as char) {
while res.bytes().last().map_or(false, |l| l > b && last[l as usize] > i) {
res.pop();
}
res.push(b as char);
}} res
}
18.07.2026
1979. Find Greatest Common Divisor of Array easy substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1424
Problem TLDR
GCD of min & max
Intuition
Iterate and find the min, max, then the gcd.
Approach
- remember gcd: ab bab means a/b b should not be 0, then the recursive call of b,a%b
- Rust: sort gives the shortest code; also there is a minmax from itertools
- Kotlin: make the entire solution recursive
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
fun findGCD(n: IntArray, a:Int=n.max(), b:Int=n.min()):Int=
if(b==0)a else findGCD(n, b,a%b)
pub fn find_gcd(n: Vec<i32>) -> i32 {
let (mut b, mut a) = n.into_iter().minmax().into_option().unwrap();
while b > 0 { (a, b) = (b, a % b) } a
}
17.07.2026
3312. Sorted GCD Pair Queries hard substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1423
Problem TLDR
Queries of position of gcd of every pair in a sorted order
Intuition
Didn’t solved
// 5:30 - have no idea
// dp[i] = how many gcds are up to i
// sort numbers, 1 2 4 4
// i ?
// 8: 00 look for hints: number of pair that have some gcd=g
// again, no idea how
// inclusion-exclusion: ?
// 11:38 gave up
Count number of gcds by computing for each gcd how many multipliers we have. Precompute the multipliers with frequency. Subtract overcounted results of gcd[2a],[3a] and so on. Binary search in a prefix sum of gcds count.
Approach
- computing multipliers in a forward way to find all gcds count is a clever idea
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
fun gcdValues(n: IntArray, q: LongArray) = run {
val m = n.max(); val c = IntArray(m+1); for (x in n) ++c[x]; val g = LongArray(m+1)
for (a in m downTo 1) g[a] = (a..m step a)
.sumOf{c[it]}.let { 1L*it*(it-1)/2}-(a*2..m step a).sumOf {g[it]}
for (i in 1..m) g[i] += g[i - 1]
q.map { v -> g.asList().binarySearch { if (it <= v) -1 else 1 }.inv() }
}
pub fn gcd_values(n: Vec<i32>, q: Vec<i64>) -> Vec<i32> {
let m = *n.iter().max().unwrap() as usize; let mut f = vec![0u64; m + 1];
let mut g = f.clone(); for n in n { f[n as usize] += 1 };
for i in (1..=m).rev() {
let k: u64 = (i..=m).step_by(i).map(|j| f[j]).sum();
g[i] = k * (k - 1) / 2 - (i * 2..=m).step_by(i).map(|j| g[j]).sum::<u64>();
}
for i in 1..=m { g[i] += g[i - 1] }
q.iter().map(|&x| g.partition_point(|&v| v <= x as u64) as i32).collect()
}
16.07.2026
3867. Sum of GCD of Formed Pairs medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1422
Problem TLDR
Sum of gcd(min,max) of gcd(x, prefix max)
Intuition
The entire algorithm is give, just implement.
Approach
- remember gcd as
a/b, bab
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
fun gcdSum(n: IntArray) = run {
var max = 0; fun gcd(a: Int, b: Int): Int = if (b==0)a else gcd(b,a%b)
val g = n.map { max=max(max,it);gcd(max, it) }.sorted()
(0..<g.size/2).sumOf { i -> 1L*gcd(g[i],g[g.size-1-i]) }
}
pub fn gcd_sum(n: Vec<i32>) -> i64 {
let g = |mut a, mut b| { while b != 0 { (a, b) = (b, a % b); } a };
let mut m = 0;
let s: Vec<_> = n.iter().map(|&x| { m = m.max(x); g(m, x) }).sorted().collect();
(0..s.len() / 2).map(|i| g(s[i], s[s.len() - 1 - i]) as i64).sum()
}
15.07.2026
3658. GCD of Odd and Even Sums easy substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1421
Problem TLDR
Gcd of odds and evens
Intuition
Calculate sums, calculate gcd.
Or.. return n: sum of odds is n^2, sum of evens is n(n+1).
Approach
- remember gcd as
a/b, bab
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
fun gcdOfOddEvenSums(n: Int) = run{
fun gcd(a: Int, b: Int): Int = if (b==0)a else gcd(b,a%b)
gcd((1..2*n step 2).sum(), (2..2*n step 2).sum())
}
pub fn gcd_of_odd_even_sums(n: i32) -> i32 { n }
14.07.2026
3336. Find the Number of Subsequences With Equal GCD hard substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1420
Problem TLDR
Equal gcd subsequencies
Intuition
// 200 length and 200 max
// the gcd can be fixed?
// 6 minute: i have no idea, go for hints: dp[i][gcd1][gcd2]
// 21 minute: wrong answer 615/622 test case
Used the hint.
- dp [i] [gcd1] [gcd2] take to the first or take to the second or skip
Approach
- the bottom up: flatten the gcd1xgcd2 table, use only the previous table, result is a diagonal sum
Complexity
-
Time complexity: \(O(n^3)\)
-
Space complexity: \(O(n^2)\)
Code
fun subsequencePairCount(n: IntArray): Long {
val dp = HashMap<Int, Long>(); val M = 1000000007L
fun gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b)
fun f(i: Int, x: Int, y: Int): Long = if (i == n.size)
if (x == y) 1L else 0L else dp.getOrPut(i*40401+x*201+y) {
(f(i+1, gcd(n[i],x), y) + f(i+1, x, gcd(n[i],y)) + f(i+1, x, y)) % M }
return (f(0, 0, 0) - 1 + M) % M
}
pub fn subsequence_pair_count(n: Vec<i32>) -> i32 {
let (mut dp, M) = ([0i64; 201*201], 1_000_000_007); dp[0] = 1;
let g = |mut a: usize, mut b: usize| { while b > 0 {(a,b)=(b,a%b)} a };
for v in n { let mut nxt = dp;
for i in 0..201*201 { if dp[i] > 0 {
let g1 = g(i/201, v as usize) * 201 + i%201;
let g2 = i/201 * 201 + g(i%201, v as usize);
nxt[g1] = (nxt[g1] + dp[i]) % M;
nxt[g2] = (nxt[g2] + dp[i]) % M
}} dp = nxt }
((1..201).map(|i| dp[i * 201 + i]).sum::<i64>() % M) as i32
}
13.07.2026
1291. Sequential Digits medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1419
Problem TLDR
Increasing digit numbers in a range
Intuition
The possible set of numbers is very small. Generate all then filter and sort.
Approach
- iterate over lengths, sliding window over string in an inner loop
Complexity
-
Time complexity: \(O(log^2(n))\)
-
Space complexity: \(O(log^2(n))\)
Code
fun sequentialDigits(l: Int, h: Int) =
(2..9).flatMap{"123456789".windowed(it)}.map{it.toInt()}.filter{it in l..h}
pub fn sequential_digits(l: i32, h: i32) -> Vec<i32> {
(2..10).flat_map(|w|(1..11-w).map(move |x| (x..x+w).fold(0,|r,t|r*10+t)))
.filter(|&x|l<=x&&x<=h).collect()
}
12.07.2026
1331. Rank Transform of an Array easy substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1418
Problem TLDR
Rank of items in an array
Intuition
Sort. Dedup. Binary search each number.
Approach
- we can use toSortedMap().run { … headSet(it).size } but leetcode give TLE, still O(nlogn)
- Rust: use itertools and collect tuples to the hashmap
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(n)\)
Code
fun arrayRankTransform(a: IntArray) =
a.toSet().sorted().run { a.map { binarySearch(it) + 1 } }
pub fn array_rank_transform(a: Vec<i32>) -> Vec<i32> {
let m: HashMap<_,_> = a.iter().copied().sorted().dedup().zip(1..).collect();
a.iter().map(|x| m[x]).collect()
}
11.07.2026
2685. Count the Number of Complete Components medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1417
Problem TLDR
Fully connected components
Intuition
- Union-Find to find connected components
- Count incoming edges for each node
- Fully connected group size is the number of edges for each node +1
Approach
- 50 elements can fit into long variable
- adjacency matrix would look the same for each group
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
fun countCompleteComponents(n: Int, e: Array<IntArray>) = e
.fold(LongArray(n){1L shl it}){ m, (a, b) -> m[a] += 1L shl b; m[b] += 1L shl a; m }
.groupBy { it }.count { (k, v) -> v.size == k.countOneBits() }
6
10.07.2026
3534. Path Existence Queries in a Graph II hard substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1416
Problem TLDR
Queries of connected nodes shortest distances
Intuition
Didn’t solved.
// 1 1 1 1 1 1 1 1 1 1 1 from every node to every node dist = 1
// 1 2 . 4 5 6 7 8 9 md=2
// * * .
// 1 1 .
// * . *
// 2 1 . 0
// . * *
// 2 2 . 1 0
// . * * *
// 2 2 . 1 1 0
// 3 2 . 2 1 1 0
// 3 3 . 2 2 1 1 0
// 3 3 . 2 2 2 1 1 0
// 4 3 . 3 2 2 2 1 1 0
// ^
// can be removed, distances stay the same
// so the distance is (a-b)/md
// 1 hr mark: wrong answer: 91, 92, 127, 173, 179, 182 md=51, 91-182 my 2, correct 3
// so this simple formula doesnt work
// 182-91=91; 91/51 = 2
// but 91+51 = 142, so we go to 127
// 127+51 = 178, we have to go to 173
// 173+51=200+ we arrive at 182 at 3 steps
// that means for each number we should track next reachable
// or do dp[current_position][steps_required]=reachable_position
// but this is O(n^2), so let's give up
// hints: binary jumping (?)
- sort the numbers
- use sliding window to find the rightmost jump for every cell: left goest +1, right goes until diff is bigger than max
- prepare binary lifting jump table: u[k][x] = u[k-1][Y] where Y = u[k-1][x]; for each x we prepare all 2^k (0..31) jumps by reusing previous;
- in query: find the left ‘c’ pointer and the right ‘t’ pointer positions
- by moving the left ‘c’ pointer with jump table count the jumps st += 2^k if it is not overshoot the right ‘t’ pointer u[k][c]<t
Approach
- learn the binary lifting
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(n)\)
Code
fun pathExistenceQueries(n: Int, ns: IntArray, md: Int, qs: Array<IntArray>)=run{
val s = ns.sorted(); val u = Array(18){IntArray(n)}; var r = 0
for (l in 0..<n) { while (r+1<n && s[r+1]-s[l]<=md)++r; u[0][l]=r}
for (k in 1..17) for (x in 0..<n) u[k][x] = u[k-1][u[k-1][x]]
qs.map {(a,b) -> if (a==b)return@map 0
var c = s.binarySearch(min(ns[a],ns[b])); val t = s.binarySearch(max(ns[a],ns[b]))
if (u[17][c]<t) return@map -1; var st = 1
for (k in 17 downTo 0) if (u[k][c]<t) {c = u[k][c]; st += 1 shl k }; st
}
}
09.07.2026
3532. Path Existence Queries in a Graph I medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1415
Problem TLDR
Queries of connected nodes
Intuition
- build a Union-Find, iterate once, connect consequent numbers
Approach
- we can reuse the nums array
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
fun pathExistenceQueries(n: Int, ns: IntArray, md: Int, qs: Array<IntArray>) = run {
ns.reduceIndexed { i, p, c -> c.also { if (c - p <= md) ns[i] = ns[i-1] } }
qs.map { (a,b) -> ns[a]==ns[b] }
}
pub fn path_existence_queries(n: i32, mut ns: Vec<i32>, md: i32, qs: Vec<Vec<i32>>) -> Vec<bool> {
let mut p = ns[0]; for i in 1..ns.len() { let n = ns[i]; if n - p <= md { ns[i] = ns[i-1]}; p = n }
qs.iter().map(|q|ns[q[0] as usize]==ns[q[1] as usize]).collect()
}
08.07.2026
3756. Concatenate Non-Zero Digits and Multiply by Sum II medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1414
Problem TLDR
Queries of sum digits * concat digits
Intuition
// prefix power?
// 1 a
// 123 b
// l r
// 23
// 1 (*100?) (could be * 10^10^5)
// b - a * 10^(r-l), should it be modPow?
Separate prefix sums and prefix powers. Track prefix lengths.
Approach
- use longs to avoid overflow on multiplications
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
fun sumAndMultiply(S: String, q: Array<IntArray>) = (S.length+1).let {
val M = 1_000_000_007L; val x = LongArray(it); val w = IntArray(it)
val s = LongArray(it); val p = LongArray(it){1}
S.forEachIndexed { i, c ->
x[i+1] = if (c > '0') (x[i] * 10 + (c-'0')) % M else x[i]
s[i+1] = s[i] + (c-'0'); w[i+1] = w[i] + (c-'0').sign; p[i+1] = p[i]*10%M
}
q.map {(l,r)->(x[r+1] - x[l] * p[w[r+1]-w[l]] % M + M) % M * (s[r+1]-s[l]) % M}
}
pub fn sum_and_multiply(s: String, q: Vec<Vec<i32>>) -> Vec<i32> {
let m = 1_000_000_007i64; let mut v = vec![(0, 0, 0, 1)];
for d in s.bytes().map(|b| (b - 48) as i64) {
let &(px, pw, pa, pp) = v.last().unwrap();
v.push((if d > 0 {(px*10+d)%m} else {px}, pw+(d>0) as usize, pa+d, pp*10%m));
}
q.iter().map(|q| {
let (l, r) = (v[q[0] as usize], v[q[1] as usize + 1]); let pw = v[r.1-l.1].3;
((r.0 + m - l.0 * pw % m) % m * (r.2 - l.2) % m) as i32
}).collect()
}
07.07.2026
3754. Concatenate Non-Zero Digits and Multiply by Sum I easy substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1413
Problem TLDR
Sum digits * concat digits
Intuition
Sum them and concat them with strings. Or go from tail with match.
Approach
- can be done in two phases for shorter code
Complexity
-
Time complexity: \(O(logn)\)
-
Space complexity: \(O(logn)\)
Code
fun sumAndMultiply(n: Int) =
("0"+"$n".filter{it>'0'}).toLong()*"$n".sumOf{it-'0'}
pub fn sum_and_multiply(mut n: i32) -> i64 {
let(mut v,mut s,mut m)=(0,0,1);
while n>0{let d=(n%10)as i64;s+=d;if d>0{v+=d*m;m*=10}n/=10}v*s
}
06.07.2026
1288. Remove Covered Intervals medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1412
Problem TLDR
Count non intersecting intervals
Intuition
Sort by (left, - right) to take more spread intervals first and skip others.
Approach
- can be a single key a*max-b
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(1)\)
Code
fun removeCoveredIntervals(iv: Array<IntArray>)= run {
var m = 0; iv.sortedWith(compareBy({it[0]},{-it[1]}))
.count { (l,r) -> r > m.also { m = max(m, r) } }
}
pub fn remove_covered_intervals(mut iv: Vec<Vec<i32>>) -> i32 {
iv.sort_by_key(|i|(i[0],-i[1]));
iv.iter().fold((0,0),|(c,m),i|(c+(i[1]>m)as i32,m.max(i[1]))).0
}
05.07.2026
1301. Number of Paths with Max Score hard substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1411
Problem TLDR
Count maximal paths
Intuition
Use Dp = answer for the current cell
Approach
- use size+1 to avoid ‘if’ checks
- we can use just previous & current row for dp to make space O(n)
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n^2)\)
Code
fun pathsWithMaxScore(b: List<String>): IntArray {
val n = b.size-1; val d = List(n+2){Array(n+2){intArrayOf(0,0)}}; d[n][n][1] = 1
for (y in n downTo 0) for (x in n downTo 0) if (b[y][x] !in "XS") {
val l = listOf(d[y][x+1], d[y+1][x], d[y+1][x+1]); val m = l.maxOf { it[0] }
val c = l.filter { it[0] == m }.fold(0) { r, i -> (r + i[1]) % 1000000007 }
if (c > 0) d[y][x] = intArrayOf(m + if (b[y][x]=='E') 0 else b[y][x] - '0', c)
}
return d[0][0]
}
pub fn paths_with_max_score(b: Vec<String>) -> Vec<i32> {
let n = b.len(); let mut p = [[0; 2]; 102]; p[n][1] = 1;
for y in (0..n).rev() { let mut c = [[0; 2]; 102]; for x in (0..n).rev() {
let v = b[y].as_bytes()[x]; if v == 88 { continue }
let m = c[x + 1][0].max(p[x][0]).max(p[x + 1][0]);
let k = [c[x+1], p[x], p[x+1]].iter().filter(|i|i[0]==m).fold(0,|r,i|(r+i[1])%1000000007);
if k > 0 { c[x] = [m + if v > 60 { 0 } else { (v - 48) as i32 }, k]; }
} p = c } p[0].into()
}
04.07.2026
2492. Minimum Score of a Path Between Two Cities medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1410
Problem TLDR
Min in connected edges
Intuition
Use Union-Find to find the connected group.
Approach
- uf path compression: u[x]=f(u[x]) is enough speed up
- don’t forget to initialize with own indices u = 1..n
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
fun minScore(n: Int, r: Array<IntArray>): Int {
val u = IntArray(n+1){it}
fun f(x: Int): Int = if (x==u[x])x else {u[x]=f(u[x]);u[x]}
for ((a,b) in r) u[f(a)] = f(b)
return r.minOf{(a,b,d) -> if (f(a)==f(1)) d else 999999}
}
pub fn min_score(n: i32, r: Vec<Vec<i32>>) -> i32 {
let mut u: Vec<_> = (0..=n as usize).collect();
let mut f = |x: i32, u: &mut [usize]| {
let mut x = x as usize; while u[x] != x { u[x] = u[u[x]]; x = u[x] }; x };
for e in &r { let (a,b) = (f(e[0], &mut u), f(e[1], &mut u)); u[a] = b }
r.iter().filter(|e| f(e[0], &mut u) == f(1, &mut u)).map(|e| e[2]).min().unwrap()
}
03.07.2026
3620. Network Recovery Pathways hard substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1409
Problem TLDR
Max(min(paths)) in DAG
Intuition
Didn’t solve.
// got hint from the start: binary search + dijkstra
// 16 minute MLE 630/637
// 20 minute wrong answer 631/637
// 23 minute TLE 632/637
// 35 minute: no idea how to improve time - hint: prune graph on each bs step
// still TLE
// 43 minute: give up, my dijkstra TLEs
- binary search an answer
- use Dijkstra
Approach
- take nodes with smallest paths sum first, skip node if it was imporved, keep track in a separate array
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(nlogn)\)
Code
fun findMaxPathScore(e: Array<IntArray>, o: BooleanArray, k: Long): Int {
var l = 0; var h = Int.MAX_VALUE; val g = Array(o.size) { ArrayList<Long>() }
for ((a, b, c) in e) if (o[a] && o[b]) g[a] += (1L*c shl 32) + b
s@ while (l <= h) {
val m = l + (h - l) / 2; val d = LongArray(o.size) { Long.MAX_VALUE }; d[0] = 0
val q = PriorityQueue<LongArray>(compareBy { it[0] }); q += longArrayOf(0, 0)
while (q.size > 0) {
val (S, X) = q.poll(); val x = X.toInt(); if (x == o.size - 1) { l = m + 1; continue@s }
if (S <= d[x]) for (E in g[x]) {
val cst = E shr 32; val y = E.toInt(); val S2 = S + cst
if (cst >= m && S2 <= k && S2 < d[y]) { d[y]=S2; q += longArrayOf(S2, y.toLong())}
}
}
h = m - 1
}
return h
}
pub fn find_max_path_score(e: Vec<Vec<i32>>, o: Vec<bool>, k: i64) -> i32 {
let (mut l, mut h, n) = (0, i32::MAX, o.len()); let mut g = vec![vec![]; n];
for v in e { if o[v[0] as usize] & o[v[1] as usize] { g[v[0] as usize].push(((v[2] as u64)<<32)|v[1] as u64) } }
while l <= h {
let (m, mut d, mut q, mut ok) = (l+(h-l)/2, vec![i64::MAX; n], BinaryHeap::from([(0,0)]), false); d[0]=0;
while let Some((s, x)) = q.pop() {
let (s, x) = (-s, x as usize); if x == n-1 { ok=true; break }
if s <= d[x] { for &E in &g[x] {
let (c, y) = ((E>>32) as i64, E as u32 as usize); let s2 = s+c;
if c >= m as i64 && s2 <= k && s2 < d[y] { d[y]=s2; q.push((-s2, y as u64)) }
}}
}
if ok { l=m+1 } else { h=m-1 }
} h
}
02.07.2026
3286. Find a Safe Walk Through a Grid medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1408
Problem TLDR
Path to bottom-right with health points
Intuition
- use BFS, put health with coordinates, prioritize the max health first with PriorityQueue
- another way is 0-1 BFS: explore free cells first by putting the in front of the queue
- track the max health for each visited cell to allow for re-enter
Approach
- Rust: use !0 instead of -1 as dx/dy
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n^2)\)
Code
fun findSafeWalk(g: List<List<Int>>, h: Int): Boolean {
val q=ArrayDeque(setOf(0 to 0));val v=Array(g.size){IntArray(g[0].size)}; v[0][0]=h-g[0][0]
while (q.size>0) {
val (x, y) = q.removeFirst(); if (y == g.size - 1 && x == g[0].size - 1) return true
for ((X, Y) in setOf(x - 1 to y, x + 1 to y, x to y - 1, x to y + 1))
if (Y in g.indices && X in g[0].indices && v[y][x] - g[Y][X] > v[Y][X]) {
v[Y][X] = v[y][x]-g[Y][X]
if (g[Y][X] == 0) q.addFirst(X to Y) else q += X to Y
}
}
return false
}
pub fn find_safe_walk(g: Vec<Vec<i32>>, h: i32) -> bool {
let (R, C) = (g.len(), g[0].len());
let mut v = vec![vec![0; C]; R]; v[0][0] = h - g[0][0];
let mut q = VecDeque::from([(0, 0, v[0][0])]);
while let Some((x, y, h)) = q.pop_front() {
if h > 0 && x == R - 1 && y == C - 1 { return true }
for (dx, dy) in [(0,1), (1,0), (0,!0), (!0,0)] {
let (X, Y) = (x.wrapping_add(dx), y.wrapping_add(dy));
if X < R && Y < C && h - g[X][Y] > v[X][Y] {
v[X][Y] = h - g[X][Y]; let a = (X, Y, v[X][Y]);
if g[X][Y] == 0 { q.push_front(a) } else { q.push_back(a) }
}
}
} false
}
01.07.2026
2812. Find the Safest Path in a Grid medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1407
Problem TLDR
Safest path from ones
Intuition
BFS from all ones to mark cells safety. Second BFS to find safest path with PriorityQueue
Approach
- we can reuse PriorityQueue (but it costs)
- we can use the grid as a storage
Complexity
-
Time complexity: \(O(n^2logn)\)
-
Space complexity: \(O(n^2)\)
Code
fun maximumSafenessFactor(G: List<List<Int>>): Int {
val n = G.size; val q = PriorityQueue<IntArray> { a, b -> b[0] - a[0] }
val g = Array(n) { IntArray(n) { -1 } }; var p = 0
for (y in 0..<n) for (x in 0..<n) if (G[y][x] > 0) q += intArrayOf(0, x, y)
while (p < 2) {
if (q.isEmpty()) { p++; q += intArrayOf(g[0][0], 0, 0); g[0][0] = -1; continue }
val (s, x, y) = q.poll()
if (p == 0) {
if (g[y][x] < 0) { g[y][x] = -s; for (k in 0..3) { val X=x+(k%2)*(k-2); val Y=y+(1-k%2)*(k-1)
if (X in 0..<n && Y in 0..<n) q += intArrayOf(s - 1, X, Y) } }
} else if (x == n - 1 && y == n - 1) return s
else for (k in 0..3) { val X=x+(k%2)*(k-2); val Y=y+(1-k%2)*(k-1)
if (X in 0..<n && Y in 0..<n && g[Y][X]>=0) { q += intArrayOf(min(s,g[Y][X]),X,Y); g[Y][X]=-1}}
}
return 0
}
pub fn maximum_safeness_factor(mut g: Vec<Vec<i32>>) -> i32 {
let (n, mut q, mut h) = (g.len(), VecDeque::new(), BinaryHeap::new());
for y in 0..n { for x in 0..n { if g[y][x] > 0 { q.push_back((y, x)) } } }
while let Some((y, x)) = q.pop_front() { for (a, b) in [(1,0),(!0,0),(0,1),(0,!0)] {
let (y2, x2) = (y.wrapping_add(a), x.wrapping_add(b));
if y2 < n && x2 < n && g[y2][x2] < 1 { g[y2][x2] = g[y][x] + 1; q.push_back((y2, x2)) }
}}
h.push((g[0][0], 0, 0)); g[0][0] *= -1;
while let Some((f, y, x)) = h.pop() { if y == n - 1 && x == n - 1 { return f - 1 } for (a, b) in [(1,0),(!0,0),(0,1),(0,!0)] {
let (y, x) = (y.wrapping_add(a), x.wrapping_add(b));
if y < n && x < n && g[y][x] > 0 { h.push((f.min(g[y][x]), y, x)); g[y][x] *= -1 }
}}
-1
}
30.06.2026
1358. Number of Substrings Containing All Three Characters medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1406
Problem TLDR
Substrings with 3 letters
Intuition
Sum of substrings ending at position i. Count all prefixes.
Approach
- just remember the latest position of each letter, the min would be the prefix
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
fun numberOfSubstrings(s: String) = IntArray(3).run {
s.indices.sumOf { i -> set(s[i]-'a', i+1); min() }
}
pub fn number_of_substrings(s: String) -> i32 {
s.bytes().zip(1..).fold(([0;3],0),|(mut j,mut s),(b,i)|{
j[b as usize%3]=i;(j,s+j[0].min(j[1]).min(j[2]))}).1
}
29.06.2026
1967. Number of Strings That Appear as Substrings in Word easy substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1405
Problem TLDR
N patterns in a word
Intuition
Brute-force.
Approach
- an optimal solutin exists, just ask your ai
Complexity
-
Time complexity: \(O(nw)\)
-
Space complexity: \(O(1)\)
Code
fun numOfStrings(p: Array<String>, w: String) =
p.count { it in w }
pub fn num_of_strings(p: Vec<String>, w: String) -> i32 {
p.iter().filter(|&p|w.contains(p)).count() as _
}
28.06.2026
1846. Maximum Element After Decreasing and Rearranging medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1404
Problem TLDR
Max possible grow of +0 or +1
Intuition
Sort. Iterate. Take at most prev + 1.
Approach
- can it be solved in O(n)? yes, count sort, the max value is the arr.size
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(1)\)
Code
fun maximumElementAfterDecrementingAndRearranging(a: IntArray) =
a.sorted().fold(0) { r, t -> min(r+1,t) }
pub fn maximum_element_after_decrementing_and_rearranging(a: Vec<i32>) -> i32 {
a.into_iter().sorted().fold(0,|r,t|t.min(r+1))
}
27.06.2026
3020. Find the Maximum Number of Elements in Subset medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1403
Problem TLDR
Powers of two symmetrical exponentially growing longest sequence length
Intuition
// the base can be anything, not just 2
Compute frequencies. The length of the sequence is very small, just check every number if it has continuation by brute force, do +2 at every step, frequencey should be at least 2.
Approach
- ones 1111 is the corner case, and it can be odd or even
Complexity
-
Time complexity: \(O(nlog(log(max)))\)
-
Space complexity: \(O(n)\)
Code
fun maximumLength(n: IntArray) = n.groupBy{1L*it}.run {
max((get(1)?.size?:0).let{it-1+it%2},
(keys-1).maxOfOrNull { x ->
var (n,c) = x to 0
while ((get(n)?.size?:0)>1) { c += 2; n *= n}
c + if (n in this) 1 else -1
}?:1 ) }
pub fn maximum_length(n: Vec<i32>) -> i32 {
let mut f = HashMap::new();
for x in n { *f.entry(x as i64).or_default() += 1 }
let o = f.remove(&1).unwrap_or(0);
f.keys().fold(1.max(o - 1 | 1), |r, &k| {
let (mut x, mut c) = (k, 0);
while f.get(&x) > Some(&1) { c += 2; x *= x }
r.max(c + (f.get(&x) > None) as i32 * 2 - 1)
})
}
26.06.2026
3739. Count Subarrays With Majority Element II hard substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1402
Problem TLDR
Subarrays with majority element
Intuition
Didn’t solve.
// 1 2 2 3 2
//-1 1 1-1 f[0]=1
//-1 b=-1 f[-1]=1
// 1 b=0 good f[0]=2 how many prefix sums are bigger than -b (lower than b)
// 1 b=1 good f[1]=1 actually: how many running sums with exact -b value
//// -1 b=0 good f[0]=3 plus ongoing positive streak -- doesnt work
- convert to the balance -1 +1 sequence b = running sum of this
- keep track of balances frequencies f[b]
- f[curr_b] - b[j] is the subarray balance, it should be positive if we want majority
- so for the f[curr_b] we want to know how many j balances we visited with lesser f[j]
- we can use TreeMap/SegmentTree for that
- for O(n) track the lesser-balance i points count in a single variable c
- if balance grows +1, the lesser count is previous lesser count plus exact f[b] of the previous b
- if balance shrinks -1, the lesser count is the previous lesser count minus new smaller b, f[b-1]
Approach
- don’t forget sentinel start of the prefix sum
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
fun countMajoritySubarrays(n: IntArray, t: Int): Long {
val f = HashMap<Int, Int>(); var b = 0; var c = 0L; f[0] = 1
return n.sumOf { x ->
if (x == t) c += f[b++] ?: 0 else c -= f[--b] ?: 0
f[b] = 1 + (f[b] ?: 0); c
}
}
pub fn count_majority_subarrays(n: Vec<i32>, t: i32) -> i64 {
let (mut f,mut b, mut c) = (vec![0; n.len()*2+2],0,0); f[n.len()] = 1;
n.iter().map(|&x| {
if x == t { c += f[b+n.len()]; b += 1 } else { b -=1; c -= f[b+n.len()] }
f[b + n.len()] += 1; c
}).sum()
}
25.06.2026
3737. Count Subarrays With Majority Element I medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1401
Problem TLDR
Subarrays with majority element
Intuition
The problem space is small 1000, O(n^2) is accepted
Approach
- in the inner loop calculate a running sum
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(1)\)
Code
fun countMajoritySubarrays(n: IntArray, t: Int) = n
.indices.sumOf { i -> var c = 0
(i downTo 0).count { j -> if (n[j]==t) c++; c > (i-j+1)/2 }
}
pub fn count_majority_subarrays(n: Vec<i32>, t: i32) -> i32 {
(0..n.len()).map(|i|{ let mut c = 0;
(0..=i).rev().filter(|&j| {
if n[j] == t { c += 1 }; c*2 > i-j+1
}).count() as i32
}).sum()
}
24.06.2026
3700. Number of ZigZag Arrays II hard substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1400
Problem TLDR
Ways to make l..r zigzag sequence
Intuition
Didn’t solve. Make a transition matrix that depends only on the prvious step: up-up/down-down are disabled, up-down and down-up are enabled (look youtube video). The dp[l..r goes up, l..r goes down] = [1 1 1 1 1 1.. 1 1 1]is the number of ways. Multiplay by transition matrix n times to get total number of ways for each cell+direction. Sum all the counts.
Approach
- the trick here is to encode the directions in a one big transition matrix [u-u u-d / d-u d-d]
Complexity
-
Time complexity: \(O(rlogn)\)
-
Space complexity: \(O(r)\)
Code
fun zigZagArrays(sz: Int, l: Int, r: Int): Int {
val M = 1000000007; val m = r - l + 1; val S = 2 * m
var b = LongArray(S * S); var dp = LongArray(S) { 1L }; var p = sz - 1L
for (i in 0..<m) for (j in 0..<m)
if (j < i) b[i * S + j + m] = 1L else if (j > i) b[(i + m) * S + j] = 1L
while (p > 0) {
if (p % 2 == 1L) dp = LongArray(S).also { nDp ->
for (i in 0..<S) if (dp[i] > 0) for (j in 0..<S)
nDp[j] = (nDp[j] + dp[i] * b[i * S + j]) % M
}
b = LongArray(S * S).also { nB ->
for (i in 0..<S) for (k in 0..<S) if (b[i * S + k] > 0) for (j in 0..<S)
nB[i * S + j] = (nB[i * S + j] + b[i * S + k] * b[k * S + j]) % M
}
p /= 2
}
return (dp.sum() % M).toInt()
}
23.06.2026
3699. Number of ZigZag Arrays I hard substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1399
Problem TLDR
Ways to make l..r zigzag sequence
Intuition
Didn’t solve.
// 15 minute: TLE, O(n^3), hint: prefix sums?
// f(i, p, 1) = f(i+1, l, 2) + f(i+1, l+1, 2) + ... f(i+1, p-1, 2)
// f(i, p, 2) = f(i+1, p+1, 1) + f(i+1, p+2, 1)+...+f(i+1,r,1)
// f(i+1, l, 2) = f(i+2, l+1, 1) + f(i+2, l+2, 1) + ... f(i+2, p-1, 1)
// f(i+1, p+1, 1) = f(i+2, l, 2) + f(i+2, l+1, 2)+...+f(i+2,p,2)
// 28 minute: give up
//
// f(i,p,1) = sum{k=l..p-1}(f(i+1,k,2))
// f(i,p-1,1) = sum{k=l..p-2}(f(i+1,k,2))
// f(i,p,1)-f(i,p-1,1)=f(i+1,p-1,2)
// f(i,p,1)=f(i,p-1,1)+f(i+1,p-1,2)
// f(i,p,2)=f(i,p+1,2)+f(i+1,p+1,1)
Top down O(n^2) can be derived (see above), but still gives TLE. Bottom up: 1) move range to 0..r-l 2) use symmetry *2 3) dp[v] is the number of arrays ending with value v 4) dp[v]=sum(dp[0..v]) odd and sum(dp[v..r-l]) even 5) the sum(dp[..]) is just a running sum variable
Approach
- not sure if I could solve this or similar next time, the jump to bottom up is not obvious
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n)\)
Code
fun zigZagArrays(n: Int, l: Int, r: Int): Int {
val r = r-l; val M = 1000000007; val dp = IntArray(r+1){1}
for (i in 1..<n) {
var pre = 0
for (v in if (i%2>0) 0..r else r downTo 0)
{ val pre2 = pre + dp[v]; dp[v] = pre; pre = pre2%M }
}
return dp.fold(0){r,t->(r+t)%M}*2%M
}
pub fn zig_zag_arrays(n: i32, l: i32, r: i32) -> i32 {
let r = (r-l+1) as usize; let M = 1000000007; let mut dp = vec![1;r];
for i in 1..n {
let mut s = 0;
if i & 1 > 0 { for v in 0..r { s=(s+replace(&mut dp[v],s))%M} }
else { for v in (0..r).rev() { s=(s+replace(&mut dp[v],s))%M} }
}
(dp.iter().fold(0, |s, &t| (s+t)%M)*2%M) as _
}
22.06.2026
1189. Maximum Number of Balloons easy substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1398
Problem TLDR
Count “balloon”s in stirng
Intuition
Calculate the frequency; Divide the frequency of ‘l’ and ‘o’ by 2.
Approach
- we can iterate 5 times
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
fun maxNumberOfBalloons(t: String) =
(0..4).minOf {t.count{c->c=="balon"[it]}/(it/2%2+1)}
pub fn max_number_of_balloons(t: String) -> i32 {
"balon".chars().map(|c|
t.matches(c).count()/((c=='l'||c=='o')as usize+1)).min().unwrap() as _
}
21.06.2026
1833. Maximum Ice Cream Bars medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1397
Problem TLDR
Max count by given coins
Intuition
Maintain the frequency array. Calculate count by dividing total couns by price. Subtract count * price.
Approach
- pre-calculate the max
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
fun maxIceCream(c: IntArray, k: Int) = run {
val s = c.groupBy{it}; var k = k
(1..c.max()).sumOf {i->min(s[i]?.size?:0, k/i).also{k -= it*i}}
}
pub fn max_ice_cream(c: Vec<i32>, mut k: i32) -> i32 {
let m=*c.iter().max().unwrap();let mut s=vec![0;m as usize+1];
for x in c{s[x as usize]+=1}
(1..=m).map(|i|{let r=s[i as usize].min(k/i);k-=r*i;r}).sum()
}
20.06.2026
1840. Maximum Building Height hard substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1396
Problem TLDR
Max growing height with restrictions
Intuition
// 123456789 10 11
// 123456543 21
// 1 6 3
// 1 2 3 4 5 6 7 8 9 10
// 0 5 3 4 3
//
// some restriction in the middle can backtrack
//
// 30 minutes, hints: two passes
// 48 minute: my formula is wrong
// 56 minute: give up
- adjust restrictions with forward anb backward passes
- for each restriction interval the max height = (L+R+d)/2, solve 2D geometry
Approach
- on backward pass we already can calculte the max
- we can use ‘previous’ height and solve in O(1) memory, or use helper collection with 0 and n-th positions
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(n|1)\)
Code
fun maxBuilding(n: Int, r: Array<IntArray>): Int {
r.sortBy { it[0] }; val l = arrayOf(intArrayOf(1, 0)) + r + intArrayOf(n, n - 1)
for (k in 1..l.lastIndex) l[k][1] = min(l[k][1], l[k-1][1] + l[k][0] - l[k-1][0])
return (l.lastIndex downTo 1).maxOf { k ->
val (i, h) = l[k]; val (j, p) = l[k-1]; l[k-1][1] = minOf(p, h + i - j)
(i - j + h + l[k-1][1]) / 2
}
}
pub fn max_building(n: i32, mut r: Vec<Vec<i32>>) -> i32 {
r.sort(); let mut l = [vec![vec![1, 0]], r, vec![vec![n, n - 1]]].concat();
for k in 1..l.len() { l[k][1] = l[k][1].min(l[k-1][1] + l[k][0] - l[k-1][0]); }
(1..l.len()).rev().fold(0, |res, k| {
let (i, h, j, p) = (l[k][0], l[k][1], l[k-1][0], l[k-1][1]);
l[k-1][1] = p.min(h + i - j);
res.max((i - j + h + l[k-1][1]) / 2)
})
}
19.06.2026
1732. Find the Highest Altitude easy substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1395
Problem TLDR
Max running sum
Intuition
Simulate. Take max.
Approach
- Kotlin: scan, Int::plus
- Rust: fold
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1|n)\)
Code
fun largestAltitude(g: IntArray) =
g.scan(0, Int::plus).max()
pub fn largest_altitude(g: Vec<i32>) -> i32 {
g.iter().fold((0,0), |(r,h), x| (r.max(h+x), h+x)).0
}
18.06.2026
1344. Angle Between Hands of a Clock medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1394
Problem TLDR
Angle between clock arrows
Intuition
- 360 degrees full circle
- 360/60=6 degrees one hour
- h*60+m total minutes M
- 5.5*M%360 periodic angle between hands of a clock
Approach
- Rust: successors
Complexity
-
Time complexity: \(O(1)\)
-
Space complexity: \(O(1)\)
Code
fun angleClock(h: Int, m: Int) =
180-abs(abs(h*30-5.5*m)-180)
pub fn angle_clock(h: i32, m: i32) -> f64 {
successors(Some(0.0f64),|a|Some((a+5.5)%360.))
.nth((h*60+m)as usize %720).map(|a|a.min(360.-a)).unwrap()
}
17.06.2026
3614. Process String with Special Operations II hard substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1393
Problem TLDR
K-th char ina pattern-build a string, %-reverse, #-repeat, *-pop
Intuition
// cd%#*# k=3
// dc
// dcdc
// dcd
// dcddcd len=6
// ...k
// # len=3 k=0
// dcd
// k
// * len=4
// dcd*
// # len=2 k=0
// dc
//
Simulate the rules to find the length. Reverse operations: * adds to length, # halfs length and trims K-length, % reverses k = len-1-k
Approach
- corner cases: k >= length, max(0, len-1)
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
fun processStr(s: String, k: Long): Char {
var l = s.fold(0L) {r,c->when(c){'*'->max(0L,r-1);'%'->r;'#'->r+r;else->r+1}}
var k = k
if (k < l) for (c in s.reversed()) when (c) {
'*' -> l++; '%' -> k = l - 1 - k; '#' -> { l /= 2; k %= l }
else -> if (k == --l) return c
}
return '.'
}
pub fn process_str(s: String, mut k: i64) -> char {
let mut l=s.chars().fold(0,|r,c|match c{'*'=>(r-1).max(0),'%'=>r,'#'=>r+r,_=>r+1});
if k < l { for c in s.chars().rev() { match c {
'*' => l += 1, '%' => k = l - 1 - k, '#' => { l /= 2; k %= l }
_ => { l -= 1; if k == l { return c } }
} } } '.'
}
16.06.2026
3612. Process String with Special Operations I medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1392
Problem TLDR
Pattern-build a string, %-reverse, #-repeat, *-pop
Intuition
Just simulate the rules. In a worst case we would have 2^n time/space complexity if every letter would be c#..#
Approach
- we can use fold
- Rust has
extend_from_within(0..)
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n)\)
Code
fun processStr(s: String) = s.fold("") { r, c ->
when (c) {
'*' -> r.dropLast(1); '%' -> r.reversed()
'#' -> r + r; else -> r + c
}
}
pub fn process_str(s: String) -> String {
let mut res = vec![];
for b in s.bytes() { match b {
b'*' => {res.pop();}, b'%' => res.reverse(),
b'#' => res.extend_from_within(0..), _ => res.push(b)
}}
String::from_utf8(res).unwrap()
}
15.06.2026
2095. Delete the Middle Node of a Linked List medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1391
Problem TLDR
Remove the middle of Linked LIst
Intuition
- fast & slow pointer
- count, then walk again
Approach
- Rust: fast & slow can be done with unsafe + raw pointers
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
fun deleteMiddle(h: ListNode?) = run {
val d = ListNode(0).apply{next = h}
var s: ListNode? = d; var f = h
while(f?.next!=null){s = s?.next;f=f?.next?.next}
s?.next = s?.next?.next; d.next
}
pub fn delete_middle(mut h: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
let mut cnt = 0; let mut s = &h;
while let Some(n) = &s { s = &n.next; cnt += 1 }
if cnt <= 1 { return None } let mut s = &mut h;
for i in 0..cnt/2-1 { s = &mut s.as_mut().unwrap().next }
let mid = s.as_mut().unwrap().next.take();
s.as_mut().unwrap().next = mid.and_then(|mut n| n.next.take());
h
}
14.06.2026
2130. Maximum Twin Sum of a Linked List medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1390
Problem TLDR
Max sum pairwise from tail
Intuition
Put into a list or revert the first half.
Approach
- Kotlin: generateSequence
- Rust: from_fn
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n|1)\)
Code
fun pairSum(h: ListNode?) =
generateSequence(h){it.next}.map{it.`val`}
.toList().run {zip(reversed(), Int::plus).max()}
pub fn pair_sum(mut h: Option<Box<ListNode>>) -> i32 {
let l: Vec<_> = from_fn(||h.take().map(|n|{h=n.next; n.val})).collect();
l.iter().rev().zip(&l).map(|(a,b)|a+b).max().unwrap()
}
13.06.2026
3838. Weighted Word Mapping easy substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1389
Problem TLDR
Convert words to chars by weighting their sums and reversing
Intuition
brute-force
Approach
- reverse by
z-c
Complexity
-
Time complexity: \(O(nw)\)
-
Space complexity: \(O(n)\)
Code
fun mapWordWeights(w: Array<String>, ws: IntArray) =
w.joinToString(""){""+('z'-it.sumOf{ws[it-'a']}%26)}
pub fn map_word_weights(w: Vec<String>, ws: Vec<i32>) -> String {
w.iter().map(|s|(122-s.bytes().fold(0,|a,c|a+ws[(c-97)as usize])%26)as u8 as char).collect()
}
12.06.2026
3559. Number of Ways to Assign Edge Weights II hard substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1388
Problem TLDR
Ways to color the all queries paths a..b in tree
Intuition
Didn’t solved myself
// how to know path from each to each in less than O(n^2)?
// use hints: LCA, DP of parity
// TLE, probably because of my LCA
- construct the tree
- DFS: mark time for enter / exit for each node, later use to compare times to check for ancestor
- BFS: track depth of each node, later go to parent until depth is smaller
- the number of two-color the path is 2^len
- binary lifting: go up by powers of two jumps, this allows to precompute up[x][i]=up[up[x][i-1]][i-1], because i-1 is a half-jump https://cp-algorithms.com/graph/lca_binary_lifting.html
Approach
- don’t forget to precompute powers of two
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(nlogn)\)
Code
fun assignEdgeWeights(e: Array<IntArray>, q: Array<IntArray>) = run {
var t=0; val n=e.size+2; val inT=IntArray(n); val d=IntArray(n)
val p=(1..n).runningFold(1L){ r,_->(r*2)%1000000007L }
val out = IntArray(n); out[0]=9999999; val up=Array(n){ IntArray(20){1} }
val g=e.flatMap{(a,b)->setOf(a to b,b to a)}.groupBy({it.first},{it.second})
fun anc(a:Int, b:Int) = inT[a]<=inT[b] && out[a]>=out[b]
fun dfs(x:Int, p:Int) {
inT[x]=++t; up[x][0]=p; for(i in 1..19) up[x][i] = up[up[x][i-1]][i-1]
g[x]?.forEach{ if(it!=p) { d[it]=d[x]+1; dfs(it,x) } }; out[x]=++t
}
dfs(1,0); q.map { (a, b) ->
var v=a; for(i in 19 downTo 0) if(!anc(up[v][i],b)) v=up[v][i]
val x = if(anc(a,b)) a else if(anc(b,a)) b else up[v][0]
val l = d[a]+d[b] - 2*d[x]; if(l==0) 0L else p[l-1]
}
}
pub fn assign_edge_weights(e: Vec<Vec<i32>>, q: Vec<Vec<i32>>) -> Vec<i32> {
let n = e.len() + 2; let mut p = vec![1; n];
for i in 1..n { p[i] = p[i-1] * 2 % 1000000007; }
let (mut d, mut up) = (vec![0; n], vec![[1; 20]; n]);
let g = e.iter().flat_map(|v| { let (a,b)=(v[0]as usize,v[1]as usize); [(a, b), (b, a)] }).into_group_map();
let (mut bfs, mut i) = (vec![1], 0);
while i < bfs.len() {
let x = bfs[i]; i += 1;
for j in 1..20 { up[x][j] = up[up[x][j-1]][j-1]; }
for &v in &g[&x] { if v != up[x][0] { d[v]=d[x]+1; up[v][0]=x; bfs.push(v); } }
}
q.iter().map(|v| {
let (mut a, mut b) = (v[0] as usize, v[1] as usize);
let (da, db) = (d[a], d[b]);
if d[a] < d[b] { std::mem::swap(&mut a, &mut b); }
for j in 0..20 { if ((d[a] - d[b]) >> j) & 1 == 1 { a = up[a][j]; } }
let x = if a == b { a } else {
for j in (0..20).rev() { if up[a][j] != up[b][j] { a=up[a][j]; b=up[b][j]; } }
up[a][0]
};
let l = da + db - 2 * d[x]; if l == 0 { 0 } else { p[l - 1] }
}).collect()
}
11.06.2026
3558. Number of Ways to Assign Edge Weights I medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1387
Problem TLDR
Ways to color the deepest path in tree
Intuition
- construct the tree, find the path length
- the number of two-color the path is 2^len
Approach
- use groupBy
- modPow is an overkill, fold is enough
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
fun assignEdgeWeights(e: Array<IntArray>): Long {
val g = e.flatMap {(a,b) -> setOf(a to b,b to a)}.groupBy({it.first},{it.second})
fun d(i: Int, p: Int): Int = g[i]?.maxOf { j -> if (j == p) 0 else 1 + d(j, i) }?:0
return (1..<d(1, 0)).fold(1L){r,_ -> (r*2)%1000000007}
}
pub fn assign_edge_weights(e: Vec<Vec<i32>>) -> i32 {
let g = e.into_iter().flat_map(|v| [(v[0], v[1]), (v[1], v[0])]).into_group_map();
fn d(i: i32, p: i32, g: &HashMap<i32, Vec<i32>>) -> i32 {
g.get(&i).into_iter().flatten().map(|&j| if j == p { 0 } else { 1 + d(j, i, g) }).max().unwrap_or(0)
}
(1..d(1, 0, &g)).fold(1, |r, _| r * 2 % 1_000_000_007)
}
10.06.2026
3691. Maximum Total Subarray Value II hard substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1386
Problem TLDR
sum k largest ranges max(l..r)-min(l..r)
Intuition
- segment tree: size is 2*n, right lalf is the leafs, left half is the parents; to query look when left pointer is the right child, and right pointer is the left child
Approach
- Use segment tree to query max and in of range l..r
- The largest max-min is when the range is the widest, put all widest ranges to a sorted collection
- Query sorted collection and update with shrinked range l..r-1
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(n)\)
Code
fun maxTotalValue(n: IntArray, k: Int): Long {
val s = n.size; val t0 = IntArray(s*2); val t1 = IntArray(s*2)
for (i in n.indices) { t0[i+s] = n[i]; t1[i+s] = n[i] }
for (i in s-1 downTo 1) { t0[i]=min(t0[i*2], t0[i*2+1]); t1[i]=max(t1[i*2], t1[i*2+1]) }
fun q(l: Int, r: Int): IntArray {
var a=l+s; var b=r+s; var m=Int.MAX_VALUE; var M=0
while (a <= b) {
if (a % 2 > 0) { m = min(m, t0[a]); M = max(M, t1[a++]) }
if (b % 2 < 1) { m = min(m, t0[b]); M = max(M, t1[b--]) }
a /= 2; b /= 2
}
return intArrayOf(l, r, M - m)
}
val pq = PriorityQueue<IntArray>(compareBy { -it[2] })
for (i in n.indices) pq += q(i, s-1)
return (1..k).sumOf { pq.poll()?.let {(l,r,v) -> if (r>l) pq += q(l,r-1); 1L*v } ?: 0L }
}
pub fn max_total_value(n: Vec<i32>, k: i32) -> i64 {
let s = n.len(); let (mut t0, mut t1) = (vec![0; s * 2], vec![0; s * 2]);
for i in 0..s { t0[i+s] = n[i]; t1[i+s] = n[i] }
for i in (1..s).rev() { t0[i]=t0[i*2].min(t0[i*2+1]); t1[i]=t1[i*2].max(t1[i*2+1])}
let q = |l: usize, r: usize| {
let (mut a, mut b, mut m, mut M) = (l+s, r+s, i32::MAX, i32::MIN);
while a <= b {
if a % 2 > 0 { m = m.min(t0[a]); M = M.max(t1[a]); a += 1 }
if b % 2 == 0 { m = m.min(t0[b]); M = M.max(t1[b]); b -= 1 }
a /= 2; b /= 2
}
(M - m, l, r)
};
let mut pq: BinaryHeap<_> = (0..s).map(|i| q(i, s - 1)).collect();
(0..k).filter_map(|_|pq.pop().map(|(v,l,r)|{if r>l{pq.push(q(l,r-1))};v as i64})).sum()
}
06.06.2026
2574. Left and Right Sum Differences easy substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1382
Problem TLDR
abs(prefix sum - suffix sum)
Intuition
- we can use math to just re-use the sum as is
Approach
Compute the sum - this is the suffix; use a single variable for prefix sum. Problem is small 1000 elements and 10^5 items, meaning we are in 32 bits
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
fun leftRightDifference(n: IntArray) =
n.run {val s = sum(); var l = 0; map {l += it; abs(2*l-it-s)}}
pub fn left_right_difference(n: Vec<i32>) -> Vec<i32> {
let (s, mut l) = (n.iter().sum::<i32>(), 0);
n.iter().map(|x| { l += x; (2*l-x-s).abs()}).collect()
}
05.06.2026
3753. Total Waviness of Numbers in Range II hard substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1381
Problem TLDR
Count hills and valleys base10 in a..b
Intuition
Didn’t solve myself. Brute-force - would not work for 10^15 elements. Digit DP: try every digit, be aware of the limit and of the leading zeros.
Approach
- when counting valleys or hills we must add entire suffix of possible values: they will be either limited (suffix of number itself) or not (pow10)
Complexity
-
Time complexity: \(O(logn)\)
-
Space complexity: \(O(logn)\)
Code
fun totalWaviness(a: Long, b: Long): Long {
val P = (1..16).scan(1L) { r, _ -> r * 10L }
fun c(x: Long): Long {
val s = "$x"; val dp = HashMap<String, Long>()
fun f(i: Int, pp: Int, p: Int, t: Boolean): Long =
if (i == s.length) 0L else dp.getOrPut("$i $pp $p $t") {
(0..if (t) 9 else s[i] - '0').sumOf { d ->
val nt = t || d < s[i] - '0'
val w = if (pp >= 0 && (pp - p) * (d - p) > 0)
if (nt) P[s.length - 1 - i] else (s.substring(i + 1).toLongOrNull() ?: 0L) + 1L else 0L
w + f(i + 1, if (p < 0 && d == 0) -1 else p, if (p < 0 && d == 0) -1 else d, nt)
}
}
return f(0, -1, -1, false)
}
return c(b) - c(a - 1)
}
pub fn total_waviness(a: i64, b: i64) -> i64 {
fn c(x: i64) -> i64 {
fn f(i: usize, u: i8, v: i8, t: bool, x: i64, s: &[u8], m: &mut HashMap<(usize, i8, i8, bool), i64>) -> i64 {
if let Some(&r) = m.get(&(i, u, v, t)) { return r; }
let (mut r, j, l) = (0, (s.len() - 1 - i) as u32, if t { 9 } else { (s[i] - 48) as i8 });
for d in 0..=l {
let (n, z, p) = (t || d < l, v < 0 && d == 0, 10i64.pow(j));
if u >= 0 && (u - v) * (d - v) > 0 { r += if n { p } else { x % p + 1 }; }
if j > 0 { r += f(i + 1, if z { -1 } else { v }, if z { -1 } else { d }, n, x, s, m); }
}
m.insert((i, u, v, t), r); r
}
if x < 0 { 0 } else { f(0, -1, -1, false, x, &x.to_string().into_bytes(), &mut HashMap::new()) }
}
c(b) - c(a - 1)
}
04.06.2026
3751. Total Waviness of Numbers in Range I medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1380
Problem TLDR
Count hills and valleys base10 in a..b
Intuition
Brute-force
Approach
- Rust: itertools allows for tuple_windows
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(logn)\)
Code
fun totalWaviness(a: Int, b: Int) =
(a..b).sumOf {"$it".windowed(3).count {(it[0]-it[1])*(it[2]-it[1])>0}}
pub fn total_waviness(a: i32, b: i32) -> i32 {
(a..=b).map(|x|x.to_string().bytes().tuple_windows()
.filter(|(a,b,c)|a>b&&c>b||a<b&&c<b).count()as i32).sum::<i32>()
}
03.06.2026
3635. Earliest Finish Time for Land and Water Rides II medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1379
Problem TLDR
Min finish time of land + water single events
Intuition
find min water and land finish times, then try all waters with finish land and try all lands with finish water
Approach
- extract the repeating parts
- Rust can derive the argument types in lambdas
- Kotlin: we can extract sub-sub functions
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
fun earliestFinishTime(lst: IntArray, ld: IntArray, wst: IntArray, wd: IntArray)= run {
fun f(st: IntArray, d: IntArray) = {s: Int ->st.zip(d).minOf{(st,d)->max(s,st)+d}}
val (a,b) = f(lst, ld) to f(wst, wd); min(a(b(0)), b(a(0)))
}
pub fn earliest_finish_time(lst: Vec<i32>, ld: Vec<i32>, wst: Vec<i32>, wd: Vec<i32>) -> i32 {
let f = |st:&[i32],d:&[i32], s| (0..d.len()).map(|i|st[i].max(s)+d[i]).min().unwrap();
f(&lst, &ld, f(&wst, &wd, 0)).min(f(&wst, &wd, f(&lst, &ld, 0)))
}
02.06.2026
3633. Earliest Finish Time for Land and Water Rides I easy substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1378
Problem TLDR
Min finish time of land + water single events
Intuition
Brute-force: take every water even and compare with every land event Optimal: find min water and land finish times, then try all waters with finish land and try all lands with finish water
Approach
- extract the repeating parts
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
fun earliestFinishTime(lst: IntArray, ld: IntArray, wst: IntArray, wd: IntArray): Int {
val f = { s:IntArray,d:IntArray,m:Int -> s.indices.minOf{max(m,s[it])+d[it]}}
return min(f(wst,wd, f(lst,ld,0)),f(lst,ld,f(wst,wd,0)))
}
pub fn earliest_finish_time(lst: Vec<i32>, ld: Vec<i32>, wst: Vec<i32>, wd: Vec<i32>) -> i32 {
let f = |s: &[i32], d: &[i32], m: i32| (0..s.len()).map(|i| s[i].max(m) + d[i]).min().unwrap();
f(&wst, &wd, f(&lst, &ld, 0)).min(f(&lst, &ld, f(&wst, &wd, 0)))
}
01.06.2026
2144. Minimum Cost of Buying Candies With Discount easy substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1377
Problem TLDR
Min sum taking 2 out of 3
Intuition
Sort descending, take greedily
Approach
- if you not sure which way is better forward or backward, you can make min(forward,backward)
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(n|1)\)
Code
fun minimumCost(c: IntArray) =
c.sortedDescending().filterIndexed {i,_->i%3<2}.sum()
pub fn minimum_cost(mut c: Vec<i32>) -> i32 {
c.sort_unstable_by(|a, b| b.cmp(a));
c.chunks(3).flat_map(|c| c.iter().take(2)).sum()
}
31.05.2026
2126. Destroying Asteroids medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1376
Problem TLDR
Can consume all asteroids smaller than running sum?
Intuition
- sort + greedy: sort, then take from smaller to larger
- bits group: consume from smallest highest one bit group if it’s min is bigger than mass
- quickselect: move to prefix & consume all asteroids that are not larger; the math guarantees O(n) - otherwise numbers have to grow by 2^i
Approach
- Rust’s select_nth_unstable requires mid position, can’t be used here
Complexity
-
Time complexity: \(O(nlogn|n)\)
-
Space complexity: \(O(n|1)\)
Code
fun asteroidsDestroyed(m: Int, a: IntArray) =
a.sorted().fold(1L*m){r,t->if(r<t)0L else r+t}>0
pub fn asteroids_destroyed(m: i32, mut a: Vec<i32>) -> bool {
let (mut c, mut s) = (m as i64, 0);
while s < a.len() {
let mut i = s;
for j in s..a.len() {
if a[j]as i64 <= c { c += a[j] as i64; a.swap(i, j); i += 1 }
}
if s == i { return false }; s = i
} true
}
30.05.2026
3161. Block Placement Queries hard substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1375
Problem TLDR
Queries ‘can place a gap after place an obstacle’
Intuition
Didn’t solved without a hint. The TreeMap solution:
- group starting points per gap size
- store obstacles in sorted set
- query: fine left and right obstacle, query the gap, take first starting poing, check size
- build: find left and right obstacle, remove old starting point from that gap, add new starting points to left and right gaps
The SegmentTree solution:
- role: finds the max gap that starts in range 0..x
- build: put current T[M+x] = sz, propagate to parents
- save obstacles in a sorted set
- query: find left obstacle, one gap is x-l, second gap is segment tree maximum in range 0..l-1 (corner case excludes l)
Approach
- another segment tree solution is defined by role: find the max gap in range 0..x (it requires to store [start,end,max] per node)
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(n)\)
Code
fun getResults(q: Array<IntArray>) = sortedSetOf(0, 100000).run {
val gs = TreeMap(mapOf(-100000 to sortedSetOf(0)))
q.mapNotNull { q -> val x = q[1]
if (q[0] > 1) gs.any { (g, s) -> -g >= q[2] && s.first() <= x-q[2] }
else null.also { val l = lower(x); val r = higher(x); add(x)
gs[l-r]?.let { it -= l; if (it.isEmpty()) gs -= l-r }
gs.getOrPut(l-x, ::TreeSet) += l; gs.getOrPut(x-r, ::TreeSet) += q[1]
}
}
}
pub fn get_results(q: Vec<Vec<i32>>) -> Vec<bool> {
let (mut o, mut t, z) = (BTreeSet::from([0, 50005]), vec![0; 100010], 50005); t[z]=z as i32;
q.into_iter().filter_map(|c| { let x=c[1];
if c[0]>1 { let f=*o.range(..=x).next_back()?; let (mut l, mut r, mut m)=(z, f as usize+z-1, 0);
while l<=r { if l%2>0 {m=m.max(t[l]); l+=1} if r%2<1 {m=m.max(t[r]); r-=1} l/=2; r/=2 }
Some((x-f).max(m) >= c[2])
} else { let (l, r) = (*o.range(..x).next_back()?, *o.range(x..).next()?); o.insert(x);
for (k,v) in [(l, x-l), (x, r-x)] { let mut i=k as usize+z; t[i]=v; while i>1 {i/=2; t[i]=t[i*2].max(t[i*2+1])} }
None
}
}).collect()
}
29.05.2026
3300. Minimum Element After Replacement With Digit Sum easy substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1374
Problem TLDR
Min of digits sum
Intuition
Compute the digits sum in a while loop, track the minimum.
Approach
- you can unroll the while loop
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
fun minElement(n: IntArray) =
n.minOf{"$it".sumOf{it-'0'}}
pub fn min_element(n: Vec<i32>) -> i32 {
n.iter().map(|x|x%10+x/10%10+x/100%10+x/1000%10+x/10000%10).min().unwrap()
}
28.05.2026
3093. Longest Common Suffix Queries hard substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1373
Problem TLDR
Query common suffixes match
Intuition
Use Trie. Update the shortest index as you go.
Approach
- in Rust the interesting pattern is an arena allocation
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
fun stringIndices(c: Array<String>, q: Array<String>) = run {
class T(var i: Int): HashMap<Char,T>()
val r = T(c.indexOf(c.minBy{it.length}))
for ((i,w) in c.withIndex()) { var t = r
for (j in w.lastIndex downTo 0) t = t.getOrPut(w[j]){T(i)}
.also { if (w.length < c[it.i].length) it.i = i }
}
q.map { var t = r; for (c in it.reversed()) t = t[c] ?: break; t.i }
}
pub fn string_indices(c: Vec<String>, q: Vec<String>) -> Vec<i32> {
let mut n = vec![([0; 26], (0..c.len()).min_by_key(|&i| c[i].len()).unwrap())];
for (i, w) in c.iter().enumerate() { let mut u = 0;
for b in w.bytes().rev() { let k = (b - b'a') as usize;
if n[u].0[k] == 0 { n[u].0[k] = n.len(); n.push(([0; 26], i)) }
u = n[u].0[k]; if w.len() < c[n[u].1].len() { n[u].1 = i }
}
}
q.iter().map(|w| { let mut u = 0;
for b in w.bytes().rev() {
let v = n[u].0[(b - b'a') as usize]; if v == 0 { break } u = v
} n[u].1 as _
}).collect()
}
27.05.2026
3121. Count the Number of Special Characters II medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1372
Problem TLDR
Count sorted characters
Intuition
Brute-force: checkk all letters separately a..z, last index of c should be in range of 0..first index of C Optimal: bitmasks to track visited uppercase and lowercase and invalid marker
Approach
- 0.. is essential in kotlin, because lastIndexof can be -1
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
fun numberOfSpecialChars(w: String) = ('a'..'z')
.count { w.lastIndexOf(it) in 0..<w.indexOf(it-32) }
pub fn number_of_special_chars(w: String) -> i32 {
(b'a'..=b'z').filter(|&c| w.rfind(c as char)
.is_some_and(|l| Some(l) < w.find((c - 32) as char))).count() as _
}
26.05.2026
3120. Count the Number of Special Characters I easy substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1371
Problem TLDR
Count letters with both cases
Intuition
Brute-force is accepted. O(n) memory: for any uniq lowercase check if uppercase present, use hashset O(1) memory: two bitmasks, for lower and for upper cases; (m & M) count bits is the result
Approach
- regex is ugly here
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n)\)
Code
fun numberOfSpecialChars(w: String) =
w.toSet().count {it-32 in w}
pub fn number_of_special_chars(w: String) -> i32 {
('a'..='z').zip('A'..='Z').filter(|&(c,C)| w.contains(c)&&w.contains(C)).count() as _
}
25.05.2026
1871. Jump Game VII medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1370
Problem TLDR
Can reach end jumping min..max to zeros
Intuition
- forward: put line sweep interval start-end events, slide
- backwards: slide window looking backwards, count reachable items inside window
Approach
- the end should not be ‘1’
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
fun canReach(s: String, min: Int, max: Int): Boolean {
val e = IntArray(s.length+max+2); e[1] = -1
return s.last() == '0' && 0 < s.indices.fold(1) { c, i ->
if (s[i] == '0' && c+e[i] > 0) { e[i+min]++; e[i+max+1]-- }
c + e[i]
}
}
pub fn can_reach(s: String, l: i32, h: i32) -> bool {
let mut e = vec![0; s.len()+h as usize + 2]; e[1] = -1;
s.ends_with('0') && 0 < s.bytes().zip(0..).fold(1, |c, (v, i)| {
if v < 49 && c + e[i] > 0 { e[i+l as usize] += 1; e[i+h as usize+1] -= 1 }
c + e[i]
})
}
24.05.2026
1340. Jump Game V hard substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1369
Problem TLDR
Max visited by jumping down in distance d
Intuition
- Top-down DP: dfs from each index to the left and to the right by d distance, memo by i
- Bottom-up DP: iterate in increasing value order to safely use previous results because we only jump down
-
O(N) solution: use decreasing stack, track left peak, pop smaller valleys and update m[left_peak right_peak]=max(m[popped]+1),
Approach
- for monotonic we have to track left peaks becasue of the duplicates
Complexity
-
Time complexity: \(O(nd|n)\)
-
Space complexity: \(O(n)\)
Code
fun maxJumps(a: IntArray, d: Int) = IntArray(a.size).let { m ->
a.indices.sortedBy{a[it]}.maxOf { i ->
m[i] = 1+setOf(i-1 downTo i-d,i+1..i+d).maxOf {
it.takeWhile{a.getOrNull(it)?:a[i]<a[i]}.maxOfOrNull{m[it]}?:0};m[i]}}
pub fn max_jumps(a: Vec<i32>, d: i32) -> i32 {
let(d,n)=(d as usize,a.len());let mut m=vec![1;n];let mut s:Vec<(usize,usize)>=vec![];
for (&v,i) in a.iter().chain([&99999]).zip(0..) {
while let Some(&(j, l)) = s.last() && a[j] < v { s.pop();
if i < n && i - j <= d { m[i] = m[i].max(m[j] + 1) }
if l < n && j - l <= d { m[l] = m[l].max(m[j] + 1) }
}
s.push((i,s.last().map_or(n,|&(k,l)|if a[k]>v {k} else {l})))
} m.into_iter().max().unwrap()
}
23.05.2026
1752. Check if Array Is Sorted and Rotated easy substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1368
Problem TLDR
Is array shifted and sorted?
Intuition
- brute-force is accepted for 100 elements
- optimal way: count unordered elements
Approach
- the shortest Rust is n^2
- Rust itetools has circular_tuple_windows
Complexity
-
Time complexity: \(O(n|n^2)\)
-
Space complexity: \(O(1|n)\)
Code
fun check(n: IntArray) =
n.indices.count { n[it]>n[(it+1)%n.size]} < 2
pub fn check(n: Vec<i32>) -> bool {
n.repeat(2).windows(n.len()).any(|w|w.is_sorted())
}
22.05.2026
33. Search in Rotated Sorted Array medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1367
Problem TLDR
Binary search in shifted array
Intuition
- find the split point
- binary search in two parts
Approach
- insertion point: the first value is less than first part and bigger than second part
- if target is less than first value - it is in the second part
Complexity
-
Time complexity: \(O(logn)\)
-
Space complexity: \(O(1)\)
Code
fun search(n: IntArray, t: Int) = n.asList().run {
val s = binarySearch { if(it < n[0])1 else -1}.inv()
maxOf(-1, binarySearch(t, 0, s), binarySearch(t, s))
}
pub fn search(n: Vec<i32>, t: i32) -> i32 {
let (s,b) = (n.partition_point(|&x| x >= n[0]), (t<n[0]) as usize);
[&n[..s],&n[s..]][b].binary_search(&t).map_or(-1, |i|(i+s*b)as _)
}
21.05.2026
3043. Find the Length of the Longest Common Prefix medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1366
Problem TLDR
Longest prefix of pairs
Intuition
- hashset: put all prefixes of one array, query all prefixes of the second array
- trie: put all prefixes of one array into trie, check longest path for all prefixes of the second
Approach
- we can use strings or ints
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
fun longestCommonPrefix(a: IntArray, b: IntArray) = run {
val s = a.flatMap { "$it".scan("", String::plus) }.toSet()
b.maxOf { var v = "$it"; while (v !in s) v = v.dropLast(1); v.length }
}
pub fn longest_common_prefix(a: Vec<i32>, b: Vec<i32>) -> i32 {
#[derive(Default)] struct T(HashMap<u8, T>); let mut r = T::default();
for x in a { x.to_string().bytes().fold(&mut r, |t, c| t.0.entry(c).or_default()); }
b.iter().map(|x| {
let mut t = &r;
x.to_string().bytes().take_while(|c| t.0.get(c).map(|n| t = n).is_some()).count() as _
}).max().unwrap()
}
20.05.2026
2657. Find the Prefix Common Array of Two Arrays medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1365
Problem TLDR
Duplicates in prefixes
Intuition
Only 50 elements, brute-force works. We can use HashSets or bitmasks
Approach
- shortest version in Kotlin is O(n^2)
- in Rust we can use zip+scan, or a simple map
Complexity
-
Time complexity: \(O(n^2|n)\)
-
Space complexity: \(O(n)\)
Code
fun findThePrefixCommonArray(a: IntArray, b: IntArray) =
(1..a.size).map {a.take(it).intersect(b.take(it)).size}
pub fn find_the_prefix_common_array(a: Vec<i32>, b: Vec<i32>) -> Vec<i32> {
let (mut c, mut d) = (0, 0i64);
(0..a.len()).map(|i|{c|=1<<a[i];d|=1<<b[i];(c&d).count_ones() as _}).collect()
}
19.05.2026
2540. Minimum Common Value easy substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1364
Problem TLDR
Min common of two sorted list
Intuition
- two pointers: one goes forward, second tries to match
- or hashset
- or binary search
Approach
- binary search is the shortest
- rust itertools has nice way to merge sorted lists
Complexity
-
Time complexity: \(O(nlogn|n)\)
-
Space complexity: \(O(1)\)
Code
fun getCommon(a:IntArray, b: IntArray) =
a.find { b.binarySearch(it) >= 0 } ?: -1
pub fn get_common(a: Vec<i32>, b: Vec<i32>) -> i32 {
a.into_iter().merge_join_by(b, i32::cmp).find_map(|e|
match e {Both(a,_)=>Some(a), _=>None}).unwrap_or(-1)
}
18.05.2026
1345. Jump Game IV hard substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1363
Problem TLDR
Min steps to reach end jumping to same value or left or right
Intuition
group by value and do BFS
Approach
- remove visited groups
- mark visited early
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
fun minJumps(a: IntArray): Int {
val g = HashMap(a.indices.groupBy{a[it]}); var t = -1
val q = ArrayDeque(listOf(0)); val v = hashSetOf(0)
while (q.size > 0 && ++t>=0) for (x in 1..q.size) {
val i = q.removeFirst(); if (i == a.size-1) return t
for (j in (g.remove(a[i])?:setOf())+(i-1)+(i+1))
if (j in a.indices && v.add(j)) q += j
}
return a.size-1
}
pub fn min_jumps(a: Vec<i32>) -> i32 {
let mut g = (0..a.len()).into_group_map_by(|&i| a[i]);
let (mut q, mut v, mut t) = (vec![0], vec![0;a.len()], 0);
loop { let mut w = vec![]; for i in q {
if i == a.len()-1 { return t }
for j in g.remove(&a[i]).into_iter().flatten().chain([i-1,i+1]) {
if j < a.len() && v[j] < 1 { v[j] = 1; w.push(j) }
}
} q = w; t += 1 }
}
17.05.2026
1306. Jump Game III medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1362
Problem TLDR
Can reach 0 by jumping +a[i] - a[i]
Intuition
- Union-Find would not work - we have a strictly directed edges in graph
- BFS/DFS works
Approach
- use array itself as a visited set
- use ‘camicadze’ value to make it out of range and make less checks
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
fun canReach(a: IntArray, s: Int):Boolean = s in a.indices&&
a[s].let{x->a[s]=a.size;x==0||canReach(a,s-x)||canReach(a,s+x)}
pub fn can_reach(mut a: Vec<i32>, s: i32) -> bool {
let mut q = vec![s];
while let Some(i) = q.pop() {
let Some(x) = a.get_mut(i as usize) else {continue};
if *x == 0 { return true }
q.extend([i-*x,i+*x]); *x += 100000
} false
}
16.05.2026
154. Find Minimum in Rotated Sorted Array II hard substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1361
Problem TLDR
Binary search in shifted array with duplicates
Intuition
// 3 4 5 6 7 1 2 3
// 3 1
// false false
// 3 1 3
// false true false
- compare all elements with last
- slice duplicates out in O(N)
Approach
- use built-in functions, Rust: partition_point, position, slices [..], Kotlin: binarySearch {..}, indexOfFirst
- x.inv() is -1-x
Complexity
-
Time complexity: \(O(n|logn)\)
-
Space complexity: \(O(1)\)
Code
fun findMin(n: IntArray) = n[n.asList().binarySearch(
max(0, n.indexOfFirst { it != n.last()})) {
if (it <= n.last()) 1 else -1 }.inv()]
pub fn find_min(n: Vec<i32>) -> i32 {
let n = &n[n.iter().position(|&x| x != n[n.len()-1]).unwrap_or(0)..];
n[n.partition_point(|&x|x > n[n.len()-1])]
}
15.05.2026
153. Find Minimum in Rotated Sorted Array medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1360
Problem TLDR
Binary search in shifted array
Intuition
// 5 6 7 0 1 2 3 4
// l m h
// 6 7 0 1 2 3 4 5
// l m h
// 6 7 0 1 2 3 4 5
// l m h
// 4 5 6 7 0 1 2
// l m h
// l
- invent the binary search from scratch
- or notice that we can compare all elements with last
Approach
- use built-in functions, Rust: partition_point, Kotlin: binarySearch {..}
Complexity
-
Time complexity: \(O(logn)\)
-
Space complexity: \(O(1)\)
Code
fun findMin(n: IntArray) =
n[-1-n.asList().binarySearch { if (it > n.last()) -1 else 1}]
pub fn find_min(n: Vec<i32>) -> i32 {
n[n.partition_point(|&x|x>n[n.len()-1])]
}
14.05.2026
2784. Check if Array is Good easy substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1359
Problem TLDR
Is combination 1..n,n
Intuition
- no-brain solution: check every number (1..n) is in array, and count(n)==2
- shortest solution: (1..n)+n==sorted()
- optimal solution: use array indices as visited storage
Approach
- n[0] can be used as extra storage for n[len-1] special case
Complexity
-
Time complexity: \(O(nlogn|n)\)
-
Space complexity: \(O(n|1)\)
Code
fun isGood(n: IntArray) =
(1..<n.size) + (n.size-1) == n.sorted()
pub fn is_good(mut n: Vec<i32>) -> bool {
(0..n.len()).all(|i| { let x = n[i].abs() as usize;
!(x>=n.len()||n[x]<0&&(x<n.len()-1||n[0]<0)) && {
if n[x] < 0 { n[0] *= -1 } else { n[x] *= -1 };1>0}
}) && n[0]<0
}
13.05.2026
1674. Minimum Moves to Make Array Complementary medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1358
Problem TLDR
Min changes 1..L to make complementary pair sum equal
Intuition
// brainteaser
// max: we can convert all numbers to the same number
// track pairs sums, peek the most common
// each pair is a sum of ranges 1..l + 1..l
// common sum should be within 2..2l
// llll
// aa
// bbbb
// s
// aaaaaa
// bbb
// s
// aa
// bb
// s
// 28 minute wrong answer
// 34 minute wrong answer
// use hints: no help, difference array?
// so looks like intersection of the intervals
Each value pair (a,b) forms a range of possible targets: 2..2L full range of targets where both ‘a’ and ‘b’ got changed; min(a,b)+1..max(a,b)+L is a range of single change either ‘a’ or ‘b’ a+b - is a single point where no change required, because target == a+b.
Merge all ranges then scan them to find maximum changes required.
Approach
- some computations can be extracted out of line sweep
Complexity
-
Time complexity: \(O(L+N)\)
-
Space complexity: \(O(L)\)
Code
fun minMoves(n: IntArray, l: Int): Int {
val d = IntArray(2*l + 2); var c = 0;
for (i in 0..<n.size/2) {
val a = n[i]; val b = n[n.size-1-i]
d[min(a,b)+1]--; d[max(a,b)+l+1]++; d[a+b]--; d[a+b+1]++
}
return (2..2*l).minOf { c += d[it]; c } + n.size
}
pub fn min_moves(n: Vec<i32>, l: i32) -> i32 {
let (mut d, l) = ([0; 200002], l as usize);
for i in 0..n.len()/2 {
let (a, b) = (n[i] as usize, n[n.len()-1-i] as usize);
d[a.min(b)+1]-=1;d[a.max(b)+l+1]+=1; d[a+b]-=1;d[a+b+1]+=1
}
(2..2*l+1).fold((0,0), |(min, c),i|(min.min(c+d[i]),c+d[i])).0 +n.len() as i32
}
12.05.2026
1665. Minimum Initial Energy to Finish Tasks hard substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1357
Problem TLDR
Energy for all tasks (spend, limit)
Intuition
// we can do binary search
// but how to optimally use the energy?
// do we know that order is always decrease t[][1]?
//
// i don't have any better idea, let's write bs
// 32
// 10-12, 10-11, 8-9, 2-4, 1-3
// 22 12 4 2 so this is the corner case
//
// 1-3 2-4 10-11 10-12 8-9
// 32 31 29 19 9 this is the optimal order
//
// 26 minute, hints: Figure a sorting pattern
// is exactly what i can't do
//
// so this is a brainteaser about sorting
//
Didn’t solve without a hint. Sort by (spend-limit). Then do a binary search with forward pass and energy consumption or just a backward pass and energy max(spend, limit). The intuition behind (spend-limit): it is a greedy assumption that minimizing the consumption works. Why the pair of (spend,-limit) or (-limit, spend) doesn’t work? Because we want to maximize the “refund” (what was required - what was returned back).
Approach
- rust itertools allows one-liner
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(1)\)
Code
fun minimumEffort(t: Array<IntArray>) = t
.sortedBy { it[1]-it[0] }
.fold(0) { e, (a,b) -> max(e+a, b) }
pub fn minimum_effort(t: Vec<Vec<i32>>) -> i32 {
t.iter().sorted_by_key(|v|v[1]-v[0])
.fold(0, |e, v| v[1].max(e+v[0]))
}
11.05.2026
2553. Separate the Digits in an Array easy substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1356
Problem TLDR
LIst of numbers to list of digits
Intuition
Convert to strings or do %10 with LInkedList/ArrayDeque or do the reverse.
Approach
- Kotlin: joinToString converts numbers to strings
- Rust: use flat_map or to_string/bytes
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
fun separateDigits(n: IntArray) =
n.joinToString("").map{it-'0'}
pub fn separate_digits(n: Vec<i32>) -> Vec<i32> {
n.iter().map(|x|x.to_string()).collect::<String>()
.bytes().map(|b|(b-b'0') as i32).collect()
}
10.05.2026
2770. Maximum Number of Jumps to Reach the Last Index medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1355
Problem TLDR
Max steps to reach end by jumps n[j]-n[i] in -t..t
Intuition
Top-down DP: at each position i with previous position j choose to skip (dfs(i+1,p)) or take(1+dfs(i+1,i)) Bottom-up DP: for each index i if it is reachable update all next position if they reachable Segment tree solution: for each value X query the range X-t..X+t for maximum reachable steps in this range
Approach
- segment tree query: if left is the right child & if right is the left child; move them sideways & update query result
Complexity
-
Time complexity: \(O(n^2|nlogn)\)
-
Space complexity: \(O(n)\)
Code
fun maximumJumps(n: IntArray, t: Int) = IntArray(n.size).also { d ->
d[0] = 1
for (i in d.indices) if (d[i] > 0) for (j in i+1..<d.size)
if (abs(n[i]-n[j]) <= t) d[j] = max(d[j], 1 + d[i])
}.last() - 1
pub fn maximum_jumps(n: Vec<i32>, t: i32) -> i32 {
let mut v = n.clone(); v.sort(); v.dedup(); let m = v.len(); let mut tr = vec![-1; m*2];
let (f,g) = (|x|v.partition_point(|&y|y<x), |x|v.partition_point(|&y|y<=x));
(0..).zip(n).fold(0, |q, (i,x)| {
let (mut l,mut r) = (f(x.saturating_sub(t)), g(x.saturating_add(t)).saturating_sub(1));
let mut q = (i==0) as i32-1; l += m; r += m;
while l <= r { if l&1 > 0 { q = q.max(tr[l]); l += 1 }; if r&1 < 1 { q = q.max(tr[r]); r -= 1 }
l /= 2; r /= 2
}
if q >= 0 { q += (i>0)as i32; let mut p = f(x)+m; tr[p] = tr[p].max(q);
while p > 1 { p /=2; tr[p] = tr[p*2].max(tr[p*2+1])}
}; q
})
}
09.05.2026
1914. Cyclically Rotating a Grid medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1354
Problem TLDR
Rotate matix layers by k
Intuition
// 4x6=16 = 2*3+2*5
// m,n up to 50, can rotate k times by 1
n^3 time, O(1) memory: go layer by layer, then repeat k%p rotates by 1: repeat p times swaps, compute next position n^2 time, O(1) memory: go layer by layer, linearize each layer by writing get(i) function, do rotation in-place by 3-reversal trick
3-reversal trick: reverse 0..k, k..end, 0..end; the result is shifted left by k
Approach
- solutions with O(n) memory are shorter
Complexity
-
Time complexity: \(O(n^3|n^2)\)
-
Space complexity: \(O(n)\)
Code
fun rotateGrid(g: Array<IntArray>, k: Int) = g.also {
val h = g.size; val w = g[0].size
for (l in 0..<min(w, h) / 2) {
val q = (l..<w - l).map {l to it} +
(l + 1..<h - l).map {it to w - 1 - l} +
(w - 2 - l downTo l).map {h - 1 - l to it} +
(h - 2 - l downTo l + 1).map {it to l }
val v = q.map { (r, c) -> g[r][c] }
q.forEachIndexed {i, (r, c) -> g[r][c] = v[(i + k) % v.size]}
}
}
pub fn rotate_grid(mut g: Vec<Vec<i32>>, k: i32) -> Vec<Vec<i32>> {
let (w, h, k) = (g[0].len(), g.len(), k as usize);
for l in 0..w.min(h)/2 {
let q: Vec<_> = (l..w-l).map(|i| (l,i))
.chain((l+1..h-l).map(|i|(i,w-1-l)))
.chain((l..w-1-l).rev().map(|i|(h-1-l,i)))
.chain((l+1..h-1-l).rev().map(|i|(i,l))).collect();
let mut rev = |s:usize, e:usize| { for i in 0..(e-s+1)/2 {
let ((a,b),(c,d)) = (q[s+i], q[e-i]);
let t = g[a][b]; g[a][b] = g[c][d]; g[c][d] = t
}};
rev(0, k%q.len()-1); rev(k%q.len(), q.len()-1); rev(0, q.len()-1)
}; g
}
08.05.2026
3629. Minimum Jumps to Reach End via Prime Teleportation medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1353
Problem TLDR
Shortest path by prime factors
Intuition
// brainteaser
// 10^5 total
// sqrt(n) to check if it is prime O(NsqrtN)
// check every number to be % by all primes in list O(n^2)
// run BFS
//
// i'll go straigth to hints, have no idea
// hints suggesting O(n^2) solution?
// prime *factors* for each number, not precompute primes, but factors
// 53 minute wrong answer
// 54 minute TLE (as expected)
// how to prepare primes buckets? 58 minute
// so the missing part is prime factors?
- prepare primes with sieve
- factorize all numbers
- prepare map from prime factor to eligible indices
- bfs using this hashmap
Another way:
- instead of preparing factors, just iterate factors inside bfs step
Approach
- prime sieve: outer loop i = 2..n, and mark all multipliers of i with false (not prime)
- factorization: outer loop: p = primes, and check if v % p, then add, and divide v/p until not divisible
- iterating from prime to possible values: p..max step p
Complexity
-
Time complexity: \(O(nlogm)\)
-
Space complexity: \(O(n+m)\)
Code
fun minJumps(n: IntArray): Int {
val q = ArrayDeque(setOf(0)); var res = -1; val v = hashSetOf(0); var i = 1
val s = BooleanArray(n.max()+1) {it>1}; val m = n.indices.groupBy{n[it]}
while (++i*i<s.size) if (s[i]) for (j in i*i..<s.size step i) s[j]=false
while (++res>=0) for (a in 1..q.size) q.removeFirst().let { i ->
if (i == n.size-1) return res; var p = n[i]
for (j in setOf(i-1,i+1)) if (j in n.indices && v.add(j)) q += j
if (s[p]&&v.add(-p)) for(j in p..<s.size step p) { m[j]?.map{if(v.add(it)) q+=it}}
}
return 0
}
pub fn min_jumps(n: Vec<i32>) -> i32 {
let (mut q, mut res, mut v, mut i) = (VecDeque::from([0]), 0, HashSet::from([0]), 2);
let mut s = vec![true;*n.iter().max().unwrap() as usize + 1]; s[1]=false;
let m = (0..n.len()).into_group_map_by(|&i|n[i] as usize);
while i*i < s.len() { if s[i] { for j in (i*i..s.len()).step_by(i) { s[j] = false }}; i+=1}
loop { for a in 0..q.len() {
let i = q.pop_front().unwrap(); if i == n.len() - 1 { return res }; let p = n[i] as usize;
for j in [i-1, i+1] { if j < n.len() && v.insert(j) { q.push_back(j); }}
if s[p] && v.insert(n.len()+p) {
for &j in (p..s.len()).step_by(p).filter_map(|j|m.get(&j)).flatten() {
if v.insert(j) { q.push_back(j); }}}
} res += 1 } 0
}
07.05.2026
3660. Jump Game IX medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1352
Problem TLDR
Max on path jumping left-up and right-down
Intuition
// 2 3 1
// * decreasing sequence 3 1
//
// 1 2 3 4 3 2 1 2 3 4
// * 4 3 2 1
// j i
// ok maybe jump only to the left in one pass, then only to the right in second
// 2 3 1
// 2
// 3
// 3
// 3
// 3
//
// 2 1 3
// 2 2 3
// 3
// 3?
//
// 3 1 5 6 4 2
//*i j j
// j* i
//* i j j
//* i
// j j* i j
// j j* j i
// how many jumps possible? is it possible for valid path have 3 jumps?
// i*
// i j* for backwards pass with want to track first lower
// i j*
// i j*
// i
// i j*
//
// 3 1 5 6 2 4
// i
// j i
// i
// i
// j i
// j i for forward pass only the max
// i
// i
// i j
// i j override with max(n[i],n[j])
// i
// i j have to find j = set.lower(3)
// can we do monotonic stack/queue? - no, we don't know what useful
//
// 29minute wrong answer: nums = [30,21,5,35,24]
// my [35,30,30,35,35] Expected [35,35,35,35,35]
//
// 0 1 2 3 4
// 30 21 5 35 24 max 0
// i 30
// j i 30
// j i 30
// i 35
// j i 35
// i set 24=4
// i j 35=3 ok my mistake was: i was taking lower, but need max distance
// and second mistake: it can be more than two jumps
// at this point let's go to hints: graph
// 61 minute wrong answer: 989 / 1002 testcases passed,
// nums = [11,18,11] Output [18,18,18] Expected [11,18,18]
O(nlogn):
- first pass left-up jumps make increasing running max array
- second pass backwards: find the rightmost position with value less than current and use its best left-up jump res[j]
- we can use monotonic decreasing queue and binary search it O(n): The clever iddea is based on proove: instead of finding rightmost-less, we can just use res[i+1], if we can jump right (minSoFar < res[i]).
- res[i] - means best jump left-up
- min < res[i] - means we can jump right-down to this min
- no reason to jump ahead of res[i+1] because he is also sees this min’s position
Approach
- or we can watch several examples and see that results are always perfectly sorted
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
fun maxValue(n: IntArray): IntArray {
var m = 0; val res = IntArray(n.size) { m = max(m, n[it]); m }
for (i in n.lastIndex downTo 0) {
if (res[i] > m) res[i] = res[i+1]; m = min(m, n[i]);
}
return res
}
pub fn max_value(n: Vec<i32>) -> Vec<i32> {
let mut m = 0; let mut r:Vec<_> = (0..n.len()).map(|i| { m=m.max(n[i]);m}).collect();
for i in (0..n.len()).rev() {
if r[i] > m { r[i] = r[i+1]}; m = m.min(n[i])
}; r
}
06.05.2026
1861. Rotating the Box medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1351
Problem TLDR
Rotate and simulate gravity in matrix
Intuition
- first simulate ‘.’ bubble left or ‘#’ bubble right
- then rotate
Approach
- to bubble ‘.’ left: overwrite it with ‘#’ then overwrite empty place with ‘.’
- another solution is to split by ‘*’ chunks and sort them
Complexity
-
Time complexity: \(O(n|nlogn)\)
-
Space complexity: \(O(n)\)
Code
fun rotateTheBox(b: Array<CharArray>) = b.map { r ->
var j = 0
for (i in r.indices)
if (r[i] == '.') { r[i] = '#'; r[j++] = '.' }
else if (r[i] == '*') j = i+1
}.let { List(b[0].size) { i -> List(b.size) { b[b.size-1-it][i] }} }
pub fn rotate_the_box(mut b: Vec<Vec<char>>) -> Vec<Vec<char>> {
for r in &mut b {
for c in r.split_mut(|&c|c=='*') { c.sort_by(|a,b|b.cmp(a)) }};
(0..b[0].len()).map(|x|b.iter().rev().map(|r|r[x]).collect()).collect()
}
05.05.2026
61. Rotate List medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1350
Problem TLDR
Rotate linked list k steps
Intuition
- find the length
- find the split point k%L
- connect/disconnect
More interesting idea: make a cycle-list by connecting head to tail at the end of the first loop
Approach
- Rust doesn’t allow to make a cycle in Option<Box
> - Rust doesn’t allow to disconnect the head while holding the reference at the last item in list
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
fun rotateRight(h: ListNode?, k: Int): ListNode? {
h?.next ?: return h; var len = 1; var t = h
while (t?.next != null) { t = t.next; len++ }
t.next = h; for (s in 1..len - k%len) t = t?.next
return t?.next.also { t?.next = null }
}
pub fn rotate_right(mut h: Option<Box<ListNode>>, k: i32) -> Option<Box<ListNode>> {
if h.is_none() || k==0 { return h }; let (mut l, mut x) = (0, &h);
while let Some(n) = x { x = &n.next; l += 1 }
if l < 2 || k % l == 0 { return h }; let mut x = &mut h;
for _ in 0..l-(k%l) { if let Some(n) = x { x = &mut n.next }}
let mut res = x.take(); let mut x = &mut res;
while let Some(n) = x { x = &mut n.next }; *x = h; res
}
04.05.2026
48. Rotate Image medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1348
Problem TLDR
Rotate square matrix
Intuition
Go layer by layer and do 4-swaps in place on a single side
Approach
- reverse + transpose also works (in any order)
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
fun rotate(m: Array<IntArray>): Unit {
val n = m.size;
for (l in 0..<n / 2) for (s in l..<n - l - 1) {
val oi = n - 1 - l; val oj = n - 1 - s; val t = m[oi][oj]
m[oi][oj] = m[s][oi]; m[s][oi] = m[l][s]
m[l][s] = m[oj][l]; m[oj][l] = t
}
}
pub fn rotate(m: &mut Vec<Vec<i32>>) {
m.reverse();
for i in 0..m.len() { for j in i+1..m.len() {
let t = m[i][j]; m[i][j]=m[j][i]; m[j][i] = t
}}
}
03.05.2026
796. Rotate String easy substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1347
Problem TLDR
Match strings after rotation
Intuition
Brute-force: check every possible rotation
Clever idea: rotation is identical to repetition, find goal in concatenated source
KMP: precompute p[] array where p[i] is the length of matching goal[0..p[i]-1] == goal[i-(p[i]-1)..i]. Jump back j = p[j-1] if chars doesn’t match.
Approach
- the
.containsin Rust has O(n) time and O(1) space complexity and based on Two-Way String Matching algo (that is alien looking and based on math
Complexity
-
Time complexity: \(O(n^2|n)\)
-
Space complexity: \(O(1|n)\)
Code
fun rotateString(s: String, g: String) =
s.length==g.length && g in s+s
pub fn rotate_string(s: String, g: String) -> bool {
let (s,g) = (s.as_bytes(), g.as_bytes());
let (mut p, mut j) = (vec![0; g.len()], 0);
for i in 1..p.len() {
while j > 0 && g[i] != g[j] { j = p[j-1] }
if g[i] == g[j] { j += 1}; p[i] = j
}; j = 0;
p.len() == s.len() && (0..s.len() * 2).any(|i| {
while j > 0 && s[i%s.len()] != g[j] { j = p[j-1] }
if s[i%s.len()] == g[j] { j += 1 }; j == p.len()
})
}
02.05.2026
788. Rotated Digits medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1346
Problem TLDR
Count numbers in 0..n with mirrored digits 2-5 6-9, 0,1,8, but not 3,4,7
Intuition
Brute-force is accepted. The logN solution:
- each digit is a start of the subtree
- in the subtree we have seven numbers total 0,1,2,5,6,8,9 and three numbers we should avoid to form tail from them - 0,1,8
- the tails length is K, means total numbers count is 7^K, and to avoid is 3^K
- if prefix has good number 2-5,6-9 then suffix can take all 7^K in its tail
Approach
- regex [0125689]* means any good prefix, [2569] must have any of this numbers, [0125689]* any good suffix
Complexity
-
Time complexity: \(O(n|logN)\)
-
Space complexity: \(O(1)\)
Code
fun rotatedDigits(n: Int) = (1..n).count {
Regex("^[0125689]*[2569][0125689]*$") in "$it"
}
pub fn rotated_digits(n: i32) -> i32 {
let s = n.to_string(); let l = s.len() as u32;
let (mut p7, mut p3, mut r, mut m) = (7_i32.pow(l), 3_i32.pow(l), 0, 0);
for c in s.bytes() {
p7 /= 7; p3 /= 3; let c = (c - 48) as i32;
for d in 0..c
{ r += (1-(152>>d&1))*(p7 - if (m | 1 << d) & 612 > 0 { 0 } else { p3 }) }
m |= 1 << c; if m & 152 > 0 { return r; }
} r + (m & 612 > 0) as i32
}
01.05.2026
396. Rotate Function medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1345
Problem TLDR
Max rolling hash
Intuition
// 0a 1b 2c 3d
// 0b 1c 2d 3a
// +3 -1 -1 -1
// 3a-(b+c+d)
// 0c 1d 2a 3b
// +3 -1 -1 -1
Reuse the previous hash to make a new. 0a1b2c3d converts to 0b1c2d3a=prev+3a-(b+c+d)=prev+3a-(sum-a)=prev+size*a-sum
Approach
- Rust has a nice way to (0..).zip(&n)
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
fun maxRotateFunction(n: IntArray) = n.run {
val s = sum(); var a = indices.sumOf { it*n[it] }
maxOf { x -> a.also { a += size*x - s }}
}
pub fn max_rotate_function(n: Vec<i32>) -> i32 {
let (s, mut f) = (0..).zip(&n).fold((0,0), |(s,f),(i,x)|(s+x,f+i*x));
n.iter().map(|x| (f, f+=n.len()as i32*x-s).0).max().unwrap()
}
30.04.2026
3742. Maximum Path Score in a Grid medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
Problem TLDR
Max right-bottom path value with at most k cost
Intuition
Recursive DP: at each cell pick max between right and bottom. Bottom-up DP: at each cell check all costs up and left.
Approach
- return some big negative value
- bottom-up: continue the costs c in 0..k curr[c+cost] = max(L,T) + value
Complexity
-
Time complexity: \(O(n^3)\)
-
Space complexity: \(O(n^3 | n^2)\)
Code
fun maxPathScore(g: Array<IntArray>, k: Int): Int {
val dp = HashMap<Int, Int>()
fun dfs(x:Int, y:Int, c:Int): Int = dp.getOrPut(x*40000+y*200+c) {
val nc = c+((g.getOrNull(y)?.getOrNull(x)?:4000)+1)/2;
if (nc > k) -99999 else g[y][x] +
if (x==g[0].size-1&&y==g.size-1)0 else max(dfs(x+1,y,nc),dfs(x,y+1,nc))
}
return dfs(0, 0, 0).takeIf{it>=0} ?:-1
}
pub fn max_path_score(g: Vec<Vec<i32>>, k: i32) -> i32 {
let (k, mut dp) = (k as usize, vec![vec![-1;k as usize+1];g[0].len()]);
for (y,r) in g.iter().enumerate() { for (x,&v) in r.iter().enumerate() {
let (cost, mut curr) = (((v+1)/2)as usize, vec![-1; k+1]);
for c in 0..(k+1).saturating_sub(cost) {
let p = if x+y<1&&c<1{0} else { dp[x][c].max(if x>0{dp[x-1][c]}else{-1})};
if p >= 0 { curr[c+cost] = v + p }
}
dp[x] = curr
}} *dp[dp.len()-1].iter().max().unwrap()
}
29.04.2026
3225. Maximum Score From Grid Operations hard substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1343
Problem TLDR
Max sum adjacent to marked columns
Intuition
Didn’t solve.
// looks like DP
// at each column peek the best index, n^2 args and n inside = n^3
// how to add previous white when doing current black and not overcount
// 17 minute: my result is too much / too little
// meaning: my dp cases are wrong
// 1:18: TLE, O(n^4) solution
//
The O(n^4) idea: consider previous-previous(PP), previous(P) and the current (C) columns. Peek the best C to maximize sum of previous. Use prefix sums of columns, result = max(PS(max(C,PP)) - PS(P)) The O(n^3) idea jump from n^4: submit to hard rule: can we take values from the current column or should we skip them. That allows to drop PP.
Approach
- the idea jump is not obvious, requires graphic visualizaition of possible outcomes
Complexity
-
Time complexity: \(O(n^3)\)
-
Space complexity: \(O(n^2)\)
Code
fun maximumScore(g: Array<IntArray>): Long {
val dp = HashMap<Int, Long>(); val ps = Array(g.size+1){LongArray(g.size+1)}
for (x in g.indices) for (y in 1..g.size) ps[x+1][y] += ps[x+1][y-1]+g[y-1][x]
fun dfs(i: Int, p: Int, skip: Int):Long = if (i==g.size)0L else dp.getOrPut(i*400+p*2+skip) {
(0..g.size).maxOf { j ->
val a = dfs(i+1, j, 0); val b = dfs(i+1, j, 1)
if (skip > 0 && j > p) ps[i][j]-ps[i][p] + max(a, b)
else if (skip < 1 && j <= p) max(ps[i+1][p]-ps[i+1][j] + a, b) else 0L
}}
return max(dfs(0, 0, 0),dfs(0,0,1))
}
28.04.2026
2033. Minimum Operations to Make a Uni-Value Grid medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1341
Problem TLDR
Min ops to make all numbers equal by +-X
Intuition
// 1 4 x=3
//+3
//
// 1 8 8 8 8 x=7
//
// is the baseline binary searchable?
//
// 1 1 3 5 5 x=2
// 2 2 1 0 0
// 1 1 0 1 1
// 0 0 1 2 2
//
// 1 1 1 1 1 %2 same reminder
// subtract reminder
// 0 0 2 4 4, then divide by x
// 0 0 1 2 2 this is array of counts from zero
// now find a median?
// 2 4 6 8 x=2
// 1 2 3 4 sum=10
// maybe consider each item as base and check
// *
// 1 *
// 2 1 *
// 3 2 1 *
// 2 1 * 1
// 1 * 1 2
// * 1 2 3
//
// 1 4 4 5 8
// * 3 3 4 7 right=3+3+4+7=17 left = 0
// 3 * 0 1 4 right= 0+1+4=5=17-4*(4-1) left=0+(4-1)=3
// 3 0 * 1 4 right= 5-3*(0-0) left=3+(0-0)
// 4 1 1 * 3 right= 5-2*(5-4)=3 left=3+3*(5-4)=6
// 7 4 4 3 * right= 3-1*(8-5)=0 left=6+4*(8-5)=18
//
- baseline of each value sequence is value %X
- number of ops is (V - V%X)/X
- scan from left to right, see how number of ops to the right changes after each move
Approach
- if you know math, just use median, it is the middle of the array
- kotlin&rust has a cool way to flatten grid
Complexity
-
Time complexity: \(O(nm)\)
-
Space complexity: \(O(nm)\)
Code
fun minOperations(g: Array<IntArray>, v: Int) = g.reduce{a,b->a+b}
.sorted().run{sumOf {if((it-get(0))%v>0)return-1;abs(it-get(size/2))/v}}
pub fn min_operations(g: Vec<Vec<i32>>, x: i32) -> i32 {
let mut a=g.concat();a.sort();let m=a[a.len()/2];
if a.iter().any(|v|(v-a[0])%x!=0){-1}else{a.iter().map(|v|(v-m).abs()/x).sum()}
}
27.04.2026
1391. Check if There is a Valid Path in a Grid medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1341
Problem TLDR
Path 0 to end on type-cells 2D grid
Intuition
The union-find idea: connect all cells according to their types. Check if the target type complements current type. The single path idea: each cell has a single enter/exit so just check path from the left and from the top of the 0 cell.
Approach
- we can use transition matrix
- it can be shortened to strings of six sections each of 4 directions: current direction changes to target direction
- 82=2^1+w^4+2^6, 100=2^2+2^5+2^6, 466=2^1+2^4+2^6 + 2^(2+4)+2^(3+4)+2^(4+4)
Complexity
-
Time complexity: \(O(nm or path)\)
-
Space complexity: \(O(nm or 1)\)
Code
fun hasValidPath(g: Array<IntArray>): Boolean {
val w = g[0].size; val u = IntArray(g.size * w) { it }
fun f(x: Int): Int = if (x == u[x]) x else {u[x]=f(u[x]);u[x]}
for (i in u.indices) { val x = i%w; val y = i/w
if (x+1<w&&82 shr g[y][x]and 1>0&&g[y][x+1]%2>0) u[f(i)] = f(i+1)
if (y+1<g.size&&g[y][x]in 2..4&&100 shr g[y+1][x]and 1>0) u[f(i)]=f(i+w)
}
return f(0) == f(u.size - 1)
}
pub fn has_valid_path(g: Vec<Vec<i32>>) -> bool {
(0..2).any(|i| 466 >> g[0][0] + i * 4 & 1 > 0 &&
successors(Some((0, 0, i)), |&(y, x, d)| {
let (x,y) = ((x as i32+(1-d)%2)as usize, (y as i32+(2-d)%2)as usize);
let d = b"....0.2..1.31..2..1032...03."[(*g.get(y)?.get(x)?*4+d)as usize]as i32-48;
(d >= 0 && x | y > 0).then_some((y, x, d))
}).any(|(y, x, _)| y == g.len() - 1 && x == g[0].len() - 1)
)
}
26.04.2026
1559. Detect Cycles in 2D Grid medium substack youtube
https://dmitrysamoylenko.com/leetcode/

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1340
Problem TLDR
Check cycle in 2D grid
Intuition
The trivial idea: start DFS from each position, mark visited cells, check neighbours, skip parent. Have to mark visited cells again with different mark to not do DFS on the same group later. The mark in post-order should be different to make a wall for the next group.
The little bit more interesting idea: use Union-Find. Walk row by row and connect items. If there is a cycle then right cell would be already connected.
Approach
- the G is for ‘Good’
- use path compression for Union-Find
- do you know why we don’t searching the root for the down cell in Rust?
Complexity
-
Time complexity: \(O(nm)\)
-
Space complexity: \(O(nm)\)
Code
fun containsCycle(g: Array<CharArray>) = IntArray(g.size*g[0].size){it}
.let { u -> u.indices.any { i -> val w = g[0].size
fun f(x: Int): Int = if (u[x]==x) x else {u[x]=f(u[x]);u[x]}
fun c(j: Int, G: Boolean) = G && g[j/w][j%w] == g[i/w][i%w]
&&(f(i) == f(j) || { u[f(i)] = f(j); !G}())
c(i+1, i%w<w-1) || c(i+w, i+w<u.size)
}}
pub fn contains_cycle(g: Vec<Vec<char>>) -> bool {
let w=g[0].len(); let z=g.len()*w; let mut u:Vec<_>=(0..z).collect();
(0..z).any(|i|{
if i+w<z && g[i/w+1][i%w] == g[i/w][i%w] { u[i+w] = i }
i%w<w-1 && g[i/w][i%w+1] == g[i/w][i%w] && {
let [a,b] = [i, i+1].map(|mut x|{while x!=u[x]{u[x]=u[u[x]];x=u[x]}x});
a == b || {u[a] = b; 0>0}
}
})
}
25.04.2026
3464. Maximize the Distance Between Points on a Square hard substack youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1339
Problem TLDR
Max of minimum distnace between selected k points on square perimeter
Intuition
// if we use binary search the min distance:
// how can we peek k elements?
// how to peek first?
// | * * * * * * * * |(unrolled perimeter)
// |.........| dist
// so for every dist we should find the first item we take
// and then check all others
// dist - log(n)
// every first - n
// all others k fit? - n (maybe this can be improved)
// solution is n^2log(n)
//
// how to faster check k-fit?
// we stop as soon as we take k elements from start
// but what if dist is big and we have to skip n elements
// how to jump to element by dist?
//
// 1 2 3 5 6 8 9
// * (dist=5, how to jump to 5?)
// ^ binary search to this position?
// log(n)
// so the solution now is nklog^2(n)
// should be accepted
//
// now how to unroll?
// (already 18 minutes just for thinking)
// from 0,0 go clockwise
// 0,0 - 0,1 - 0,2 - 1,2 - 2,2 - 2,1 - 2,0 - (1,0)?
// or just take four edges then concat them
// 26 minute
// i have a doubt: the dist in binary search is not precise
// 29 minute, lets go hints (they basically the same idea)
//
// except hint about selecting elements: no binary search?
// 47 minute: wrong answer on test case side = 2 points = [[0,0],[1,2],[2,0],[2,2],[2,1]] k = 4
// 2 instead of 1
// 54 minute: i have error of duplicate on edges concatenations
// 1:10 minute: gosh i spot that i can't use binary search on a cycled perimeter coordinates
// ok let's give up, i can't spend more than 1 hour
Didn’t solved myself. Several aha-moments are required:
- flatten the perimeter, every point has perimeter-distance to 0,0, sort by it
- freeze the minimum at-most distance between points and binary search it
- to optimally take k points we have to scan for starting point
- to find next point from start we can use binary search
- we have to check wrap-around between first taken and last taken point, 4s-(last-first)
Approach
- symmetry allows nice conversion to distance: top and left is (x+y), bottom and right is (perimeter - (x+y))
- inner binary search can be from previous position
- upper bound of distance is perimeter/k
Complexity
-
Time complexity: \(O(nklog^2(n))\)
-
Space complexity: \(O(n)\)
Code
fun maxDistance(s: Int, p: Array<IntArray>, k: Int): Int {
val P = 4L*s; var L = 0L; var H = P/k
val e = p.map { (x,y) -> if (x==0||y==s)x+y+0L else P-x-y }.sorted()
while (L <= H) {
val M = (L + H) / 2
if (p.indices.any { i -> var j = i; var c = 1
do { j = e.binarySearch(e[j] + M,fromIndex=j); if (j < 0) j = -j-1 }
while (j < e.size && e[j] - e[i] <= P - M && ++c < k)
c == k
}) L = M + 1 else H = M - 1
}
return H.toInt()
}
pub fn max_distance(s: i32, p: Vec<Vec<i32>>, k: i32) -> i32 {
let (s, P, n, mut L, mut H) = (s as i64, 4*s as i64, p.len(), 0, 4*s as i64/k as i64);
let mut e = p.iter().map(|v| { let(x,y)=(v[0]as i64, v[1]as i64);
if x==0||y==s{x+y}else{P-x-y}}).sorted().collect_vec();
while L <= H {
let M = (L+H)/2;
if (0..n).any(|i| (1..k).try_fold(i, |j,_| {
let x = e[j..].partition_point(|&v| v < e[j]+M)+j;
(x < n && e[x]-e[i] <= P-M).then_some(x)
}).is_some()) { L = M + 1 } else { H = M - 1 }
} H as i32
}
24.04.2026
2833. Furthest Point From Origin easy substack youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1338
Problem TLDR
Max dist when replace _ with L or R
Intuition
The brute-force: replace all _ to R and check balance, then to L and check again. Some geometry transformation:_ + abs(R-L) = length-2*min(L,R) (see video explanation)
Approach
- asci %5 gives perfect 0,1,2 for _,L,R, do with that what you want
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
fun furthestDistanceFromOrigin(m: String) =
2*"LR".maxOf{c->m.count{it!=c}}-m.length
pub fn furthest_distance_from_origin(m: String) -> i32 {
(m.len()-2*m.matches('L').count().min(m.matches('R').count())) as _
}
23.04.2026
2615. Sum of Distances medium substack youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1337
Problem TLDR
Sum of distances to each occurance
Intuition
Didn’t solved without a hint.
// 0123456789
// a...a....a...
// i j j 4+9
// j i j 4+5
// j j i 9+5
//
// a b c d
// * |a-b|+|a-c|+|a-d|=b-a + b-a+c-b + b-a+c-b+d-c=-3a+b+c+d
// * |a-b|+|b-c|+|b-d|=b-a + c-b + c-b+d-c=-a-b+c+d
// * |a-c|+|b-c|+|c-d|=b-a+c-b + c-b + d-c=-a-b+c+d
// * |a-d|+|b-d|+|c-d|= b-a+c-b+d-c + c-b+d-c + d-c=-a-b-c+3d
// any way to shortcut this?
//
// a b c d e f
// * 5f-e-d-c-b-a sum+4f-2e-2d-2c-2b-2a -sum+6f
// * f-e + 4e-d-c-b-a = f+3e-d-c-b-a sum+2e-2d-2c-2b-2a
// * f-d+e-d + 3d-c-b-a = f+e+d -c-b-a sum-2c-2b-2a
// * f-c+e-c+d-c + 2c-b-a = f+e+d -c-b-a sum-2c-2b-2a
// * f-b+e-b+d-b+c-b+b-a = f+e+d+c-3b-a sum-4b-2a
// * f-a+e-a+d-a+c-a+b-a = f+e+d+c+b-5a sum -6a
// ok what the rule?
// (acceptance rate 40%)
// from hints: freq*idx-sum
// a b c d
// +x=prev+x
// +x+2y=prev+2y
// +x+2y+3z=prev+3z
The simple working intuition:
- consider only forward pass for now
- each position sum is the previous positions sum plus frequency so-far count of distances to last occurence
Approach
- we can iterate once but with two cursors: forward and backward and duplicate pairs of variables have to be tracked
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
fun distance(n: IntArray) = LongArray(n.size).apply {
val m = Array(2) { HashMap<Int, LongArray>() }
for (i in n.indices) for ((j,s) in listOf(i to 2, (size - 1 - i) to 0))
m[s/2].getOrPut(n[j]) { LongArray(2) }.let { a ->
this[j] += (s-1) * (j * a[0] - a[1]); a[0]++; a[1] += 1L*j
}
}
pub fn distance(n: Vec<i32>) -> Vec<i64> {
let (mut r, mut m) = (vec![0; n.len()], HashMap::new());
for i in 0..n.len() { for (j, d,s) in [(i, 1,1), (n.len() - 1 - i, 0,-1)] {
let e = m.entry(n[j]).or_insert([(0, 0); 2]);
r[j] += s * (j as i64 * e[d].0 - e[d].1);
e[d].0 += 1; e[d].1 += j as i64;
}} r
}
22.04.2026
2452. Words Within Two Edits of Dictionary medium substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1336
Problem TLDR
Words in dictionary with 2 edits #medium
Intuition
- We can place all single-edits of dictionary into a hash set, then check single-edits of words.
- Or just brute-force with the same time complexity
Approach
- Rust has
retain
Complexity
-
Time complexity: \(O(n^3)\)
-
Space complexity: \(O(n)\)
Code
// 28ms
fun twoEditWords(q: Array<String>, d: Array<String>) =
q.filter { q -> d.any { d -> d.indices.count { d[it] != q[it]} < 3 }}
// 1ms
pub fn two_edit_words(mut q: Vec<String>, d: Vec<String>) -> Vec<String> {
q.retain(|q| d.iter().any(|d| d.bytes().zip(q.bytes()).filter(|(d,q)|d!=q).count()<3)); q
}
21.04.2026
1722. Minimize Hamming Distance After Swap Operations medium substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1335
Problem TLDR
Diff src vs target after rearrange by rules #medium #uf
Intuition
// we can form connected islands of numbers
// can change only src
// [a,b,c,d,e,f]
// * * * island, then sort or take from hashmap-with-counter by target
//
- intersected swaps form connected islands
- we can sort both src&target inside each island
- we can use counting sort
Approach
- union-find to find islands
- path compression
- Rust: itertools
counts() - Kotlin: Array of hashmaps shorter than groupBy
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 68ms
fun minimumHammingDistance(s: IntArray, t: IntArray, a: Array<IntArray>): Int {
val u = IntArray(s.size) { it }; val fvc = Array(s.size) { HashMap<Int,Int>() }
fun f(x: Int): Int = { if (x != u[x]) u[x] = f(u[x]); u[x] }()
for ((a,b) in a) u[f(a)] = f(b)
for ((i,v) in s.withIndex()) fvc[f(i)][v] = 1 + (fvc[f(i)][v] ?: 0)
return s.indices.count { i ->
val c = fvc[f(i)][t[i]] ?: 0
if (c > 0) fvc[f(i)][t[i]] = c-1; c <= 0
}
}
// 33ms
pub fn minimum_hamming_distance(s: Vec<i32>, t: Vec<i32>, a: Vec<Vec<i32>>) -> i32 {
let mut u: Vec<_> = (0..s.len()).collect();
fn f(u: &mut [usize], x: usize) -> usize { if u[x] != x { u[x] = f(u, u[x]) } u[x] }
for p in a { let (x, y) = (f(&mut u, p[0] as _), f(&mut u, p[1] as _)); u[x] = y; }
let mut m = (0..s.len()).map(|i|(f(&mut u,i),s[i])).counts();
(0..s.len()).filter(|&i| {
let c = m.entry((f(&mut u,i),t[i])).or_default();
if *c > 0 { *c -= 1; false } else { true }
}).count() as _
}
20.04.2026
2078. Two Furthest Houses With Different Colors easy substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1334
Problem TLDR
Max distance between different numbers #easy
Intuition
Brute-force.
Clever solution: first or last is guaranteed to be included (if first==last its entire size, if first!=last then there is a third color in-between).
Approach
- scan all indices, pick max to first or last
- downsize the max length while prefix and suffix of this length is not good
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 14ms
fun maxDistance(c: IntArray) =
c.indices.last { c[0]!=c[it] || c.last()!=c[c.size-1-it] }
// 0ms
pub fn max_distance(c: Vec<i32>) -> i32 {
let n=c.len()-1; (0..n+1).rposition(|l|c[0]!=c[l]||c[n]!=c[n-l]).unwrap() as _
}
19.04.2026
1855. Maximum Distance Between a Pair of Values medium

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1333
Problem TLDR
Max distance a[i] not greater than b[j] #medium #sliding_window
Intuition
- Sliding window: for each left pointer move the rigth as far as possible
- Max-window: always expand the window, shrink window only when condition is broken
Approach
- the max-window is more clever
- binary search would also work
Complexity
-
Time complexity: \(O(n)\), nlog(n) for binarysearch
-
Space complexity: \(O(1)\)
Code
// 81ms
fun maxDistance(a: IntArray, b: IntArray) = maxOf(0, a.indices
.maxOf { i -> -b.asList().binarySearch { if (it < a[i]) 1 else -1 }-i-2 })
// 3ms
pub fn max_distance(a: Vec<i32>, b: Vec<i32>) -> i32 {
let (mut i, mut j) = (0, 0);
while i < a.len() && j < b.len() { if a[i] > b[j] { i += 1 }; j += 1}
0.max(j as i32 - i as i32 - 1)
}
18.04.2026
3783. Mirror Distance of an Integer easy substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1332
Problem TLDR
Diff with reversal #easy
Intuition
Reverse and subtract. Can’t be done in-place, because we need to know the length of number.
Approach
- Kotlin’s shortest is strings reversal
- Rust doesn’t have divmod, but can use asm that will mutate ‘x’ and return reminder
let d: i32; unsafe { asm!("cdq;div {0}", in(reg) 10, inout("eax") x, out("edx") d) }
Complexity
-
Time complexity: \(O(lg(n))\)
-
Space complexity: \(O(1)\)
Code
// 10ms
fun mirrorDistance(n: Int) =
abs(n - "$n".reversed().toInt())
// 0ms
pub fn mirror_distance(n: i32) -> i32 {
let (mut r, mut x) = (0, n);
while x > 0 { r = r*10+x%10; x/=10}; (r-n).abs()
}
17.04.2026
3761. Minimum Absolute Distance Between Mirror Pairs medium substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1331
Problem TLDR
Distance to prev mirror number #medium
Intuition
Use a hashmap, scan, put mirrors into map, check for current number.
Approach
- Kotlin: string conversion is shorter
- Rust: (0..).zip(n), filter_map
Complexity
-
Time complexity: \(O(m)\)
-
Space complexity: \(O(n)\)
Code
// 232ms
fun minMirrorPairDistance(n: IntArray) = HashMap<Int, Int>().let { m ->
n.indices.minOf { i ->
i - (m[n[i]] ?: -n.size).also { m["${n[i]}".reversed().toInt()] = i }
}.takeIf { it < n.size } ?: -1
}
// 19ms
pub fn min_mirror_pair_distance(n: Vec<i32>) -> i32 {
let mut m = HashMap::new();
(0..).zip(n).filter_map(|(i, mut x)| {
let d = m.get(&x).map(|j| i-j);
let mut r = 0; while x > 0 {r = r*10+x%10; x /= 10}
m.insert(r, i); d
}).min().unwrap_or(-1)
}
16.04.2026
3488. Closest Equal Element Queries medium substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1330
Problem TLDR
Shortest distances to the same values #medium
Intuition
// [1,3,1,4,1,3,2], queries = [0,3,5]
// * * *
// brute force is n^2
// 0 2 4 *
// for each find the closest to the right and to the left
// to the left
// ? 2 2 (and update first to (first+size-i)
// to the right
// 2 2 ? (and update last to (size-last+i))
//
In a 2*n forward pass updated the distance to the previous value and to the current value.
Approach
- HashMap’s put in Kotlin and insert in Rust returns the previous value
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 104ms
fun solveQueries(n: IntArray, q: IntArray) = HashMap<Int,Int>().run {
val z = n.size; val d = IntArray(z) { z }
for (i in 0..<2*z) put(n[i%z], i)?.let { p ->
d[i%z] = min(d[i%z], i-p); d[p%z] = min(d[p%z], i-p)
}
q.map { d[it].takeIf { it < z } ?: -1 }
}
// 38ms
pub fn solve_queries(n: Vec<i32>, q: Vec<i32>) -> Vec<i32> {
let z = n.len(); let (mut p, mut d) = (HashMap::new(), vec![z;z]);
for i in 0..2*z { if let Some(p) = p.insert(n[i%z], i) {
d[i%z] = d[i%z].min(i-p); d[p%z] = d[p%z].min(i-p)
}}
q.iter().map(|&i|if d[i as usize]<z {d[i as usize] as i32}else{-1}).collect()
}
15.04.2026
2515. Shortest Distance to Target String in a Circular Array easy substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1329
Problem TLDR
Distance to target #easy
Intuition
- (s+dist)%n forward
- (s-dist)%n backward
Approach
- don’t forget s
- Kotlin has
.modthat handles sign, indexOfFirst vs firstOrNull - Rust:
find
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 14ms
fun closestTarget(w: Array<String>, t: String, s: Int) =
w.indices.indexOfFirst { w[(s + it)%w.size]==t || w[(s-it).mod(w.size)]==t }
// 0ms
pub fn closest_target(w: Vec<String>, t: String, s: i32) -> i32 {
let n = w.len() as i32;
(0..n).find(|i| w[((s + i) % n) as usize] == t || w[((s - i + n) % n) as usize] == t).unwrap_or(-1)
}
14.04.2026
2463. Minimum Total Distance Traveled hard substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1328
Problem TLDR
Shortest distances to travel robots to factories #hard #dp
Intuition
Didn’t solve without the hints.
// does speed matters?
//
// match each robot to each factory?
//
// r r f f
//
// the dp state can be cached by robots directions in a tail + factories
//
// the only thing is: does the order/speed matter?
//
// another idea: start BFS from each robot
// remove factory hits as repaired
// but: positions are 10^9, we can't simulate travel
//
// can travel by entire distance at once?
// put in a next_timestamp priority queue
//
// 27 minute wrong answer, mine bigger, meaning not optimal
// bfs didn't work here
// [9,11,99,101] [[10,1],[7,1],[14,1],[100,1],[96,1],[103,1]]
// 30 minute look for hint: segments
//
// r f r r f
// *****
//
Consider each robot from left to right to pick or skip factory from left to right.
Approach
- iterative version can save some space
Complexity
-
Time complexity: \(O(nfl)\)
-
Space complexity: \(O(nfl)\)
Code
// 254ms
fun minimumTotalDistance(r: List<Int>, f: Array<IntArray>): Long {
val r = r.sorted(); val dp = HashMap<Int, Long>()
val f = f.sortedBy { it[0] }.flatMap { f -> List(f[1]) { f[0] }}
fun dfs(i: Int, j: Int): Long = if (i == r.size) 0L else
if (j == f.size) Long.MAX_VALUE/2 else
dp.getOrPut(i*10000+j) { min(abs(r[i]-f[j]) + dfs(i+1, j+1), dfs(i, j+1)) }
return dfs(0, 0)
}
// 2ms
pub fn minimum_total_distance(r: Vec<i32>, f: Vec<Vec<i32>>) -> i64 {
let f: Vec<_> = f.into_iter().sorted_by_key(|v|v[0])
.flat_map(|v|vec![v[0]; v[1] as usize]).collect();
let mut dp = vec![0; f.len() + 1];
for p in r.into_iter().sorted() {
let mut prev = dp[0]; dp[0] = i64::MAX/2;
for j in 0..f.len() {
let t = dp[j+1]; dp[j+1] = ((p-f[j]).abs() as i64 + prev).min(dp[j]); prev = t }
} dp[f.len()]
}
13.04.2026
1848. Minimum Distance to the Target Element easy substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1327
Problem TLDR
Distance to target from start #easy
Intuition
Iterate from left to right. Or iterate from the start.
Approach
- Kotlin ‘zip’ doesn’t work with non-equal ranges
- Rust itertools has ‘interleave’, abs_diff
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 16ms
fun getMinDistance(n: IntArray, t: Int, s: Int) =
n.indices.filter { n[it] == t }.minOf { abs(it - s) }
// 0ms
pub fn get_min_distance(n: Vec<i32>, t: i32, s: i32) -> i32 {
(0..=s as usize).rev().interleave(s as usize+1..n.len())
.find(|&i| n[i] == t).unwrap().abs_diff(s as usize) as _
}
12.04.2026
1320. Minimum Distance to Type a Word Using Two Fingers hard substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1326
Problem TLDR
Min travel on keyboard to type a word #hard #dp
Intuition
// len is 300, table = 26
// two fingers
// travel finger 1 + travel finger 2
//
// HAPPY
// 11221
// can be dp i, f1, f2 = dist 300*26^2
// should work
// 11 minute, 45/55 test case wrong answer 294 vs 295 expected
// mine is better means my algo cheats
//
Top down dp is accepted. (position, finger1, finger2)
The clever intuition:
- at each step we have a situation: current target is w[i], one finger definitely at w[i-1], search for the other finger
- dp[a] is how much maximum we saved using extra finger finally placed at a
- dp[b] = max(A..Z -travel(a,c) +travel(b,c) + dp[a]), this finger ‘saves’ us from travel(bc) and makes us travel(ac)
- we store in dp[b] because we place finger on c and c became b at the next step
Approach
- write top down, its ok
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 35ms
fun t(a: Char, b: Char) = abs((a-'A')%6-(b-'A')%6) + abs((a-'A')/6-(b-'A')/6)
fun minimumDistance(w: String) = w.zipWithNext(::t).sum() -
w.zipWithNext().fold(IntArray(26)) { dp, (b,c) ->
dp[b-'A'] = ('A'..'Z').maxOf { dp[it-'A'] - t(it,c) } + t(b,c); dp
}.max()
// 0ms
pub fn minimum_distance(w: String) -> i32 {
fn t(a: i32, b: i32) -> i32 { (a%6-b%6).abs() + (a/6-b/6).abs() }
let (s, m) = w.bytes().map(|b|(b-b'A') as i32).tuple_windows().fold((0,[0;26]), |(s, mut dp), (b,c)| {
dp[b as usize] = (0..26).map(|a| dp[a as usize]-t(a,c)).max().unwrap() + t(b,c); (s + t(b,c), dp)
}); s - m.into_iter().max().unwrap()
}
11.04.2026
3741. Minimum Distance Between Three Equal Elements II medium substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1325
Problem TLDR
Min sum of distances between i,j,k of the same values #medium
Intuition
Same as yesterday: keep two previous indices. Sum of abs (i,j,k) is 2*(i-k).
fun minimumDistance(n: IntArray) = n
.indices.groupBy{n[it]}.values
.flatMap { it.windowed(3) { 2 * (it[2]-it[0])}}
.minOrNull() ?: -1
pub fn minimum_distance(n: Vec<i32>) -> i32 {
(0..n.len()).into_group_map_by(|&i| n[i]).values()
.flat_map(|v| v.windows(3).map(|w|2*(w[2]-w[0]) as i32))
.min().unwrap_or(-1)
}
Approach
- let’s write optimized versions
- my yesterday golfed solutiona are also accepted
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 85ms
fun minimumDistance(n: IntArray) =
LongArray(100001){-1}.let { p -> n.indices.minOf { i ->
val j = p[n[i]]; p[n[i]] = j shl 32 or 1L*i
if (j >= 0) 2L*(i-(j shr 32)) else Long.MAX_VALUE
}.takeIf { it < Long.MAX_VALUE } ?: -1L }
// 16ms
pub fn minimum_distance(n: Vec<i32>) -> i32 {
let mut p = [-1i64; 100001];
(0..n.len()).filter_map(|i| {
let j = p[n[i] as usize]; p[n[i] as usize] = j<<32|i as i64;
(j >= 0).then(|| 2*(i as i64 - (j>>32)) as i32)
}).min().unwrap_or(-1)
}
10.04.2026
3740. Minimum Distance Between Three Equal Elements I easy substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1324
Problem TLDR
Min sum of distances between i,j,k of the same values #easy
Intuition
Brute-force.
Approach
- 2*(k-i) is the math optimization
- [101] is the space optimization
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 32ms
fun minimumDistance(n: IntArray) = n
.indices.groupBy{n[it]}.values
.flatMap { it.windowed(3) { 2 * (it[2]-it[0])}}
.minOrNull() ?: -1
// 0ms
pub fn minimum_distance(n: Vec<i32>) -> i32 {
(0..n.len()).into_group_map_by(|&i| n[i]).values()
.flat_map(|v| v.windows(3).map(|w|2*(w[2]-w[0]) as i32))
.min().unwrap_or(-1)
}
09.04.2026
3655. XOR After Range Multiplication Queries II hard blog post youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1323
Problem TLDR
Run stepped multiplication queries #hard #mod
Intuition
Almost solved, gave up.
// same as yesterday
// i learned it before: split queries by sqrt(k)
// a^x = a^{2*(x/2 + x%2)} = (a*a)^{x/2}*(a*a)^{x%2}
// 18 minute, there is an error somewhere
// 28 minute, 2 errors fixes, still wrong answer
// nums =
//[2,3,1,5,4]
//queries =
//[[1,4,2,3],[0,2,1,2]]
// 4, 18, 2, 15, 4 -- expected
//
// 2, 3, 1, 5, 4
// 4, 6, 2, 5, 4 (after k=1 l..r=0..2 v=2)
// 4, 18, 6, 15, 12 -- mine (after k=2 l..r=1..4 v=3) (looks like i multiplied all without step)
// * *
// 42 minute: how to deal with step?
// 45 minute: another test case wrong 68/605
// 49 minute: i don't see any error in my code
//
// nums =
// [562,62]
// queries =
// [[0,1,2,7],[1,1,2,11],[0,1,2,2],[1,1,1,11],[1,1,2,1],[0,0,1,9],[0,1,2,4],[1,1,1,6],[0,0,2,17]]
// Output
// 591836426
// Expected
// 4839076
// 58 minute gave up.
- Divide problem on slow/fast path: k = sqrt(q) is the point of separation
- fast path is the big k steps, can be brute forced
- slow path: save events of start-stop for every k in p[k][l..r] individually
- collect them for every k separately
- modulo doesnt allow 1/v operation, have to use pow(v, M-2) instead
Approach
- my point of failure was the attention to one detail: when to cancel, it is not r+1, we have to use steps
- the threshold of 40: ~300ms vs 400: ~1300ms
Complexity
-
Time complexity: \(O(nsqrt(q))\)
-
Space complexity: \(O(nsqrt(q))\)
Code
// 323ms
fun xorAfterQueries(n: IntArray, q: Array<IntArray>): Int {
val p = Array(40) { IntArray(n.size+1){1} }; val M = 1_000_000_007L
fun pow(a: Long, b: Long): Long = if (b==0L) 1L else pow(a*a%M, b/2)*(if (b%2>0)a else 1L)%M
for ((l,r,k,v) in q)
if (k >= 40) for (i in l..r step k) n[i] = (1L*n[i]*v%M).toInt() else {
p[k][l] = (1L*p[k][l]*v%M).toInt(); val next = l + ((r-l)/k+1)*k
if (next < n.size) p[k][next] = (1L*p[k][next]*pow(1L*v, M-2L)%M).toInt()
}
for (k in 1..<40) for (i in n.indices) {
if (i >= k) p[k][i] = (1L*p[k][i]*p[k][i-k]%M).toInt()
n[i] = (1L*n[i]*p[k][i]%M).toInt()
}
return n.reduce(Int::xor)
}
// 322ms
pub fn xor_after_queries(mut n: Vec<i32>, q: Vec<Vec<i32>>) -> i32 {
const M: i64 = 1000000007; let z = n.len(); let mut c = vec![vec![1; z + 1]; 40];
fn p(a: i64, b: i64) -> i64 { if b < 1 { 1 } else { p(a * a % M, b / 2) * (if b % 2 > 0 { a } else { 1 }) % M } }
for u in q {
let (l, r, k, v) = (u[0] as usize, u[1] as usize, u[2] as usize, u[3] as i64);
if k < 40 { c[k][l] = c[k][l] * v % M; let x = r - (r - l) % k + k; if x < z { c[k][x] = c[k][x] * p(v, M - 2) % M } }
else { for i in (l..=r).step_by(k) { n[i] = (n[i] as i64 * v % M) as i32 } }
}
for k in 1..40 { for i in 0..z {
if i >= k { c[k][i] = c[k][i] * c[k][i - k] % M }
n[i] = (n[i] as i64 * c[k][i] % M) as i32;
}}
n.into_iter().fold(0, |a, b| a ^ b)
}
08.04.2026
3653. XOR After Range Multiplication Queries I medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1322
Problem TLDR
Run queries #medium
Intuition
Just run queries.
Approach
- cast to long in-place
Complexity
-
Time complexity: \(O(nq)\)
-
Space complexity: \(O(1)\)
Code
// 96ms
fun xorAfterQueries(n: IntArray, q: Array<IntArray>) = n.apply {
for ((l,r,k,v) in q) for (i in l..r step k)
n[i] = ((1L*n[i] * v) % 1000000007).toInt()
}.reduce(Int::xor)
// 56ms
pub fn xor_after_queries(mut n: Vec<i32>, q: Vec<Vec<i32>>) -> i32 {
for v in q { for i in (v[0] as usize..=v[1] as _).step_by(v[2] as _) {
n[i] = (n[i] as i64 * v[3] as i64 % 1000000007) as _
}}
n.into_iter().fold(0, |a, b| a ^ b)
}
07.04.2026
2069. Walking Robot Simulation II medium substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1321
Problem TLDR
Implement perimeter-robot #medium
Intuition
// 15 minute: so this TLE
//
// does robot always goes on perimeter? -- yes
//
// make it linear
//
// xxxxxyyyxxxxxyyyxxxxxyyyxxxxxyyy
// w h w h 0
//
// each rotation is extra step? - no
- its only the perimeter
- w-1, h-1
- top-down south
Approach
- extract separate method
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 146ms
class Robot(a: Int, b: Int, var p: Int = 0) {
val w=a-1; val h=b-1; val wh=w+w+h+h
val i get() = when (val m = p % wh) {
in 0..w -> listOf(m, 0) to if(m==0 && p>0) "South" else "East"
in 0..w+h -> listOf(w, m-w) to "North"
in 0..wh-h -> listOf(wh-h-m, h) to "West"
else -> listOf(0, wh-m) to "South"
}
fun step(n: Int) { p += n }; fun getPos() = i.first; fun getDir() = i.second
}
// 16ms
struct Robot(i32, i32, i32, i32); impl Robot {
fn new(a: i32, b: i32) -> Self { Self(a-1, b-1, 2*a+2*b-4, 0) }
fn step(&mut self, n: i32) { self.3 += n }
fn i(&self) -> (Vec<i32>, &'static str) {
let (w, h, t, p, m) = (self.0, self.1, self.2, self.3, self.3 % self.2);
if m <= w { (vec![m, 0], if p>0 && m==0 {"South"} else {"East"}) }
else if m <= w+h { (vec![w, m-w], "North") }
else if m <= t-h { (vec![t-h-m, h], "West") }
else { (vec![0, t-m], "South") }
}
fn get_pos(&self) -> Vec<i32> { self.i().0 }
fn get_dir(&self) -> String { self.i().1.into() }
}
06.04.2026
874. Walking Robot Simulation medium substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1320
Problem TLDR
Farthest robot movement #medium #simulation
Intuition
Just simulate the movements, 1..9 can be iterated.
Approach
- to compress position into a single variable, we have to make coordinates positive
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(o)\)
Code
// 41ms
fun robotSim(c: IntArray, o: Array<IntArray>): Int {
val S = o.map { it[1]+32768 shl 16 or it[0]+32768 }.toSet()
var d = 0; var p = -2147450880; val D = listOf(65536, 1, -65536, -1)
return c.maxOf {
if (it < 0) d = (d - 2*it - 1) % 4
repeat(it) { if (p+D[d] !in S) p += D[d] }
val x = (p and 65535) - 32768; val y = (p ushr 16) - 32768
x*x + y*y
}
}
// 1ms
pub fn robot_sim(c: Vec<i32>, o: Vec<Vec<i32>>) -> i32 {
let s: HashSet<_> = o.iter().map(|v| v[1]+32768<<16 | v[0]+32768).collect();
let (mut p, mut d, D) = (-2147450880,0, [65536, 1, -65536, -1]);
c.into_iter().fold(0, |m, i| {
if i < 0 { d = (d + if i < -1 { 3 } else { 1 }) % 4 }
for _ in 0..i { if !s.contains(&(p + D[d])) { p += D[d] } }
let (x, y) = ((p & 65535) - 32768, (p as u32 >> 16) as i32 - 32768);
m.max(x*x + y*y)
})
}
05.04.2026
657. Robot Return to Origin easy

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1319
Problem TLDR
R,L,U,D return to 0 in XY plane #easy
Intuition
Compare counts separately for vertical and horizontal directions. Both directions can fit into a single variable h*2^16+v.
Approach
- hash collisions of 8 make the solution extra spicy
- do you know how %5 works?
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 38ms
fun judgeCircle(m: String) =
0==m.sumOf {listOf(8,-1,1,-8)[it.code%5]}
// 0ms
pub fn judge_circle(m: String) -> bool {
0==m.bytes().fold(0,|a,b|a+[8,-1,1,-8][(b%5)as usize])
}
04.04.2026
2075. Decode the Slanted Ciphertext medium substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1318
Problem TLDR
Decode row-encoded string #medium
Intuition
Spaces at the end is not allowed for original string. That means we can simply decode with the end condition, then trim.
Approach
- Kotlin: trimEnd
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 38ms
fun decodeCiphertext(e: String, r: Int) = buildString {
val skip = e.length/r + 1
for (j in 0..<skip) for (i in 0..<r)
if (j + i * skip < e.length) append(e[j + i * skip])
}.trimEnd()
// 8ms
pub fn decode_ciphertext(e: String, r: i32) -> String {
let (s, mut ans) = (e.len() / r as usize + 1, String::new());
for j in 0..s { for i in 0..r as usize {
if j + i * s < e.len() { ans.push(e.as_bytes()[j + i * s] as char) }}}
ans.trim_end().into()
}
03.04.2026
3661. Maximum Walls Destroyed by Robots hard substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1317
Problem TLDR
Max walls hit, each robot shoot left or right #hard #dp
Intuition
Didn’t solve.
// 1 4 10
// < * * * * >
// 1 7
// 4-3..4+3
// ranges intersection:
// *ab***
//
// ***a*b**
// count all walls in ranges
//
// 0 1 2 3 4 5 6 7 8 9 10
// * r * * * * * * r
// w w w
//
// 27minute wrong answer 523/602 test case
//
// so the wrong was my understanding of the problem
// each robot have to choose which way to shoot, not both
//
Dp state: current robot and should it account for previous robot range.
Approach
- sort
- start with top-down dp
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 500ms
fun maxWalls(r: IntArray, d: IntArray, w: IntArray): Int {
val x = r.indices.sortedBy { r[it] }; w.sort(); val dp = HashMap<Int, Int>()
val bs = { v: Int -> w.binarySearch(v).let { max(it.inv(), it) }}
fun cnt(a: Int, b: Int) = if (a > b) 0 else bs(b+1)-bs(a)
fun dfs(i: Int, clipLeft: Int): Int = if (i == r.size) 0 else dp.getOrPut(i*d.size*2+clipLeft) {
val p = r[x[i]]; val rad = d[x[i]]
val prev = if (i < 1) 0 else if (clipLeft>0) min(r[x[i-1]]+d[x[i-1]],p-1) else r[x[i-1]]
val L = max(p-rad, prev + 1)
val R = min(p+rad, if (i+1 < r.size) r[x[i+1]]-1 else Int.MAX_VALUE)
max(cnt(L, p) + dfs(i+1, 0), cnt(p, R) + dfs(i+1, 1))
}
return dfs(0, 0)
}
02.04.2026
3418. Maximum Amount of Money Robot Can Earn medium youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1316
Problem TLDR
Max sum path, 2 skips allowed #medium #dp
Intuition
// how to pick two optimal robbers?
//
// dp?
//
// can be greedy (min,max)? - no, we have to track all possibilites
// and they will grow at 2^x rate
// so should be dp
//
The top-down DFS + memo is the simplest and robust choice without extra thinking required.
Approach
- bottom-up: for each cell store 3 best values: (zero skips left, 1 skip left, 2 skips left)
Complexity
-
Time complexity: \(O(nm)\)
-
Space complexity: \(O(m)\)
Code
// 329ms
fun maximumAmount(c: Array<IntArray>) = HashMap<Int, Int>().run {
fun d(y: Int, x: Int, r: Int): Int = getOrPut(y*4000+x*4+r) {
c.getOrNull(y)?.getOrNull(x)?.let { v ->
fun n(k: Int) = max(d(y+1, x, k), d(y, x+1, k))
if (v < 0 && r > 0) max(v + n(r), n(r-1)) else v + n(r)
} ?: if (y == c.size && x == c[0].size - 1) 0 else -9999999
}
d(0, 0, 2)
}
// 7ms
pub fn maximum_amount(c: Vec<Vec<i32>>) -> i32 {
let mut d = vec![[-9999999;3]; c[0].len()+1]; d[1] = [0;3];
for r in c { for x in 1..d.len() {
let (v, p) = (r[x-1], [0,1,2].map(|i| d[x-1][i].max(d[x][i])));
d[x] = [p[0]+v, p[0].max(p[1]+v), p[1].max(p[2]+v)]
}} d[d.len()-1][2]
}
01.04.2026
2751. Robot Collisions hard youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1315
Problem TLDR
Collide LR robots #hard #stack
Intuition
// 1. sort by position
// 2. simulation is too big, need a O(n) algorithm
// 3. R R L R L
// 2 2 1 1 3
// 2 1 0
// 2 1 0 0 2
// 2 0 0 0 1
// 1 0 0 0 0
Sort. Use stack.
Approach
- we can re-use p array as a stack
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(n)\)
Code
// 70ms
fun survivedRobotsHealths(p: IntArray, h: IntArray, d: String) = run {
var t = -1; for (i in p.indices.sortedBy { p[it] })
if (d[i] == 'R') p[++t] = i else while (t >= 0 && h[i] > 0) when {
h[p[t]] > h[i] -> { h[p[t]]--; h[i] = 0 }
h[p[t]] < h[i] -> { h[p[t--]] = 0; h[i]-- }
else -> { h[p[t--]] = 0; h[i] = 0 }
}
h.filter { it > 0 }
}
// 11ms
pub fn survived_robots_healths(p: Vec<i32>, mut h: Vec<i32>, d: String) -> Vec<i32> {
let mut s = vec![];
for i in (0..p.len()).sorted_by_key(|&i| p[i]) {
if d.as_bytes()[i] == b'R' { s.push(i) } else {
while let Some(t) = s.pop() {
if h[t] > h[i] { h[t] -= 1; h[i] = 0; s.push(t); break }
if h[t] < h[i] { h[t] = 0; h[i] -= 1; continue }
h[t] = 0; h[i] = 0; break
}}}
h.into_iter().filter(|&x| x > 0).collect()
}
31.03.2026
3474. Lexicographically Smallest Generated String hard

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1314
Problem TLDR
String from pattern matches #hard #greedy #kmp
Intuition
Didn’t solve.
// b
// FFFF - aaaa
// TFFF baaa F - always a
// T - always str2
// 10^4 * 500 = 10^6 can be accepted
// F - is not always 'a', if str2 can match
// TFFF aa
// aa
// ab
// ab the matching part is simple
// the non-matching: maybe increment it? aa-ab-ac-..-az-ba
// maybe FFF..s create a pattern?
// aba
// TFT
// ababa
Greedy n*m solution:
- fill by T
- validate by T
- validate by F
- for matching F’s: increment rightmost letter
Approach
- we can initialize with ‘a’
- we can compare with ‘a’ to skip hold positions
Complexity
-
Time complexity: \(O(nm)\)
-
Space complexity: \(O(n+m)\)
Code
// 80ms
fun generateString(a: String, b: String): String {
val s = CharArray(a.length+b.length-1) { 'a' }
for (i in a.indices) if (a[i] == 'T') for (j in b.indices) s[i+j] = b[j]
for (i in a.indices) if (a[i] == 'F' && b.indices.all { s[i+it] == b[it]})
++s[i+(b.indices.findLast { s[i+it] == 'a' } ?: return "")]
else if (a[i] == 'T' && b.indices.any { s[i+it] != b[it]}) return ""
return String(s)
}
// 3ms
pub fn generate_string(a: String, b: String) -> String {
let (a, b, mut s) = (a.as_bytes(), b.as_bytes(), vec![b'a'; a.len() + b.len() - 1]);
for i in 0..a.len() { if a[i] == b'T' { s[i..i+b.len()].copy_from_slice(b) } }
for i in 0..a.len() { if a[i] == b'F' && &s[i..i+b.len()] == b {
let Some(j) = s[i..i+b.len()].iter().rposition(|&c| c == b'a') else { return "".into() };
s[i+j] += 1
} else if a[i] == b'T' && &s[i..i+b.len()] != b { return "".into() }}
String::from_utf8(s).unwrap()
}
30.03.2026
2840. Check if Strings Can be Made Equal With Operations II medium

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1313
Problem TLDR
Strings equal at odd-even positions #medium #hash
Intuition
- compare frequencies
- compare hashes
Approach
- as well as it is green its all fine! (for golf)
-
sum((c parity)^4) is the perfect hash
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 49ms
fun checkStrings(a: String, b: String) = a.indices.sumOf { i ->
(a[i]-' '+i%2*32.0).pow(3) - (b[i]-' '+i%2*32.0).pow(3)
} == 0.0
// 0ms
pub fn check_strings(a: String, b: String) -> bool {
let h = |s: &[u8]| (0..s.len()).map(|i|
1<<(s[i] as usize & 31 | i%2*7) ).sum::<usize>();
h(a.as_bytes()) == h(b.as_bytes())
}
29.03.2026
2839. Check if Strings Can be Made Equal With Operations I easy youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1312
Problem TLDR
| Match a and b at (0 | 2,1 | 3) positions #easy |
Intuition
How short can the code be?
Approach
- Kotlin: setOf, (0..1)
- Rust: bitmask
Complexity
-
Time complexity: \(O(1)\)
-
Space complexity: \(O(1)\)
Code
// 24ms
fun canBeEqual(a: String, b: String) =
(0..1).all { setOf(a[it],a[it+2]) == setOf(b[it],b[it+2]) }
// 0ms
pub fn can_be_equal(a: String, b: String) -> bool {
let f = |s: &[u8]| 1<<s[0] | 1<<s[2] | 1<<s[1]+16 | 1<<s[3]+16;
f(a.as_bytes()) == f(b.as_bytes())
}
28.03.2026
2573. Find the String with LCP hard

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1311
Problem TLDR
Build string from longest common prefixes matrix #hard
Intuition
// [[4,0,2,0], 0..=4, [0..][2..]=2
// [0,3,0,1],
// [2,0,2,0],
// [0,1,0,1]]
// [0][0] 4=aaaa,
// [0][1] 0= b b
// [0][2] 2=ab
// [0][3] 0 a!=b
// 6 minute:
// i have no idea
// diagonal 4 3 2 1 is always like this
// can be ignored
// is symmetric, look only top right corner
//
// [[4,0,2,0],
// [0,3,0,1],
// [2,0,2,0],
// [0,1,0,1]]
//
// 020
// abcd
// * a!=b
// * ab==cd
// * a!=d
// 01
// bcd
// * b!=c
// * b==d
// 0
// cd
// * c!=d
//
// how to use this?
// can just increment from 'a'?
// abcd
// aaaa
// a!=b: abaa
// ab==cd: abab
// a!=d: true
// b!=c: true
// b==d: true
// c!=d: true
// will this work? let's try
//
// 32 minute, corner case:
// [[4,1,1,1],
// [1,3,1,1],
// [1,1,2,1],
// [1,1,1,1]]
// 38 minute, test case "abcdefghijklmnopqrstuvwxyz{"
n^3: check matrix symmetry and diagonal properties, build string in (i,j, count) loop, validate separately n^2: build string filling the letters on vacant equal places, validate by dp property p[i][j]=s[i]==s[j] + p[i+1][j+1]
Approach
- diagonal: 4 3 2 1 always
- symmetry above vs below diagonal
- letter not overflow ‘z’
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n)\)
Code
// 21ms
fun findTheString(p: Array<IntArray>): String {
val n = p.size-1; val s = CharArray(n+1); var c = 'a'-1
for (i in 0..n) if (s[i] < 'a') {
if (++c > 'z') return ""
for (j in i..n) if (p[i][j] > 0) s[j] = c
}
return if ((0..n).all { i -> (0..n).all { j ->
val x = if (max(i,j) < n) p[i+1][j+1] else 0
p[i][j] == if (s[i] == s[j]) 1 + x else 0 }}) String(s) else ""
}
// 7ms
pub fn find_the_string(p: Vec<Vec<i32>>) -> String {
let n = p.len(); let (mut s, mut c) = (vec![0;n], 96);
for i in 0..n { if s[i] == 0 {
c += 1; if c > 122 { return "".into() }
for j in 0..n { if p[i][j] > 0 { s[j] = c }}
}}
((0..n).all(|i| (0..n).all(|j| p[i][j]==(s[i]==s[j])as i32 *
(1 + if i.max(j) < n-1 { p[i+1][j+1] } else {0})
))).then(|| String::from_utf8(s).unwrap()).unwrap_or_default()
}
27.03.2026
2946. Matrix Similarity After Cyclic Shifts easy substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1310
Problem TLDR
Shift rows k times left and right #easy #matrxi
Intuition
Brute force is accepted.
Approach
- we can shift by k instead of by 1 k times
- rows must be periodic or size == k, so left shift is the same as right shift
- just check each row, don’t have to create a matrix
Complexity
-
Time complexity: \(O(nm)\)
-
Space complexity: \(O(1)\)
Code
// 15ms
fun areSimilar(m: Array<IntArray>, k: Int) =
m.all { r -> r.indices.all { r[it] == r[(it+k)%r.size] }}
// 0ms
pub fn are_similar(m: Vec<Vec<i32>>, k: i32) -> bool {
m.iter().all(|r| (0..r.len()).all(|i| r[i] == r[(i + k as usize) % r.len()]))
}
26.03.2026
3548. Equal Sum Grid Partition II hard substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1309
Problem TLDR
Cut matrix in half sums, can remove one cell #hard
Intuition
Didn’t solve myself.
- rotate 4 times to simplify the logic
- lee intuition: store visited values in a hashset, calculate if suffix-prefix is in visited set
- another intuition: store visited prefixes in a hashmap to cut positions, calculate if (total-value)/2 in visited prefixes
Approach
- reasoning about “not to disconnect” is the hardest part
- corners are allowed to cut
- single line grid is a corner case
- we are making horizontal cuts
- i==R && x%C==0 is the last row corners
Complexity
-
Time complexity: \(O(nm)\)
-
Space complexity: \(O(nm)\) can be O(max(n,m))
Code
// 286ms
fun canPartitionGrid(g: Array<IntArray>): Boolean {
val l=g.map{it.map{1L*it}}; val t=l.sumOf{it.sum()}
val x=l[0].indices.map{c->l.map{it[c]}}
fun F(m:List<List<Long>>):Boolean {
val R=m.size-1; val C=m[0].size-1; var p=0L; val M=HashMap<Long,Int>()
return (0..R).any { y ->
m[y].withIndex().any{ (x,c) ->
val i=M[(t-c)/2]; p += c
(t-c)%2==0L && i!=null && (if(C<1)y==i+1||y==R else i<R-1||x%C==0)
} || y<R && { M[p]=y; p*2 == t }()
}
}
return listOf(l,l.reversed(),x,x.reversed()).any(::F)
}
// 128ms
pub fn can_partition_grid(g: Vec<Vec<i32>>) -> bool {
let l: Vec<Vec<_>> = g.iter().map(|r| r.iter().map(|&v| v as i64).collect()).collect();
let t: i64 = l.iter().flatten().sum();
let x: Vec<Vec<_>> = (0..l[0].len()).map(|c| l.iter().map(|r| r[c]).collect()).collect();
let (mut lr, mut xr) = (l.clone(), x.clone()); lr.reverse(); xr.reverse();
let f = |m: &Vec<Vec<i64>>| {
let (r, c, mut p, mut map) = (m.len() - 1, m[0].len() - 1, 0, HashMap::new());
(0..=r).any(|y| {
m[y].iter().enumerate().any(|(x, &v)| {
let i = map.get(&((t - v) / 2)); p += v;
(t - v) % 2 == 0 && i.map_or(false, |&i| if c < 1 { y == i + 1 || y == r } else { i < r - 1 || x % c == 0 })
}) || y < r && { map.insert(p, y); p * 2 == t }
})
};
[&l, &lr, &x, &xr].into_iter().any(|m| f(m))
}
25.03.2026
3546. Equal Sum Grid Partition I medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1308
Problem TLDR
Split matrix to equal sums #medium
Intuition
O(1) memory solution: calculate total, then separately check each row/column splits p+p==t, sum prefixes in a single variable
Single pass solution: use a hashset to keep track of all visited prefixes, at the end lookup for total/2
Approach
- careful with int overflow
- Kotlin: any, sumOf
- Rust: flatten, any, fold
Complexity
-
Time complexity: \(O(nm)\)
-
Space complexity: \(O(1)\)
Code
// 24ms
fun canPartitionGrid(g: Array<IntArray>) =
g.sumOf { it.sumOf { 1L * it }}.let { t ->
var h = 0L; var v = 0L
g.any { h += it.sumOf { 1L * it }; h == t - h } ||
g[0].indices.any { x -> v += g.sumOf { 1L * it[x] }; v == t - v }
}
// 2ms
pub fn can_partition_grid(g: Vec<Vec<i32>>) -> bool {
let (mut h, mut v, t) = (0, 0, g.iter().flatten().fold(0, |s,&x| s + x as i64));
g.iter().any(|r| { h += r.iter().sum::<i32>() as i64; h+h==t}) ||
(0..g[0].len()).any(|c| { v += g.iter().fold(0,|s,r|s+r[c] as i64); v+v==t})
}
24.03.2026
2906. Construct Product Matrix medium youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1307
Problem TLDR
Product of other cells in a matrix #medium #prefix
Intuition
// p = a*b*c*d
// a' = (p/a)%m
// are we allowed to do 1/a with modulo?
//
// corner case: zero if we do %M locally
//
// this is some math theory
//
// 12345 is not a prime
// if there is a group of numbers that are multiplies of 12345
// then all elements are zero except this group (if no duplicates)
//
// 12 minute hint: solve without '/', hint2: suffix-prefix
//
Division is not allowed: total product can be 0, and modulo division should be mod inverse, not allowed for 12345
Approach
- flatten the matrix to make code shorter
Complexity
-
Time complexity: \(O(nm)\)
-
Space complexity: \(O(nm)\)
Code
```kotlin [-Kotlin 90ms]
// 90ms
fun constructProductMatrix(g: Array
```rust [-Rust 20ms]
// 20ms
pub fn construct_product_matrix(g: Vec<Vec<i32>>) -> Vec<Vec<i32>> {
let f = g.concat();
let o = |a: &mut i64, &x: &i32| { let r = *a; *a = *a * x as i64% 12345; Some(r) };
f.iter().scan(1, o).zip(f.iter().rev().scan(1, o).collect_vec().into_iter().rev())
.map(|(p,s)| (p * s % 12345) as i32).chunks(g[0].len())
.into_iter().map(Iterator::collect).collect()
}
23.03.2026
1594. Maximum Non Negative Product in a Matrix medium substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1306
Problem TLDR
Max product path right-down #medium #dp
Intuition
// 14minute wrong answer 138 / 159 testcases Output 38431730 Expected 459630706
// 15 minute tle 152 / 159 testcases passed
// so the full search is not allowed for 15x15 grid
// 20 minute, use hint: dp, high+low works
The brute-force gives TLE. Local optimum max is the wrong intuition. Preserve two results for each cell: max and min.
Approach
- only 1D array is needed to track the last row
Complexity
-
Time complexity: \(O(nm)\)
-
Space complexity: \(O(m)\)
Code
// 21ms
fun maxProductPath(g: Array<IntArray>) =
List(2) { LongArray(g[0].size) }.let { (h, l) ->
for (y in g.indices) for (x in g[0].indices) {
if (x + y == 0) { h[x] = 1L*g[y][x]; l[x] = h[x]; continue }
val i = if (y > 0) x else x-1; val j = if (x > 0) x-1 else x
val a = listOf(h[i], h[j], l[i], l[j])
h[x] = a.maxOf { it * g[y][x] }; l[x] = a.minOf { it * g[y][x] }
}
h.last().takeIf { it >= 0 }?.let { it%1000000007 } ?: -1L
}
// 0ms
pub fn max_product_path(g: Vec<Vec<i32>>) -> i32 {
let mut h = vec![0i64; g[0].len()]; let mut l = h.clone();
for y in 0..g.len() { for x in 0..g[0].len() {
let (v, i, j) = (g[y][x] as _, x-(y==0) as usize, x-(x>0) as usize);
if x+y<1 { h[x]=v; l[x]=v } else {
let mut a = [h[i]*v, l[i]*v, h[j]*v, l[j]*v]; a.sort(); h[x] = a[3]; l[x] = a[0] }
}}
match *h.last().unwrap() { n if n < 0 => -1, n => (n % 1_000_000_007) as _ }
}
22.03.2026
1886. Determine Whether Matrix Can Be Obtained By Rotation easy substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1305
Problem TLDR
Rotate matrix #easy
Intuition
Rotate 4 times and check deep equals.
Approach
- or just check 4 counters of equal values, should be n^2
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n^2)\)
Code
// 14ms
fun findRotation(m: Array<IntArray>, t: Array<IntArray>) =
generateSequence(m) { m ->
Array(m.size){ y -> IntArray(m.size) { x -> m[m.size-1-x][y] }}
}.take(4).any(t::contentDeepEquals)
// 0ms
pub fn find_rotation(m: Vec<Vec<i32>>, t: Vec<Vec<i32>>) -> bool {
let n = m.len(); iterate(m, |c| (0..n).map(|i| (0..n).map(|j|
c[n-1-j][i]).collect()).collect()).take(4).any(|c| c == t)
}
21.03.2026
3643. Flip Square Submatrix Vertically medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1304
Problem TLDR
Reverse submatrix k by k #easy
Intuition
Carefully do this in-place.
Approach
- name variables properly
- Rust allows to swap entire slices
Complexity
-
Time complexity: \(O(k*k)\)
-
Space complexity: \(O(1)\)
Code
// 1ms
fun reverseSubmatrix(g: Array<IntArray>, r: Int, c: Int, k: Int)=g.also{
for (y in 0..<k/2) for (x in c..<c+k)
g[y+r][x] = g[r+k-1-y][x].also { g[r+k-1-y][x] = g[y+r][x] }
}
// 0ms
pub fn reverse_submatrix(mut g: Vec<Vec<i32>>, r: i32, c: i32, k: i32) -> Vec<Vec<i32>> {
let (r, c, k) = (r as usize, c as usize, k as usize);
let (top, btm) = g[r..r+k].split_at_mut(k/2);
for (t,b) in top.iter_mut().zip(btm.iter_mut().rev()) {
t[c..c+k].swap_with_slice(&mut b[c..c+k])
} g
}
20.03.2026
3567. Minimum Absolute Difference in Sliding Submatrix medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1303
Problem TLDR
Mid diffs in k*k submatrices #medium #matrix
Intuition
Just brute-force, the size is small, 30
Approach
- Kotlin: toSortedSet(), windowed
- Rust: itertools allows to use sorted in a single expression, tuple_windows
Complexity
-
Time complexity: \(O(nmk^2)\)
-
Space complexity: \(O(nmk^2)\)
Code
// 86ms
fun minAbsDiff(g: Array<IntArray>, k: Int)=
List(g.size-k+1) { y -> List(g[0].size-k+1) { x ->
List(k*k){ g[y+it/k][x+it%k] }.toSortedSet()
.windowed(2) {it[1]-it[0]}.minOrNull() ?: 0
}}
// 2ms
pub fn min_abs_diff(g: Vec<Vec<i32>>, k: i32) -> Vec<Vec<i32>> {
let k = k as usize; (0..=g.len()-k).map(|y| (0..=g[0].len()-k).map(|x|
(0..k*k).map(|i| g[y+i/k][x+i%k]).sorted().dedup().tuple_windows()
.map(|(a,b)|b-a).min().unwrap_or(0)
).collect()).collect()
}
19.03.2026
3212. Count Submatrices With Equal Frequency of X and Y medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1302
Problem TLDR
Count prefix freq X == freq Y #medium #matrix
Intuition
Keep two prefixes: for the X and for the Y. Freq = freq_left + freq_top
Approach
- we can just look at balance x++ y–
- we can store just the last row
- to keep track ‘at least one’ rule, use a single bit per column
Complexity
-
Time complexity: \(O(nm)\)
-
Space complexity: \(O(m)\)
Code
// 18ms
fun numberOfSubmatrices(g: Array<CharArray>) =
IntArray(g[0].size).let { X ->
g.sumOf { r ->
var x = 0; var s = 0; var j = 0
r.count { c ->
if (c > '.') { s = 1; x += 4*(c - 'X')-2 }
X[j] = X[j] + x or s; X[j++] == 1
}
}
}
// 18ms
pub fn number_of_submatrices(g: Vec<Vec<char>>) -> i32 {
let mut v = vec![0; g[0].len()];
g.iter().map(|r| {
let (mut b, mut s) = (0, 0);
r.iter().zip(&mut v).map(|(&c, x)| {
if c > '.' { s = 1; b += (c as i32 - 88)*4-2 }
*x = *x + b|s; (*x == 1) as i32
}).sum::<i32>()
}).sum()
}
18.03.2026
3070. Count Submatrices with Top-Left Element and Sum Less Than k medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1301
Problem TLDR
Count prefix sums less than K #medium #matrix
Intuition
Just compute and re-use prefix sum.
Approach
- count in-place
- use row-sum extra variable
- rust itertools have product!
- optimization: after sum bigger than k consider this as the limit for x
Complexity
-
Time complexity: \(O(mn)\)
-
Space complexity: \(O(1)\)
Code
// 39ms
fun countSubmatrices(g: Array<IntArray>, k: Int) =
g.indices.sumOf { y -> g[0].indices.count { x ->
g[y][x] += (if (y > 0) g[y-1][x] else 0) +
(if (x > 0) g[y][x-1] else 0) -
(if (x*y > 0) g[y-1][x-1] else 0)
g[y][x] <= k
}}
// 0ms
pub fn count_submatrices(mut g: Vec<Vec<i32>>, k: i32) -> i32 {
(0..g.len()).map(|y| (0..g[0].len()).fold((0,0), |(mut s, c), x| {
s += g[y][x]; g[y][x] = s + (y>0) as i32 * g[y.max(1)-1][x];
(s, c + (g[y][x] <= k) as i32)
}).1).sum()
}
17.03.2026
1727. Largest Submatrix With Rearrangements medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1300
Problem TLDR
Max area of binary matrix, swap columns #medium
Intuition
// columns!
// 6
// ***___***___
// __*****_____ 5
// ______***___
// ______*_____
// ______*_____
// ______*_____
// ______*_____
// 7
//
// 001
// 112 = 1+1+1=3
// 203 = 2+2=4
//
// 22223345 max(2*8,3*4, 4*2, 5)
- subproblem: only the last row with histogram of the previous rows
- sort the histogram, O(n) scan max(h(x)*(width-x))
Approach
- don’t have to build histogram for the first row
- r[x] *= prev + 1 trick
Complexity
-
Time complexity: \(O(nmlog(m))\)
-
Space complexity: \(O(m)\)
Code
// 110ms
fun largestSubmatrix(m: Array<IntArray>) =
m.withIndex().maxOf { (y,r) ->
if (y>0) for (x in r.indices) r[x] *= m[y-1][x] + 1
r.sorted().withIndex().maxOf { (x,v) -> (r.size-x)*v }
}
// 4ms
pub fn largest_submatrix(mut m: Vec<Vec<i32>>) -> i32 {
(0..m.len()).map(|y| {
if y > 0 { for x in 0..m[0].len() { m[y][x] *= m[y-1][x]+1}}
let mut r = m[y].clone(); r.sort();
(0..r.len()).map(|x|(r.len()-x)as i32*r[x]).max().unwrap()
}).max().unwrap()
}
16.03.2026
1878. Get Biggest Three Rhombus Sums in a Grid medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1299
Problem TLDR
Top 3 rhombus sums #medium
Intuition
Brute-force.
Approach
- the distance from center to top is the exact number of steps from top to right
Complexity
-
Time complexity: \(O((mn)^2)\)
-
Space complexity: \(O((mn)^2)\), can be O(1)
Code
// 245ms
fun getBiggestThree(g: Array<IntArray>) = buildSet {
for (y in g.indices) for (x in g[0].indices) {
add(g[y][x])
for (d in 1..minOf(x, g[0].size-1-x, y, g.size-1-y)) {
var c = 0; var i = y-d; var j = x
for ((dy, dx) in listOf(1 to 1, 1 to -1, -1 to -1, -1 to 1))
repeat(d) { c += g[i][j]; i += dy; j += dx }
add(c)
}
}
}.sortedDescending().take(3)
// 13ms
pub fn get_biggest_three(g: Vec<Vec<i32>>) -> Vec<i32> {
let (mut s, m, n) = (vec![], g.len(), g[0].len());
for y in 0..m { for x in 0..n { s.push(g[y][x]);
for d in 1..=x.min(n-1-x).min(y).min(m-1-y) {
let (mut c, mut i, mut j) = (0, y-d, x);
for (dx,dy) in [(1,1),(1,!0),(!0,!0),(!0,1)] { for _ in 0..d
{ c+=g[i][j]; i=i.wrapping_add(dx); j=j.wrapping_add(dy) }
}
s.push(c)
}
}} s.sort_unstable_by_key(|&x|-x); s.dedup(); s.truncate(3); s
}
15.03.2026
1622. Fancy Sequence hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1298
Problem TLDR
Design: add number, mulriply all, add all #design
Intuition
// ((x+a+b+c)*d*c+e+f)*g
// x+abc
// x*dc*g + abc*dc*g + ef*g
// x*dcg + abc*dc*g + ef*g
// the problem is: not all values are here
// when appening: freeze current mul & add for this value
//
// x*dc + abc*dc + e, then add y
// x*dcg + abc*dc*g + ef*g + h
// y*g + f*g + h
//
// mul = dcg
// fm = dc y*g = y * mul / fm
//
// add = abc*dc*g + e*g + f*g + h = g(abc*dc+e)+f*g+h
// fa = abc*dc + e
// g = mul/fm
// f*g+h = add - (mul/fm)*fa
//
// 23 minute wrong answer on some case 53/107
// 19239 vs 50
// too big (was Int overflow)
// another 65/107, value negative probably overflow
// now its positive, still wrong, illegal modulo?
// are we allowed to divide mul/fm?
// 38 minute, some overflow (or modulo) issue
// hint: modular inverse? oh-no
//
Arithmetics: x * mul / fm + add - (mul/fm)*fa, fm - frozen mul, fa - frozen add.
Approach
- store three numbers: value, fronzen add, fronzen mul
- or store one number: reversed value
(v-add)/m - division modulo is not allowed, we have to use inverse modulo: x^-1%m = -M/x * (M%x)^-1 (recursive until x > 1)
Complexity
-
Time complexity: \(O(m)\)
-
Space complexity: \(O(n)\)
Code
// 80ms
class Fancy: ArrayList<Long>() {
var x = 1L; var s = 0L; val M = 1_000_000_007L
fun i(v: Long): Long = if (v < 2) v else M - M/v * i(M%v)%M
fun append(v: Int) = add((v-s+M) * i(x) % M)
fun addAll(v: Int) { s += v }
fun multAll(v: Int) { x = x * v % M; s = s * v % M }
fun getIndex(i: Int) = if (i < size) (get(i)*x %M + s)%M else -1
}
// 56ms
const M:i64 = 1000000007; struct Fancy(Vec<i64>, i64, i64);
fn i(x: i64) -> i64 { if x < 2 { x } else { M - M/x * i(M%x) % M }}
impl Fancy {
fn new() -> Self { Self(vec![], 1, 0) }
fn append(&mut self, v: i32) { self.0.push((v as i64-self.2+M)*i(self.1)%M) }
fn add_all(&mut self, v: i32) { self.2 += v as i64 }
fn mult_all(&mut self, v: i32) { self.1 = self.1*v as i64%M; self.2 = self.2*v as i64%M }
fn get_index(&self, i: i32) -> i32 { self.0.get(i as usize).map_or(-1, |v| (v*self.1+self.2)%M)as _}
}
14.03.2026
1415. The k-th Lexicographical String of All Happy Strings of Length n medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1297
Problem TLDR
K-th generated abc non-repeating string #medium #dfs
Intuition
// the problem is small, just generate all, sort
// abab
// abac
// abca
// abcb
// acab
// acac
// baba
// 2^10
The simple solution: just generate all strings in DFS, sort.
Approach
- the DFS already generates in a sorted order, no need to sort
- no need to keep strings, just count until k
- the math intuition: each char generates subtree with known elements count, initial a: 2^(n-1), b: 2^(n-1), c: 2^(n-1)
- index is “abc”[k/count] at first, then {“ab”, “bc”, “ac”}[k/count], k %= count, count /= 2
Complexity
-
Time complexity: \(O(2^n)\), or O(n)
-
Space complexity: \(O(2^n)\), or O(1)
Code
// 11ms
fun getHappyString(n: Int, k: Int, s: String = "abc", b: Int = 1 shl n-1): String =
if (n==0 || (k-1)/b > s.lastIndex) "" else
s[(k-1)/b] + getHappyString(n-1, (k-1)%b+1, "abc".replace(""+s[(k-1)/b],""))
// 12ms
pub fn get_happy_string(n: i32, k: i32) -> String {
(0..n).map(|_| *b"abc").multi_cartesian_product()
.filter(|s| s.windows(2).all(|w| w[0] != w[1]))
.nth(k as usize-1).and_then(|v| String::from_utf8(v).ok()).unwrap_or_default()
}
13.03.2026
3296. Minimum Number of Seconds to Make Mountain Height Zero medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1296
Problem TLDR
Min steps to work a mountain with arithmetic-sum-workers #medium #bs
Intuition
// the description is brainrot
// 1+2+3+4+5 + (n-2)+(n-1)+n = s
//
Binary search: freeze the number of parallel steps, test the amount of total work done. Inner binary search to answer what number of steps is the maximum allowed to be less than frozen steps.
Approach
- S = x*(x+1)/2
- there is a math solution possible for inner bs
- live math in rust is slower than precomputed array in kotlin
Complexity
-
Time complexity: \(O(log(nlog(w)))\)
-
Space complexity: \(O(w)\) can be O(1)
Code
// 117ms
fun minNumberOfSeconds(mh: Int, wt: IntArray): Long {
val a = LongArray(mh+1) { 1L * it * (it+1)/2 }
var lo = 0L; var hi = 1L shl 62
while (lo <= hi) {
val m = lo + (hi - lo) / 2
if (mh > wt.sumOf { t ->
var i = a.binarySearch(m/t); if (i < 0) i = -i-2; i
}) lo = m + 1 else hi = m - 1
}
return lo
}
// 144ms
pub fn min_number_of_seconds(mh: i32, wt: Vec<i32>) -> i64 {
let (mut lo, mut hi) = (0i64, 1i64<<62);
while lo <= hi {
let m = lo + (hi - lo) / 2; let mut s = 0i64;
for &t in &wt {
let (mut l, mut h) = (0, mh as i64);
while l <= h {
let i = (l + h) / 2;
if i*(i+1)/2 * t as i64 <= m { l = i + 1 } else { h = i - 1 }
}
s += h
}
if s < mh as i64 { lo = m + 1 } else { hi = m - 1 }
} lo
}
12.03.2026
3600. Maximize Spanning Tree Stability with Upgrades hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1295
Problem TLDR
Max of min values in span tree of graph, 2*s at most k #hard #graph
Intuition
// i will spend no more than 30 minutes to this until i use hints
// the must-edges should be included
// check for cycles
// upgrade makes sense to always do *2 (k times)
// the minimum is min(must, notmust_k*2)
// the question is to remove min-value edges
// the new edges can only worsen the situation of min(must)
// so take as few as possible
// now the question: how to build a spanning tree with priority?
//
// union-find?
//
// now how to take all necessary edges from others to make span tree?
// we must visit all nodes
// take largest s first; can be not optimal
// necessary node can be not largest
// how to spend k optimally?
// and to not form cycles
//
// 20 minute
//
// go from unvisited nodes?
//
// a-b c (ac=1, bc=2) k=1 (ab is must, min=0)
//
// honestly not sure
// both ac and bc are promising, both can make a cycle
//
// ok google how to build a span tree lol
// 27 minute
// let's just blindly sort by value and take largest
// wrong answer, didn't work 30 minute, use hints
// the missing part: binary search
//
// 1:03 another edge case
//
Sort by bigger s first. Binary Search: freeze the allowed s lvl, try to greedily add everything Heap: just greedily add everything, then 2*s of k smallest added
Approach
- heap is not needed, we have a sorted order
- Union-Find to check cycles/added
- we can do a single pass if we sort by m first
Complexity
-
Time complexity: \(O(n+eloge)\)
-
Space complexity: \(O(e+n)\)
Code
// 238ms
fun maxStability(n: Int, e: Array<IntArray>, k: Int): Int {
e.sortWith(compareBy({-it[3]}, {-it[2]}))
val u = IntArray(n) { it }; val g = ArrayList<Int>(); g += Int.MAX_VALUE
fun f(x: Int): Int = if (u[x]==x)x else f(u[x]).also {u[x]=it}
for ((a,b,s,m) in e) if (f(a)!=f(b)) u[f(a)]=f(b).also{if(m>0) g[0]=min(g[0],s) else g+=s} else if(m>0) return -1
return if ((0..<n).all {f(it) == f(0)}) minOf(g[0], g[max(0,g.size-k-1)], g.last()*2) else -1
}
// 33ms
pub fn max_stability(n: i32, mut e: Vec<Vec<i32>>, k: i32) -> i32 {
e.sort_unstable_by_key(|v| (-v[3], -v[2]));
let mut u: Vec<_> = (0..n as usize).collect(); let (mut c, mut g) = (n, vec![i32::MAX]);
fn f(u: &mut [usize], mut x: usize) -> usize { if x == u[x] { x } else { let a = f(u, u[x]); u[x] = a; a }}
for v in e {
let (a, b, s, m) = (f(&mut u, v[0] as _), f(&mut u, v[1] as _), v[2], v[3]);
if a != b { u[a] = b; c -= 1; if m > 0 { g[0] = g[0].min(s) } else { g.push(s) } }
else if m > 0 { return -1 }
}
if c > 1 { -1 } else { g[0].min(g[g.len().saturating_sub((k + 1) as usize)]).min(g[g.len() - 1]*2) }
}
11.03.2026
1009. Complement of Base 10 Integer easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1294
Problem TLDR
Invert binary #easy
Intuition
Use a bitmask of the next power of two - 1.
Approach
- Kotlin: takeHighestOneBit, countLeadingZeroBits
- Rust: leasing_zeros, next_power_of_two, ilog2
-
0 case trick: use 1 to check bits count at least 1
Complexity
-
Time complexity: \(O(1)\)
-
Space complexity: \(O(1)\)
Code
// 0ms
fun bitwiseComplement(n: Int) =
(n or 1).takeHighestOneBit()*2 - n - 1
// 0ms
pub fn bitwise_complement(n: i32) -> i32 {
n^(2<<(n|1).ilog2())-1
}
10.03.2026
3130. Find All Possible Stable Binary Arrays II hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1293
Problem TLDR
01-array to make with z zeros, o ones, l repeats #hard #dp
Intuition
// so this is yesterday problem, but this time should be solved in O(n^2) instead of n^3
// this is a n^3 solution: take every possible count 1..min(z,l)
//
// how to speed up?
// dp[z][o]=dp[o][z-1]+dp[o][z-2]+...+dp[o][z-min(z,l)-1]+dp[o][z-min(z,l)]
// dp[z-1][o]= dp[o][z-2]+dp[o][z-3]+...+dp[o][z-1-min(z-1,l)-1]+dp[o][z-1 - min(z-1,l)]
//
// dp[z][o] = dp[z-1][o]+dp[o][z-1]+(?? dp[o][z-min(z,l)] ) // how to deal with tail?
//
// z=3,l=2 dp[3][o]=dp[o][3-1]+dp[o][3-2]
// dp[3-1][o]=dp[o][3-1-1]+dp[o][3-1-2]
// dp[3][o]=dp[3-1][o] + dp[o][3-1] - dp[o][3-1-2]
//
// z=3,l=4 dp[3][o]=dp[o][3-1]+dp[o][3-2]+dp[o][3-3]
// dp[3-1][o]=dp[o][3-1-1]+dp[o][3-1-2]
// dp[3][o]=dp[3-1][o] + dp[o][3-1]
//
// z=5,l=3 dp[5][o]=dp[o][5-1]+dp[o][5-2]+dp[o][5-3]=dp[o][4]+dp[o][3]+dp[o][2]
// dp[4][o]=dp[o][4-1]+dp[o][4-2]+dp[o][4-3]=dp[o][3]+dp[o][2]+dp[o][1]
// dp[5][o]=dp[4][o]+dp[o][4]-dp[o][1]
//
// so if we rewrite to bottom up we can save one dimention of iteration
//
- consider batches of repeating current digit
- alterate by swapping arguments (curr, other) = (other, curr-take)
- can take at most min(curr, limit)
- mathematically subtract dp[curr][other]-dp[curr-1][other] to see that for loop can be O(1)
Approach
- the combinatorics solution consists of: stars and bars (s-1 b-1), inclusion-exclusion principle f(curr)-f(excl), f(excl)-f(excl-excl)…, Fermat little theorem a^-1=a^(m-1) %m, modulo exponentiation a^y = a^2(y/2)+a^2(y%2)
Complexity
-
Time complexity: \(O(zo)\)
-
Space complexity: \(O(zo)\)
Code
// 366ms
fun numberOfStableArrays(z: Int, o: Int, l: Int): Int {
val dp = HashMap<Int, Long>(); val M = 1000000007
fun dfs(z: Int, o: Int): Long = if (z<=0||o<0) 0L
else if (o==0) {if (z <=l)1L else 0L} else dp.getOrPut(z*1000+o){
(dfs(z-1,o)+dfs(o,z-1)-dfs(o,z-min(z,l)-1)+M)%M
}
return ((dfs(z, o) + dfs(o, z) + M) % M).toInt()
}
// 39ms
pub fn number_of_stable_arrays(z: i32, o: i32, l: i32) -> i32 {
let (m,z,o,l) = (1000000007, z as usize, o as usize, l as usize);
let (mut f, mut v) = ([1;2005], [1;2005]);
for i in 1..2005 { f[i] = f[i-1] * i as i64 % m }
let (mut b, mut e) = (f[2004], m-2);
while e > 0 { if e & 1 == 1 { v[2004] = v[2004]*b%m} b=b*b%m; e/=2 }
for i in (1..2005).rev() { v[i-1] = v[i]*i as i64 % m }
let c = |n: usize, r: usize| if r > n {0} else {f[n]*v[r]%m*v[n-r]%m};
let w = |n: usize, b: usize| if b == 0 {(n==0)as i64} else {
(0..=b).take_while(|&i| n >= i*l + b).fold(0, |a,i|
(a+[1,m-1][i&1]*c(b,i)%m*c(n-i*l-1,b-1)%m)%m )};
(1..=z).fold(0, |a,k|
(a + w(z,k)*(w(o,k)*2 + w(o,k-1) + w(o,k+1))%m)%m ) as _
}
09.03.2026
3129. Find All Possible Stable Binary Arrays I medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1292
Problem TLDR
Count 01-arrays with z zeros, o ones, at most l repeat #medium
Intuition
Didn’t solve.
// length = z+o = 400
// consequent repeats at most l
// this can be DFS + memo n^3
// my solution is n^4 TLE
// the symmetry trick didn't help
// lets look hints
// MLE
The working intuition: build arrays by alterating blocks.
Approach
- inside DFS: try at most min(l, current) to take, flip the arguments
Complexity
-
Time complexity: \(O(zol)\)
-
Space complexity: \(O(zo)\)
Code
// 218ms
fun numberOfStableArrays(z: Int, o: Int, l: Int): Int {
val dp = HashMap<Int, Int>()
fun d(z: Int, o: Int): Int =
if (z == 0) 0 else if (o == 0) {if (z <= l) 1 else 0}
else dp.getOrPut(z*400+o) {
(1..min(z,l)).fold(0){ r, nz -> (r+d(o,z-nz))%1000000007}
}
return (d(z, o) + d(o, z))%1000000007
}
08.03.2026
1980. Find Unique Binary String medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1291
Problem TLDR
Uniq bits not in a set #medium
Intuition
Brute-force, only 16 elements. Max count is 2^16. Max count where first new appears is n+1. Cantour trick: build a new uniq by flipping exactly one uniq bit position in all bits. It would be uniq because it differs at least by one bit with each in a set.
Approach
- xor trick “1” converts to “0”, because they even-odd
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 12ms
fun findDifferentBinaryString(n: Array<String>) =
n.mapIndexed{i,s -> 1-(s[i]-'0')}.joinToString("")
//n.indices.joinToString(""){""+"10"[n[it][it]-'0']}
//(0..16).map{it.toString(2).padStart(n.size,'0')}.find{it !in n}
//(0..16).first{it !in n.map{it.toInt(2)}}.toString(2).padStart(n.size,'0')
// 0ms
pub fn find_different_binary_string(n: Vec<String>) -> String {
(0..n.len()).map(|i| (n[i].as_bytes()[i]^1)as char).join("")
}
07.03.2026
1888. Minimum Number of Flips to Make the Binary String Alternating medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1290
Problem TLDR
Min flips to make 01 alterating string #medium #prefix_sum #sliding_window
Intuition
// 111000
// 0 1
//
// 110001
// 100011
// 1
// 0
//
// whats the point of shifting?
//
// 110
// 101 just shifted
//
// soo we can start from first 10
//
// 011
// 110
// 101
//
// 11010
//
// 10110
// 01011
//
// or double 00
// 001 shift 010
//
// just split 11 idk if it works
//
// can be many splits
// is this dp?
// 0011
//
// 101|101
//
// not optimal
// 10001100101000000|10001100101000000
// 1010101010101010|1
// 101010101010101|01
// 10101010101010|101
// 1010101010101|0101
// ...
// 10|101010101010101
// 1|0101010101010101
// they are all repeating
//
// 011|011
// 010|
// 01|0
// 0|10
// 101|
// 10|1
// 1|01 match
// a | b
// miss before + (len-miss) after
Prefix sum intuition:
- split at every every index, count bitflips in prefix+suffix(inverted)
- if string length is even return early
Sliding window intuition:
- slide concatenation
- if string length is even slide once
- to move the left pointer flip the bit
Approach
- (c+i)%2 gives a match increment
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\), or O(n) for prefix sum
Code
// 36ms
fun minFlips(s: String): Int {
var c = 0
return (0..<s.length+s.length%2*s.length).minOf { i ->
c += (s[i%s.length]-'0' + i)%2
if (i > s.lastIndex) c -= 1-(s[i-s.length]-'0'+i)%2
if (i < s.lastIndex) s.length else min(c, s.length-c)
}
}
// 2ms
pub fn min_flips(s: String) -> i32 {
let (n, mut a) = (s.len(), vec![0; s.len()+1]);
for (i,b) in s.bytes().enumerate() {
a[i+1]=a[i]+((b+i as u8)&1)as usize }
if n%2==0 { return a[n].min(n-a[n]) as _ }
(0..=n).map(|i| {
let t = a[n] + i - 2 * a[i]; t.min(n - t)
}).min().unwrap_or(0) as _
}
06.03.2026
1784. Check if Binary String Has at Most One Segment of Ones easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1289
Problem TLDR
1+0* pattern #easy
Intuition
- Regex ^1+0*$
Approach
- or just check of 01
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 7ms
fun checkOnesSegment(s: String) =
"01" !in s
// 0ms
pub fn check_ones_segment(s: String) -> bool {
!s.contains("01")
}
05.03.2026
1758. Minimum Changes To Make Alternating Binary String easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1288
Problem TLDR
Min flips to make bits alterating #easy
Intuition
Check two targets: 01-type and 10-type.
Approach
-
we can count a balance: balance = correct-wrong , L=C+W, L- B =(C+W)-(C-W)=2W, W=(L- B )/2 - (i + s[i]) %2 is an even-odd match
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 16ms
fun minOperations(s: String) = s.length/2-
abs(s.indices.sumOf { 1-2*((it+s[it].code)%2) })/2
// 0ms
pub fn min_operations(s: String) -> i32 {
s.len()as i32/2 - s.bytes().enumerate().map(|(i,b)|(1-2*((i as u8^b)&1)as i32)).sum::<i32>().abs()/2
}
04.08.2026
1582. Special Positions in a Binary Matrix easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1287
Problem TLDR
Count single 1-row-column #easy
Intuition
Brute-force.
Approach
- check each cell
- or check each row
Complexity
-
Time complexity: \(O(n^2m^2)\), can be O(nm)
-
Space complexity: \(O(1)\)
Code
// 14ms
fun numSpecial(m: Array<IntArray>) = m.count { r ->
r.sum()==1 && m.sumOf { it[r.indexOf(1)] }==1
}
// 0ms
pub fn num_special(m: Vec<Vec<i32>>) -> i32 {
m.iter().filter(|r|r.iter().sum::<i32>()==1&&
m.iter().map(|R|R[r.iter().position(|&x|x>0).unwrap()]).sum::<i32>()==1).count() as _
}
03.03.2026
1545. Find Kth Bit in Nth Binary String medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1286
Problem TLDR
Kth bit in s=s+1+inv(rev(s)) sequence #medium
Intuition
// 2^20 is 1M
//
// 011100110110001 15
// 0111001 1 0110001 7-1-7
// a 1 inv(rev(a))
// 011 1 001 3-1-3
// 0 1 1 1-1-1
//
// 011100110110001 15
// 15-1-15 = 31
// 31-1-31 = 63
// 63-1-63 = 127
// 1 3 7 15 31 63 127
// 2^n-1
//
// 0
// 0 1 1
// 011 1 001
// 0111001 1 0110001
// ^
// ^
// ^
- current middle of K is the highest one bit, 110 - 100
- reverse jump: k = 2*k.takeHighestOneBit()-k
- the glue-positions are all powers of two
O(1) intuition (is just observation of the patterns): 123456789101112 0111001101 1 0 1 1 1 blue bits are powers of two 0 1 0 1 0 1 odd positions are alterating bits sequence (infinite) 3 * * even positions have all the same odd ‘core’ by dividing by 2 (+flip) 5 10
- rule 1: odd k is alterating bits 01010101, just return k/2%2
- rule 2: even k goes to the core by dividing /2 until odd met, then it is rule1+flip
Approach
- start with drawing the patterns
- look for the unique properties, how many you can spot, useful or not
- use small examples to test theory, k = 0, 1, 2, 3
- use one big example to prove it still works k = 11
- spend another 2 hours asking ai to give as many other ideas as possible
Complexity
-
Time complexity: \(O(log(k))\) or O(1)
-
Space complexity: \(O(log(k))\) or O(1)
Code
// 0ms
fun findKthBit(n: Int, k: Int): Char =
if (k < 2) '0' else if (k and (k-1)==0) '1' else
'1'+ ('0'-findKthBit(n, 2*k.takeHighestOneBit()-k))
// 0ms
pub fn find_kth_bit(n: i32, mut k: i32) -> char {
(b'0' + if k % 2 > 0 { k/2 % 2 } else { 1-(k >> k.trailing_zeros())/2%2 }as u8) as _
}
02.03.2026
1536. Minimum Swaps to Arrange a Binary Grid medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1285
Problem TLDR
Min rows swaps to zero above diagonal #medium
Intuition
// 62% acceptance rate, should be simple
// 200 nxn=40000
// count suffix zeros
// 0
// 1
// 2
// target is
// n-1
// n-2
// ...
// 1
// 0
// or more
// 012 210
// how to rearrange optimally?
// 201
// 210
//
// 022 220
//
// 021 210
//
// only adjucent means its a bubble sort only
//
- count suffixes
- bubble rows up
Approach
- we don’t have to add them back
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n)\)
Code
// 22ms
fun minSwaps(g: Array<IntArray>) =
ArrayList(g.map { it.lastIndexOf(1) }).run {
indices.sumOf { i ->
val j = indices.find { get(it) <= i }
removeAt(j ?: return -1); j
}
}
// 0ms
pub fn min_swaps(g: Vec<Vec<i32>>) -> i32 {
let mut s = g.into_iter().map(|r|r.into_iter().rposition(|x|x>0).unwrap_or(0)).collect_vec();
(0..s.len()).try_fold(0, |r, i| {
s.iter().position(|&x| x <= i).map(|j|{ s.remove(j); r+j as i32})}).unwrap_or(-1)
}
01.03.2026
1689. Partitioning Into Minimum Number Of Deci-Binary Numbers medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1284
Problem TLDR
Min 01-strings add up to target #medium
Intuition
// 279
// 101
// 101
// 11 * 7
// 2
// 7
// (2+7)
//
// 12345
// 11111
// 1111
// 111
// 11
// 1
//
// 54321
// 11111
// 1111
// 111
// 11
// 1
//
// 105
//
// 50
//
// 505
Greedy idea: take as big binary number as possible to quickly fill to target.
Approach
- max
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 24ms
fun minPartitions(n: String) =
n.max() - '0'
// 0ms
pub fn min_partitions(n: String) -> i32 {
(n.bytes().max().unwrap() - 48) as _
}
28.02.2026
1680. Concatenation of Consecutive Binary Numbers medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1283
Problem TLDR
Concat binaries 1..n #medium
Intuition
Brute-force is accepted.
The log solution: r = r*2^L + x x = x + 1 repeated for distinct groups of lengths group divider is (1 shl L) - 1, count = curr-prev convert to matrix (2^L 1 0) ( 0 1 1) ( 0 0 1)
RX1 = M^count * RX1
exponentiation: a^b = a^(b/2)*2 + a^(b)%2
Approach
- for brute-force: we can reuse previous length and increase on each 2^x
- we can use countLeadingZeroBits()
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 127ms
fun concatenatedBinary(n: Int) = (1..n).fold(0L)
{ r, x -> (x + (r shl (32-x.countLeadingZeroBits())))%1000000007 }
// 2ms
pub fn concatenated_binary(n: i32) -> i32 {
const I: [i64; 9] = [1, 0, 0, 0, 1, 0, 0, 0, 1]; const M:i64 = 1000000007;
let (n, mut r, mut s, mut l) = (n as i64, 0, 1, 1);
fn mul(a: [i64; 9], b: [i64; 9]) -> [i64; 9] {
from_fn(|i| (0..3).map(|k| a[i/3*3+k] * b[k*3+i%3]).sum::<i64>() % M)
}
fn pow(b: [i64; 9], p: i64) -> [i64; 9] {
if p == 0 { I } else { mul(pow(mul(b, b), p / 2), if p % 2 > 0 { b } else { I }) }
}
while s <= n {
let e = n.min((1i64 << l) - 1);
let t = pow([(1i64 << l) % M, 1, 0, 0, 1, 1, 0, 0, 1], e - s + 1);
r = (r * t[0] + s * t[1] + t[2]) % M;
s = e + 1; l += 1;
}
r as _
}
27.02.2026
3666. Minimum Operations to Equalize Binary String hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1282
Problem TLDR
Min steps to convert 01 stirng to ones flipping K #hard #bfs
Intuition
Didn’t solve.
// acceptance rate 40%
// i will give up after 30 minutes
//
//
// 110 k=1
// 1
//
// 0101 k=3
// 10 0
// 111
//
// 101 k=2
// 01
// 00
// 11
// ... -1
//
// there should be a law or shortcut?
//
// simulation - impossible
//
// all k should be selected
// order doesnt matter
// so it is just a two numbers: zeros and ones
//
// 00000001111111 k
//
// how many zeros to choose at each step?
// dp? try all counts?
//
// how to detect that we can't reach the end?
//
// z 5 o 5 k=6
// o += min(k,z) o=5+5=10
// o -= k-min(k,z) o=10-1=9
// z = k-min(k,z) z=1
//
//
// 9minute
//
// z 1 o 9 k=6 so, this can loop forever
// any strategy that would work?
// 5:5 - 1:9 - 7:3 - BFS? numbers up to 10^5
// each round is n choices
// prune with visited set
//
// i have no other ideas, let's try
// 14 ;minute
// 20 minute - wrong answer 0101 k=3 my is 1, expected 2
// 26 minute - wrong answer 001 k=3 my is 2, expected -1
// 32 minute - wrong answer 000 k = 1, my is -1, expected 3
// so my entire intuition doesnt work on the repeated cases
// how to mitigate?
// k=1, zeros = 3, repeats = z/k = 3
// so this should be dijkstra with steps?
// anyway i can be wrong and already spent 35 minutes, lets' go hints
The TLE BFS: number of zeros are the state, next states are max(0,k-ones)..min(k,zeros). The optimization: parity hack, from z=5 k=3 we can jump to exactly any of 2,4,6,8. Same parity, continuous (steps 2), strict L..R range. Now, instead of individual state jumps consider range adjustments L..R. We want the L to be close to 0, R to be close to N. So range grows continously, peek only interesting range.
For L to reach 0, we want it be close to K, and also want L..R be wider to skip-jump to K. For R reach N, we target R-K to flip all bits.
Approach
- use ai
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 13ms
fun minOperations(s: String, k: Int): Int {
var L = s.count { it == '0' }; var R = L
for (step in 0..s.length) {
if (L == 0) return step
val newL = when {
k in L..R -> (L + k) % 2
k < L -> L - k
else -> k - R
}
val targetR = s.length - k
val newR = s.length - when {
targetR in L..R -> (L + targetR) % 2
targetR < L -> L - targetR
else -> targetR - R
}
L = newL; R = newR
}
return -1
}
26.02.2026
1404. Number of Steps to Reduce a Number in Binary Representation to One medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1281
Problem TLDR
Ops /2+1 to make 1 #medium #simulation
Intuition
Simulate the process, O(n^2) is accepted
Approach
- to optimize propagate the carry to the next op instead of doing full +1 operation
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 10ms
fun numSteps(s: String) = s.lastIndexOf('1') +
(if (Regex("^10*$") in s) 0 else 2) + s.count {it<'1'}
// 0ms
pub fn num_steps(s: String) -> i32 {
let mut c = 0;
(1..s.len()).rev().map(|i| {
c += (s.as_bytes()[i] - b'0') as i32;
let r = 1 + c % 2; c = c/2+c%2; r
}).sum::<i32>() + c
}
25.02.2026
1356. Sort Integers by The Number of 1 Bits easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1280
Problem TLDR
Sort #easy
Intuition
Sort.
Approach
- you can use 15 buckets (32 bits, and even less for 10^4 max test case)
- still have to sort
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(n)\)
Code
// 18ms
fun sortByBits(a: IntArray) =
a.sortedBy{it.countOneBits()*1e5+it}
// 0ms
pub fn sort_by_bits(mut a: Vec<i32>) -> Vec<i32> {
a.sort_by_key(|&x|(x.count_ones(),x)); a
}
24.02.2026
1022. Sum of Root To Leaf Binary Numbers easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1279
Problem TLDR
Sum of a binary numbers in a binary tree #easy
Intuition
The simplest way: helper method, global sum variable, track leafs.
Approach
- we can skip checking the leafs
- we can use tree itself as a storage
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(log(n))\)
Code
// 18ms
fun sumRootToLeaf(r: TreeNode?): Int = r?.run {
max(`val`, setOf(left,right).sumOf { it?.`val` += `val`*2; sumRootToLeaf(it) })
} ?: 0
// 0ms
pub fn sum_root_to_leaf(r: Option<Rc<RefCell<TreeNode>>>) -> i32 {
r.map_or(0, |n| { let n = n.borrow_mut();
[&n.left, &n.right].into_iter().flatten().map(|x| {
x.borrow_mut().val += n.val * 2;
Self::sum_root_to_leaf(Some(x.clone()))}).sum::<i32>().max(n.val)
})
}
23.02.2026
1461. Check If a String Contains All Binary Codes of Size K medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1278
Problem TLDR
All numbers as substring length of k #medium #sliding_window
Intuition
Use sliding window of k. Calculate the current number, add to a set. Uniqs count should be 2^k.
Approach
- use built-in windows, the k is small, can take substrings on the fly
- inverted solution: number of allowed duplicates is len-k+1 - 2^k
- return early
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 130ms
fun hasAllCodes(s: String, k: Int) =
s.windowed(k).toSet().size == 1 shl k
// 87ms
pub fn has_all_codes(s: String, k: i32) -> bool {
s.as_bytes().windows(k as usize).unique().count() as i32 == 1 << k
}
22.02.2026
868. Binary Gap easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1277
Problem TLDR
Distance between onces in a binary #easy
Intuition
The simplest way is to convert to string, then scan the positions.
Approach
n & (n-1)erases the last set bit- trailing_zeros, count_ones
- regex to match (?=(10*1))
-
regex to split ^0+ 1 0+$
Complexity
-
Time complexity: \(O(log(n))\) or less
-
Space complexity: \(O(log(n))\) or less
Code
// 17ms
fun binaryGap(n: Int) =
(28 downTo 0).firstOrNull{("1"+"0".repeat(it)+"1") in n.toString(2)}?.plus(1)?:0
/*
Regex("(?=(10*1))").findAll(n.toString(2)).maxOfOrNull{it.groupValues[1].length-1}?:0
*/
// 0ms
pub fn binary_gap(mut n: i32) -> i32 {
(1..n.count_ones()).map(|_| {
n >>= n.trailing_zeros() + 1; n.trailing_zeros() as i32 + 1 }).max().unwrap_or(0)
}
21.02.2026
762. Prime Number of Set Bits in Binary Representation easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1276
Problem TLDR
Number in l..r with prime bits count #easy #combinatorics
Intuition
Just brute force the range L..R.
Approach
- only 2..19 primes, all can fit in bitmask 0xa28ac
- we can solve the problem for each prime: “how many numbers up to R with the same bits count?”
- custom solutin with combinatorics: check every set bit, how many places it can be put in a tail
- Gosper’s hack: find next smallest number with the same set bits count
Complexity
-
Time complexity: \(O(n)\) to O(log(n)) for combinatorics
-
Space complexity: \(O(1)\)
Code
// 1ms
fun countPrimeSetBits(l: Int, r: Int) =
intArrayOf(2,3,5,7,11,13,17,19).sumOf { f(r,it)-f(l-1,it) }
companion object {
val nCr = Array(22) { IntArray(22) }
init { for (i in 0..20) {
nCr[i][0] = 1
for (j in 1..i) nCr[i][j]=nCr[i-1][j-1]+nCr[i-1][j]
}}
fun f(n: Int, k: Int): Int {
var cnt = 0; var b = 0
for (i in 20 downTo 0) if (n shr i and 1 > 0)
if (k-b >= 0) cnt += nCr[i][k-b++]
if (b == k) cnt++
return cnt
}
}
// 86ms
fun countPrimeSetBits(l: Int, r: Int): Int {
var cnt = 0
for (p in listOf(2, 3, 5, 7, 11, 13, 17, 19)) {
var x = (1 shl p) - 1
while (x <= r) {
if (x >= l) ++cnt
val c = x and -x
val nextR = x + c
x = (nextR xor x shr 2) / c or nextR
}
}
return cnt
}
// 0ms
pub fn count_prime_set_bits(l: i32, r: i32) -> i32 {
(l..=r).map(|x| 0xa28ac >> x.count_ones() & 1).sum::<i32>()
}
20.02.2026
761. Special Binary String hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1275
Problem TLDR
Swaps of 1M0-special substring to make string large #hard
Intuition
Didn’t solve :)
// 30 minutes befor i go to hints
// description unclear: prefix?
// at least as many 1 as 0 what?
// 11 ok
// 01 not ok, prefix 0 has one zero and no ones
// 1010 ok
// 100 not ok, two zeros more than one
// 110 ok
// and the first condition: numbers are equal
// 1010 ok
// 1100 ok
// 101 not ok
// 110 not ok
// 10 ok
// 11101 not ok
// 11101000 ok
//
// now the swap operation to make largest possible
// meaning move ones to start
// 11011000
// **
// ****
//
//
// s length is only 50
//
// for every zero we try to:
// 1. find first substring
// 2. find next substring
//
// from zero we should only move left
//
// acceptance rate is too high 73% brainteaser?
//
// 8 minute
//
// 11011000
// **
// ****
// let's try to go only 1 position to the left
// that means next should always by 11
// followed by 00
// ok this is wrong
// 1010101100
// 1010110010 my
// 1100101010 correct
// 17 minute
// 1010101100
// aabbbb
// 1010110010 one change
// ok this can backtrack
// how many times? maybe 50? what if we just repeat
// another wrong answer
// 110110100100
// 110110100100 my
// 111010010100 correct
// so the second chunk can be longer
// 110100
// 21 minute
// we should find the shortest chunk
// or should we try all of them?
// lets just take shortest
// 30 minute wrong answer, go for hints
//101110110011010000"
//111100110100100010"
//11101001100100010"
// draw a line?? y coordinate?
Derived rules: starts with 1, ends with 0. Slide and compute the balance. On each b==0 go deeper by a single char: “1(substring)0”
Approach
- why cut and then append 1..0? To go deeper.
- why can’t cut 1..0 on the entire ‘s’? Because its not proven they are outer shell, they can be many chunks.
Complexity
-
Time complexity: \(O(n^2)\), can be O(n)
-
Space complexity: \(O(n)\)
Code
// 37ms
fun makeLargestSpecial(s: String): String = buildList {
var b = 0; var j = 0
for (i in s.indices) {
b += 2 * (s[i]-'0') - 1
if (b == 0) { add("1" + makeLargestSpecial(s.slice(j+1..<i)) + "0"); j = i + 1 }
}
}.sortedDescending().joinToString("")
19.02.2026
696. Count Binary Substrings easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1274
Problem TLDR
Count substrings of 01 and 10 #easy #sliding_window
Intuition
Count consequent zeros and ones. Slide pair-wise res += min(prev, curr).
Approach
- the fun solution is to split the string
- itertools in Rust allow nested windows without vec allocation
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 69ms
fun countBinarySubstrings(s: String) = s
.replace("01", "0 1").replace("10", "1 0").split(" ")
.zipWithNext { a, b -> min(a.length, b.length)}.sum()
// 0ms
pub fn count_binary_substrings(s: String) -> i32 {
s.as_bytes().chunk_by(|a,b|a==b).map(|c|c.len() as i32)
.tuple_windows().map(|(a,b)|a.min(b)).sum()
}
18.02.2026
693. Binary Number with Alternating Bits easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1273
Problem TLDR
Alternating bits #easy #bits
Intuition
Check 31 bits with brute force.
The “clever solutions”:
- shift right by 2 positions, should match; shift right by 1 positions, should be opposite
- shift right by 1 position, do or: should be all ones
Approach
-
regex: (00 11)
Complexity
-
Time complexity: \(O(1)\)
-
Space complexity: \(O(1)\)
Code
// 0ms
fun hasAlternatingBits(n: Int) =
n or n/4 == n && n and n/2 == 0
/*
Regex("(11|00)") !in n.toString(2)
(n xor n/2).toString(2).all { it == '1' }
*/
// 0ms
pub fn has_alternating_bits(mut n: i32) -> bool {
n ^= n/2; n & n+1 == 0
}
17.02.2026
401. Binary Watch easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1272
Problem TLDR
All times with count bits set #easy #brainteaser
Intuition
Not an easy problem.
// i don't understand the description
// is AM/PM a separate bit?
// H: 8 4 2 1
// M: 32 16 8 4 2 1
// input is count of turned on bits?
// t=1, should be 10 results - correct
// now we need:
// dfs to collect all possible bits permutations
// (1 shl (t-1))
// then a way to convert a bitmask to the time string
// or maybe inversed problem is simpler:
// iterate hours and minutes, convert to bits, check count
//
// how to convert numbe to bits?
// 3: 11, ITS just a binary representation
The brainteaser brute-force: check every hour-minute pair. The honest worker solution: backtrack every set bit of possible 10 bit positions. The hard solution: compute next smallest bitmask with set bits.
Approach
- hours to bits conversion: just a binary representation
- bits to hours conversion: just an int value of a bitmask
- only 720 possible values (60*12)
- we can call countOneBits once on H*64+M
- use format or padStart
- next smallest bitmask: mode left the first 1-bit of the ‘11..’s tail, put leftower ‘11..’s-1 tail to the end (100110 becomes 101011)

Complexity
-
Time complexity: \(O(h*m)\)
-
Space complexity: \(O(h*m)\)
Code
// 25ms
fun readBinaryWatch(t: Int) = (0..719)
.filter { (it/60 * 64 + it%60).countOneBits() == t }
.map { "%d:%02d".format(it/60,it%60) }
// 0ms
pub fn read_binary_watch(t: i32) -> Vec<String> {
successors(Some((1<<t)-1), |&s:&i32| {
let tz = s.trailing_zeros(); let to = (s >> tz).trailing_ones();
(tz + to < 10).then(|| s + (1 << tz) + (1 << (to - 1)) - 1)
})
.filter_map(|s| {
let (h,m) = (s>>6, s&63);
(h < 12 && m < 60).then(|| format!("{}:{:02}", h, m))
}).collect()
}
16.02.2026
190. Reverse Bits easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1271
Problem TLDR
Reverse bits #easy #bits
Intuition
Manually reverse all 31 positions.
Approach
- if called many times: use built-in functions (they should be optimized and cached) and use lookup tables if memory allows
Complexity
-
Time complexity: \(O(log(n))\)
-
Space complexity: \(O(1)\)
Code
// 103ms
fun reverseBits(n: Int) =
Integer.reverse(n)
/*
(0..31).sumOf { b -> n shr b and 1 shl (31-b) }
n.toString(2).reversed().padEnd(32,'0').toInt(2)
(0..31).fold(0) { r, b -> n shr b and 1 shl (31-b) or r }
*/
// 2ms
pub const reverse_bits: fn(i32) -> i32 = i32::reverse_bits;
/*
pub fn reverse_bits(n: i32) -> i32 {
(0..32).map(|b| (n >> b & 1) << (31-b)).sum()
}
*/
15.02.2026
67. Add Binary easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1269
Problem TLDR
Binary strings sum #easy
Intuition
Carry = value / base
Approach
- ‘0’ = 48, so &1 converts char to 1 or 0
- insert(0) is O(n^2) but only 9ms for the test cases
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 9ms
fun addBinary(a: String, b: String) = buildString {
var c = 0; var i = a.lastIndex; var j = b.lastIndex
while (i >= 0 || j >= 0 || c > 0) {
c += if (i < 0) 0 else a[i--]-'0'
c += if (j < 0) 0 else b[j--]-'0'
insert(0, c % 2); c /= 2
}
}
// 0ms
pub fn add_binary(a: String, b: String) -> String {
let (mut a, mut b, mut c) = (a.bytes().rev(), b.bytes().rev(), 0);
from_fn(|| (a.len() > 0 || b.len() > 0 || c > 0).then(|| {
c += (a.next().unwrap_or(0)&1) + (b.next().unwrap_or(0)&1);
let v = c % 2 + 48; c /= 2; v as char
})).collect::<Vec<_>>().iter().rev().collect()
}
14.02.2026
799. Champagne Tower medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1268
Problem TLDR
Flow in a Pascal’s Triangle #medium
Intuition
// only 100 rows, we can simulate
// however p is 10^9, so not one-by-one
// x
// x/2 x/2
// x/4 (x/4+x/4) x/4
// x/8 (x/8+x/4) (x/4+x/8) x/8
// x/16 (x/16+x/16+x/8) (x/8+x/4) (x/8+x/16+x/16) x/16
//
// p=1 only first x filled
// p=2 2-1-1/2-1/2
// p=3 3-1-(1/2+1/2+1/2+1/2)
// p=4 4-1-2-(1/4+1/4+1/4+1/4)
// how to look at this problem?
//
// given 4 cups
// look at x - minus 1 cup, now have 3 cups
// look at x/2 - to make it full i need 2 cups, can i have them?
// so mark it full and at this row we spend 2 cups
// 1 cup extra
// look at x/2 - we spending 2 cups at this row, so the cup is full
// and our 1 extra cup stays
// look at x/4 - to make it full we need 4 cups, but have only 1
// so this place is 1/4, and we spend 1 cup at this row
// look at x/4+x/4 - 1/2
// x/4 - 1/4
// next row x/8 0 cups left, ok but what if we have 6 cups initially
// x - 1 5left
// x/2 - 1 take2 3left
// x/2 - 1
// x/4 3/4 take3 0left
// (x/4+x/4) 5/4 overflows 0left and 1/4 goes under this cup
// x/4 3/4
// x/8 -- 0/8
// x/8+x/4 5/8 so , should we maintain overflows individually?
// any better angle to look at this problem?
// 24 minute
// 4
// 3/2 3/2
// 1/4 1/4+1/4 1/4
//
Simulate the flow. Keep the flow values at cells. The next row use the (previouse-1)/2
Approach
- use an arena allocation of a single array[r]
- right-aligned pyramid allows to iterate only forward
Complexity
-
Time complexity: \(O(r^2)\)
-
Space complexity: \(O(r)\)
Code
// 107ms
fun champagneTower(p: Int, r: Int, c: Int): Double {
var o = DoubleArray(r+1); o[r] = 1.0*p
for (j in 1..r) for (i in r-j+1..r)
o[i] = max(0.0, (o[i]-1.0)/2).also { o[i-1] += it }
return min(1.0, o[c])
}
// 1ms
pub fn champagne_tower(p: i32, r: i32, c: i32) -> f64 {
let r = r as usize; let mut o = [0.;100]; o[r] = p as f64;
for j in 1..=r { for i in 1+r-j..=r {
o[i] = 0.0f64.max(o[i]-1.)/2.; o[i-1] += o[i]
}} o[c as usize].min(1.)
}
13.02.2026
3714. Longest Balanced Substring II medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1267
Problem TLDR
Largest equal frequencies substring of abc-string #medium #hashmap
Intuition
Didn’t solve.
// abbac
// i a:1 at i=0
// i b:1 at i=1
// i b:2 at i=2
// i a:2 at i=3
// i c:1 at i=4
//
// aaababbaaaa
//a: 123 4 5678
//b: 1 23
// * lookup where a==1 (4-3)
// *
// lookup where a==3 (6-3) (count of c should be 0 or 3)
// how to deal with c?
//
// aaabcabcbaaaa
//a: 123 4 5678
//b: . 1 2 3
//c: . 1 2
// . * how to deal with a=4? the valid substr bca b=1 c=1
// . look for `4-min(1,1)`
// . * b=2 a=4 c=1 i=b[2-min(4,1)] `cab`
// i * c=2 b=2 a=4 i=max(c[2-min(4,2)],b[0],a[2]),
// im not sure this works
// already 17 minute
// let's go hints
// cases?
// 43 minute, case "ccaca"
//
Case 1: repeated char max(if (repeates) f++ else f = 1)
Case 2: pairs (a,b)(a,c)(b,c) solve separately, max(i - hashmap(balance))
Case 3: (abc) max(i-hashmap(balance(a,b)|balance(a,c)))
Approach
- i know that for general alphabet the problem is O(n^2)
- that means just 3 letters should be solved individually
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 232ms
fun longestBalanced(s: String): Int {
var m = Array(4){mutableMapOf(0 to -1)}; var f = 0
var c = IntArray(3); var k = IntArray(3)
return s.indices.maxOf { i ->
c[s[i]-'a']++; if (i > 0 && s[i] == s[i-1]) f++ else f = 1; var r = f
for (e in 0..2) if (s[i]-'a' == e) {m[e]=HashMap(); m[e][0] = i; k[e] = 0} else {
if ((s[i]-'a'+1)%3 == e) ++k[e] else --k[e]
r = max(r, i - (m[e].getOrPut(k[e]){i} ?: i))
}
max(r, i - (m[3].getOrPut(((c[1]-c[0]) shl 16) + c[2]-c[0]){i} ?: i))
}
}
// 158ms
pub fn longest_balanced(s: String) -> i32 {
let (mut m, mut k, mut c, mut f) = (vec![Map::from([(0,-1)]);4], [0;3], [0;3], 0);
s.bytes().enumerate().map(|(i, b)| {
f = 1 + f * (i > 0 && b == s.as_bytes()[i-1]) as i32;
let (i, x) = (i as i32, (b - 97) as usize); c[x] += 1;
(0..3).map(|e| if x == e { m[e] = Map::from([(0, i)]); k[e] = 0; 0 } else {
k[e] += ((x + 1) % 3 == e) as i32 * 2 - 1; i - *m[e].entry(k[e]).or_insert(i)
}).max().unwrap().max(i - *m[3].entry(((c[1]-c[0])<<16)+c[2]-c[0]).or_insert(i)).max(f)
}).max().unwrap_or(0)
}
12.02.2026
3713. Longest Balanced Substring I medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1266
Problem TLDR
Max substring with equal frequencies #medium #sliding_window
Intuition
Brute-force.
- Start from every index. Go to the end. Compute the frequencies, Detect when all f the same.
- Check every window size decreasing. Compute the frequencies in a sliding window. Stop when all f the same.
Approach
- max(f) * uniq = window
Complexity
-
Time complexity: \(O(26n^2)\)
-
Space complexity: \(O(1)\)
Code
// 123ms
fun longestBalanced(s: String) = (s.length downTo 1).first { w ->
val f = IntArray(26); var u = 0
s.indices.any { i ->
if (f[s[i]-'a']++ < 1) ++u
if (i - w >= 0) if (--f[s[i-w]-'a'] < 1) --u
1 + i - w >= 0 && w == f.max() * u
}
}
// 16ms
pub fn longest_balanced(s: String) -> i32 {
let b = s.as_bytes(); (0..b.len()).map(|i| {
let (mut f, mut u, mut m) = ([0; 26], 0, 0);
b[i..].iter().enumerate().map(|(len, &c)| {
let k = (c - b'a') as usize;
if f[k] == 0 { u += 1 }; f[k] += 1; m = m.max(f[k]);
if m * u == len + 1 { (len + 1) as i32 } else { 0 }
}).max().unwrap_or(0)
}).max().unwrap_or(0)
}
11.02.2026
3721. Longest Balanced Subarray II hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1265
Problem TLDR
Max subarray evens count = odds count #hard #segment_tree
Intuition
Didn’t solve.
// this is a hard version of yesterdays problem
// O(n^2) will not be accepted
//
// my idea: define window size and binary search it
// when moving the window we have to adjust count on the fly
//
// 3 2 2 5 4 w=2
// * * f[3]=1 f[2]=1
// * * f[3]=0 f[2]=2 (and count uniqs in parallel)
//
// stop: does this function linear from true to false?
// small subarray is NOT balanced
// and big subarray IS balanced
// so the binary search wouldn't work
//
// given the small acceptance rate i go for hints at 10 minute
// so its a segment tree;
- Convert evens and odds to +1/-1
- Segment Tree: manage the prefix sum up to i
- If sum[root] == 0, then entire prefix is balanced
- If sum[root] != 0, find leftmost index
jwith the same value of sum[root], because prefix[i]-prfix[j] = 0 means subarray is balanced - Handle duplicated by updating the value to 0 in a segment tree
- The min[..] and right[..] are the prefix values of subtrees for the search. min[n] is the lowest possible prefix sum in this subtree
Approach
- try to understand how this works
- can you answer the question: why we are checking
s in min[left]..right[left]to go to the left subtree? Why we are shifting min[right]+sum[left]?
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(n)\)
Code
// 165ms
fun longestBalanced(n: IntArray): Int {
val sz=n.size; val sum = IntArray(sz*4); val min = IntArray(sz*4); val max = IntArray(sz*4)
fun update(idx: Int, v: Int, l: Int = 0, r: Int = sz-1, n: Int = 1) {
if (l == r) { sum[n] = v; min[n] = v; max[n] = v; return }
if (idx <= (l+r)/2) update(idx,v,l,(l+r)/2,n*2) else update(idx,v,(l+r)/2+1,r,n*2+1)
sum[n] = sum[n*2]+sum[n*2+1]
min[n] = min(min[n*2], sum[n*2] + min[n*2+1])
max[n] = max(max[n*2], sum[n*2] + max[n*2+1])
}
fun q(l: Int = 0, r: Int = sz-1, n: Int = 1, s: Int = 0): Int = if (l==r) l else
if (sum[1]-s in min[n*2]..max[n*2]) q(l,(l+r)/2,n*2,s) else q((l+r)/2+1,r,n*2+1,s+sum[n*2])
val p = IntArray(100001)
return n.indices.maxOf { i ->
if (p[n[i]] > 0) update(p[n[i]]-1, 0); p[n[i]] = i+1; update(i, n[i]%2*2-1)
if (sum[1] == 0) i + 1 else i - q()
}
}
10.02.2026
3719. Longest Balanced Subarray I medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1264
Problem TLDR
Longes even=odd subarray #medium #hashset
Intuition
// two pointers: we can't just blindly shrink/expand the window
// pref mid suf
//
// 1 3 5 6 7 9 11
// o o o e o o o
// which part to cut?
// is this DP? big acceptance rate, probably brain teaser
// the array size is small only 1500
// we can check every subarray in O(n^2)
// build a prefix sum array
// ok but how to deal with duplicates?
//
// 1 2 3 2
// 1 1 2 2 odds
// 0 1 1 2 evens non-uniq
// 0 1 1 1 evens uniq
// * * will give wrong count for this range
//
// let's try write o(n^3), can't think of an optimal solution
// TLE
// as expected
// 18 minute, go for hints; brute force? i litterally did that
// ok maybe there is an O(N^2) brute-force possible?
From every position go to the end and count evens and odds. Mark visited with hashset.
Approach
- use array instead of hashset
- array can be global if we mark visited values with current i
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n)\)
Code
// 263ms
fun longestBalanced(n: IntArray) = n.indices.maxOf { i ->
var b = 0; var m = HashSet<Int>()
1 - i + ((i..<n.size).lastOrNull { j ->
if (m.add(n[j])) b += 1 - n[j]%2*2; b == 0
}?:i-1)
}
// 16ms
pub fn longest_balanced(n: Vec<i32>) -> i32 {
let (mut r, mut s) = (0, [0;100001]);
for i in 0..n.len() { if n.len() - i <= r { break }; let mut b = 0;
for (j, &x) in n[i..].iter().enumerate() { let v = x as usize;
if s[v] <= i { s[v] = i + 1; b += 1 - (v as i32 & 1) * 2 }
if b == 0 { r = r.max(j + 1) }}} r as _
}
09.02.2026
1382. Balance a Binary Search Tree medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1263
Problem TLDR
Balance binary search tree #medium #dfs
Intuition
Collect to a list with in-order dfs. Build a new, count of left subtree is equal to the count of right subtree. Mid is current.
Approach
- we can store nodes itself on a list
- we can avoid building the list, just make a lazy iterator (sequence in Kotlin, or Stack and from_fn in Rust)
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\), O(log(n)) for the lazy iterator
Code
// 22ms
fun balanceBST(r: TreeNode?): TreeNode? {
val l = buildList {fun c(r: TreeNode?) {r?.run { c(left); add(r); c(right) }};c(r)}
fun b(f: Int, t: Int): TreeNode? =
if (f > t) null else l[(f+t)/2].apply {
left = b(f, (f+t)/2-1); right = b((f+t)/2+1, t)
}
return b(0, l.lastIndex)
}
// 0ms
type Tr = Rc<RefCell<TreeNode>>; type Opt = Option<Tr>;
pub fn balance_bst(r: Opt) -> Opt {
fn c(n: &Opt) -> i32 { n.as_ref().map_or(0, |n| 1 + c(&n.borrow().left) + c(&n.borrow().right)) }
let (n, mut s, mut c) = (c(&r), vec![], r);
let mut i = std::iter::from_fn(move || {
while let Some(t) = c.take() { c = t.borrow().left.clone(); s.push(t); }
s.pop().map(|t| { c = t.borrow().right.clone(); t })
});
fn b(k: i32, i: &mut impl Iterator<Item = Tr>) -> Opt {
if k < 1 { return None }; let l = b(k / 2, i);
i.next().map(|t| { t.borrow_mut().left = l; t.borrow_mut().right = b(k - 1 - k / 2, i); t })
}
b(n, &mut i)
}
08.02.2026
110. Balanced Binary Tree easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1262
Problem TLDR
Is tree balanced? #easy #dfs
Intuition
Solve the sub-problem for every node. Compare max depths for the left and right.
Approach
- we can use ‘marker’ depth as a boolean
- we can shortcircuit and don’t check the right subtree
- we can override values in a tree to golf the solutino
- BFS will not solve this: leafs can be at any heights, only max depths left&right for each node matters
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(log(n))\)
Code
// 0ms
fun isBalanced(r: TreeNode?): Boolean = r?.run {
val b = isBalanced(left) && isBalanced(right)
val l = left?.`val`?:0; val r = right?.`val`?:0
`val`= 1 + max(l,r); b && abs(l-r) < 2
} ?: true
// 0ms
pub fn is_balanced(r: Option<Rc<RefCell<TreeNode>>>) -> bool {
fn d(r: &Option<Rc<RefCell<TreeNode>>>) -> Result<i8, ()> {
let Some(n) = r else { return Ok(0) }; let n = n.borrow();
let l = d(&n.left)?; let r = d(&n.right)?;
if (l-r).abs() > 1 { Err(()) } else { Ok(1 + l.max(r)) }
}
d(&r).is_ok()
}
07.02.2026
1653. Minimum Deletions to Make String Balanced medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1261
Problem TLDR
Min removal to balance ‘ab’ #medium #greedy
Intuition
Split at each position and compare left and right counts of ‘a’ and ‘b’. The greedy intuition: count ‘b’, at each ‘a’ choose min of (remove ‘a’=d+1, keep ‘a’=b count removed)
Approach
- the corner cases of single ‘a’ and ‘b’ should be checked
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 24ms
fun minimumDeletions(s: String): Int {
var b = 0
return min(0,s.minOf { b += 2*(it - 'a')-1; b }) + s.count{it=='a'}
}
// 10ms
pub fn minimum_deletions(s: String) -> i32 {
s.bytes().fold((0,0),|(b,d),c|if c>b'a'{(b+1,d)}else{(b,b.min(d+1))}).1
}
06.02.2026
3634. Minimum Removals to Balance Array medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1260
Problem TLDR
Min removals to make min*k not less than max #medium #sliding_window
Intuition
// 12 18 k=2 wrong answer
// why 0 instead of 1 ?
// ok, read description wrong
// it k times not k diff
// another case is int overflow
// 1 10 10 10 10 20
Invert the problem: maximum window that we want to keep is the answer.
Approach
- lazy sliding window: we don’t have to shrink window, only care about expanding it
- use longs
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(1)\)
Code
// 41ms
fun minRemoval(n: IntArray, k: Int) = n.run {
sort(); var w = 0; count { 1L*it > 1L*k*n[w] && ++w > 0 }
}
// 9ms
pub fn min_removal(mut n: Vec<i32>, k: i32) -> i32 {
n.sort(); let mut w = 0;
for &x in &n { w += (x as i64 > n[w]as i64*k as i64) as usize}; w as i32
}
05.02.2026
3379. Transformed Array easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1259
Problem TLDR
Shuffled list i+n[i] #easy
Intuition
It took me 8 minutes to understand the problem. i - is the index of a result array i+n[i] is the index of a value we take
Approach
- in Kotlin & Rust we have built-in for negative mod:
mod&rem_euclid - in-place solution possible if we store results in a left bits
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 162ms
fun constructTransformedArray(n: IntArray) =
List(n.size) { n[(it + n[it]).mod(n.size)] }
// 3ms
pub fn construct_transformed_array(n: Vec<i32>) -> Vec<i32> {
(0..n.len()).map(|i|n[((n[i]+i as i32).rem_euclid(n.len() as i32)) as usize]).collect()
}
03.02.2026
3637. Trionic Array I easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1257
Problem TLDR
Validate inc,dec,inc sequency #easy
Intuition
Brute-Force O(n^3) is accepted.
Approach
- we can count peaks
- we can convert to string and use regex
- chunk_by, eq in Rust
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 32ms
fun isTrionic(n: IntArray) =
n.map{it}.zipWithNext(Int::compareTo)
.joinToString("").matches(Regex("(-1)+1+(-1)+"))
/*
n.map{it}.zipWithNext(Int::compareTo).let { s ->
s[0]<0 && 0 !in s && s.windowed(2).count{(a,b)->a!=b}==2 }
n[0]<n[1] && 2 == (2..<n.size).count {
(n[it-2]<n[it-1])!=(n[it-1]<n[it]) } &&
(1..<n.size).all{n[it]!=n[it-1]}
*/
// 0ms
pub fn is_trionic(n: Vec<i32>) -> bool {
n.windows(2).map(|w|w[1].cmp(&w[0])as i8).collect::<Vec<_>>()
.chunk_by(i8::eq).map(|c|c[0]).eq([1,-1,1])
}
02.02.2026
3013. Divide an Array Into Subarrays With Minimum Cost II hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1256
Problem TLDR
Min sum of k splits at max d distance #hard #sliding_window #heap
Intuition
Didn’t solve.
// take first
// select k-1 min-sum values at dist
//
// ***********
// * * *
//
// move (k-1) pointers?
//
// binarysearch?
//
// binarysearch+dp? dp answers for sum: canSplit[i]
// still should be minSplit[i] O(n^2)
// no other ideas, lets try dp, inner cycle is d, O(nkd)
// obviously deadend tle
// somehow stuck with brute-force dp
// looks like i didn't understood the description
// dist is not between splits
// it is between second and last
//
// let's go to hints
//
// sliding window + heap + heap
//
// *|**m*|********
// i-d i
//
// let's give up at 50 minutes
- Maintain sliding window of d
- Put k-1 best values in one sorted container (TreeSet of n[i],i)
- Remove overflows and d+1-distant values.
- Keep still-in-window values in a second storage container
- Balance when d+1-distant value has been removed
Approach
- there is also a BIT solution (ask ai): sort distinct values, keep BIT-arrays of counts and sums
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(n)\)
Code
// 533ms
fun minimumCost(n: IntArray, k: Int, d: Int): Long {
var sum = 0L; val c = compareBy<Int>({n[it]},{it})
val q = TreeSet(c); val s = TreeSet(c)
return (1..<n.size).minOf { i ->
q += i; sum += n[i]
if (q.size >= k) { val j = q.pollLast(); sum -= n[j]; s += j }
if (i-d-1 > 0 && !s.remove(i-d-1) && q.remove(i-d-1)) {
sum -= n[i-d-1]; val j = s.pollFirst(); sum += n[j]; q += j
}
if (i-d-1 >= 0) sum else 1L shl 60
} + n[0]
}
01.02.2026
3010. Divide an Array Into Subarrays With Minimum Cost I easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1255
Problem TLDR
Split on 2 min values #easy #quickselect
Intuition
Array is 50 elements. Sort and take 2. Or scan and deal with ifs.
Approach
- bitmask solution is also possible, enabling a branchless vectorizable code
Complexity
-
Time complexity: \(O(nlog(n))\), fastest is O(n)
-
Space complexity: \(O(n)\), fastest is O(1)
Code
// 10ms
fun minimumCost(n: IntArray) =
n.run{sort(1);n[0]+n[1]+n[2]}
/*
n.run{sort(1);n.take(3).sum()}
n[0]+n.drop(1).sorted().take(2).sum()
*/
// 0ms
pub fn minimum_cost(mut n: Vec<i32>) -> i32 {
n[1..].sort();n[0]+n[1]+n[2]
}
/*
n[1..].select_nth_unstable(1);n[0]+n[1]+n[2]
n[0] + n[1..].iter().sorted().take(2).sum::<i32>()
let (a,b)=n[1..].iter().fold((0u64,0),|(a,b),&x|(a|(1<<x),b|a&(1<<x)));
n[0] + (a.trailing_zeros() + (b | a & a - 1).trailing_zeros()) as i32
*/
31.01.2026
744. Find Smallest Letter Greater Than Target easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1254
Problem TLDR
Larger letter in array #easy
Intuition
Scan. Or do a binary search.
Approach
- or search in t+1..’z’
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 1ms
fun nextGreatestLetter(l: CharArray, t: Char) =
l.find{it>t}?:l[0]
/*
(l.filter{it>t}+l[0])[0]
l[l.count{it<=t}%l.size]
(l.map{it}-('a'..t)+l[0])[0]
(t+1..'z').find{it in l}?:l[0]
l[(-1-l.map{it}.binarySearch{if(it>t)1 else -1})%l.size]
l[(Arrays.binarySearch(l,t+1).let{if(it<0)-1-it else it})%l.size]
*/
// 0ms
pub fn next_greatest_letter(l: Vec<char>, t: char) -> char {
l[l.partition_point(|&c|c<=t)%l.len()]
}
30.01.2026
2977. Minimum Cost to Convert String II hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1253
Problem TLDR
Min cost to convert string with transitions of substrings #hard #dp #trie #hash #floyd-warshall
Intuition
- Build transitions matrix of tokens
- Do Floyd-Warshall for k i j ij = min(ij, ik+kj)
- Do DP to optimally split into substrings
- Do rolling hashing to do substring in O(1) ammortized
//
// TLE
//
// should i prepare all substrings?
//
// TLE dp as array?
//
// TLE
//
// expect me do write bottom up dp?
// comments says Floyd-Warshall causes tle
//
// 100^3 = 1000000 should be in acceptable range...
//
// i'll try to write bottom-up then will gave up, don't want to write dijkstra
//
// so the substring calculation is what gaves me tle, its o(n^3), n = 1000
//
Approach
- or do a Trie instead of rolling hashes, but we have to build transitions u,v from String to Trie id
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n^2)\)
Code
// 1231ms
fun minimumCost(s: String, t: String, o: Array<String>, c: Array<String>, ct: IntArray): Long {
val sa=o.toSet() + c; val a = sa.toList(); val ai = a.indices.associate { a[it] to it }
val m = Array(a.size) { i -> LongArray(a.size) { if (i==it) 0L else 1L shl 60 }}
for (i in o.indices) m[ai[o[i]]!!][ai[c[i]]!!] = min(1L*ct[i], m[ai[o[i]]!!][ai[c[i]]!!])
for (k in a.indices) for (i in a.indices) for (j in a.indices) m[i][j]=min(m[i][j], m[i][k] + m[k][j])
val dp = LongArray(s.length+1); val hs = a.map { it.fold(0) {h,c -> h*31+c.code }}.toSet()
for (i in s.length-1 downTo 0) {
dp[i] = if (s[i] == t[i]) dp[i + 1] else 1L shl 60; var sh = 0; var ht = 0
for (j in i..<s.length) {
sh = sh*31+s[j].code; ht = ht*31+t[j].code; if (sh !in hs || ht !in hs) continue
val si = ai[s.substring(i,j+1)]?:continue; val ti = ai[t.substring(i,j+1)]?:continue
dp[i] = min(dp[i], m[si][ti] + dp[j + 1])
}
}
return if (dp[0] < 1L shl 60) dp[0] else -1L
}
// 464ms
fun minimumCost(s: String, t: String, o: Array<String>, c: Array<String>, ct: IntArray): Long {
class T(var id: Int = -1) : HashMap<Char, T>(); val r = T(); var C = 0; val inf = 1L shl 60
fun a(w: String) = w.fold(r) { n, c -> n.getOrPut(c, ::T) }.run { if (id < 0) id = C++; id }
val u = o.map(::a); val v = c.map(::a); val m = Array(C) { i -> LongArray(C) { if (i == it) 0 else inf } }
for (i in o.indices) m[u[i]][v[i]] = min(m[u[i]][v[i]], ct[i].toLong())
for (k in 0..<C) for (i in 0..<C) for (j in 0..<C) m[i][j] = min(m[i][j], m[i][k] + m[k][j])
val dp = LongArray(s.length + 1) { inf }; dp[0] = 0
for (i in s.indices) {
if (dp[i] >= inf) continue; if (s[i] == t[i]) dp[i + 1] = min(dp[i + 1], dp[i]); var x = r; var y = r
for (j in i..<s.length) {
x = x[s[j]]?:break; y = y[t[j]]?:break
if (x.id >= 0 && y.id >= 0) dp[j + 1] = min(dp[j + 1], dp[i] + m[x.id][y.id])
}
}
return dp.last().takeIf { it < inf } ?: -1L
}
29.01.2026
2976. Minimum Cost to Convert String I medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1252
Problem TLDR
Min cost to convert string #medium #floyd-warshall
Intuition
Prepare transition matrix from any char to any char. Path relaxation: repeat path length, repeat(path length) a,b,c ab = min(ab,ac+cb) Floyd-Warshall: outer loop is the middle, try to update ab = min(ab, ac+cb)
// 1. find full min cost transition matrix from any char to any char
// 2. convert source to target sumOf { m[s[i]][t[i]] }
//
// 1 can be done with dfs 26^2
//
// floyd-warshall abc ac = min(ab+bc,ac)
// wrong answer ? (forgot about duplicates)
//
//
Approach
- the costs have duplicates, use min
Complexity
-
Time complexity: \(O(n + fw)\)
-
Space complexity: \(O(n + fw)\)
Code
// 33ms
fun minimumCost(s: String, t: String, o: CharArray, c: CharArray, ct: IntArray): Long {
val m = Array(26) { i -> LongArray(26) { if (i == it) 0 else 1 shl 30 }}
for (i in o.indices) m[o[i]-'a'][c[i]-'a'] = min(1L*ct[i], m[o[i]-'a'][c[i]-'a'])
for (c in 0..25) for (a in 0..25) for (b in 0..25) m[a][b] = min(m[a][b], m[a][c] + m[c][b])
return s.indices.sumOf { m[s[it]-'a'][t[it]-'a'].takeIf {it < 1L shl 30}?: return -1L}
}
// 6ms
pub fn minimum_cost(s: String, t: String, o: Vec<char>, c: Vec<char>, ct: Vec<i32>) -> i64 {
let mut m = [[1<<30;26];26]; for i in 0..26 { m[i][i] = 0 }
for i in 0..o.len() { let (a,b) = (o[i]as usize-97, c[i]as usize-97); m[a][b]=m[a][b].min(ct[i] as i64)}
for c in 0..26 { for a in 0..26 { for b in 0..26 { m[a][b] = m[a][b].min(m[a][c]+m[c][b])}}}
s.bytes().zip(t.bytes()).try_fold(0, |s, (a, b)| { let c = m[(a - 97) as usize][(b - 97) as usize];
if c >= 1 << 30 { None } else { Some(s + c) } }).unwrap_or(-1)
}
28.01.2026
3651. Minimum Cost Path with Teleportations hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1251
Problem TLDR
Min cost to walk 2D grid with free teleports #hard #dijkstra #dp
Intuition
Didn’t solved.
// BFS?
// A*
// Dijkstra
//
// store individual k for each path
//
// moves only right-down,
// can teleport backwards for some optimal paths
//
// we have to try all possible paths
//
// visited set is x,y,k
//
// to teleport we have to try all "lower" values
//
// 80*80=1600 or 10^3 can be O(n) scan for lowers?
//
// DP=DFS+cache? - no, we can visit twice with better value, so should be Dijkstra
//
// TLE
//
// TLE TLE TLE
// TLE
To make Dijkstra work skip already done teleportations for each lower[k], where lower is indices of all sorted values.
The dp solution: do k layered relaxations of teleportations and walks right-bottom.
Approach
- why in Dijkstra we can skip teleportations individually for each k?
- why in Dp solution we updating by batches of equal values the minimum value so far?
- why in Dp solution we sort descending and going from bigger to lower value and updating min(dp)?
Complexity
-
Time complexity: \(O(n^2klog(n))\) for Dijkstra and n^2k for DP
-
Space complexity: \(O(n^2k)\) for Dijkstra, n^2 for dp
Code
// 1505ms
fun minCost(g: Array<IntArray>, k: Int): Int {
val q = PriorityQueue<IntArray> { a,b -> a[3]-b[3] }
val d = Array(g.size) { Array(g[0].size) { IntArray(k+1) {1 shl 30}}}
val sorted = (0..<g.size*g[0].size).sortedBy {g[it/g[0].size][it%g[0].size]}
q += intArrayOf(0, 0, k, 0); val lower = IntArray(k+1)
while (q.size > 0) {
val (x,y,k,c) = q.poll()
if (x==g[0].size-1&&y==g.size-1) return c
for ((x,y) in arrayOf(x+1 to y, x to y+1))
if (x < g[0].size && y < g.size&&d[y][x][k]>c+g[y][x]) {
q += intArrayOf(x,y,k,c+g[y][x]); d[y][x][k] = c+g[y][x]
}
if (k > 0) while (lower[k] < sorted.size) {
val i = sorted[lower[k]]; val (ny,nx) = i/g[0].size to i%g[0].size
if (g[ny][nx] > g[y][x]) break
if (c < d[ny][nx][k-1]) { q += intArrayOf(nx,ny,k-1,c); d[ny][nx][k-1] = c }
lower[k]++
}
}; return -1
}
// 68ms
pub fn min_cost(g: Vec<Vec<i32>>, k: i32) -> i32 {
let w = g[0].len(); let g = g.concat(); let n = g.len();
let mut d = vec![1 << 30; n]; d[0] = 0;
let mut v: Vec<_> = (0..n).collect(); v.sort_by_key(|&i| -g[i]);
for a in 0..=k {
for i in 0..n {
if i >= w { d[i] = d[i].min(d[i - w] + g[i]); }
if i % w > 0 { d[i] = d[i].min(d[i - 1] + g[i]); }
}
if a == k { break; }
let (mut m, mut s) = (1 << 30, 0);
for i in 0..=n {
if i == n || g[v[i]] != g[v[s]]
{ for &j in &v[s..i] { d[j] = m; } s = i }
if i < n { m = m.min(d[v[i]]); }
}
} d[n-1]
}
27.01.2026
3650. Minimum Cost Path with Edge Reversals medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1250
Problem TLDR
Min path in weighted graph with reverse 2w nodes #medium #dijkstra
Intuition
Add reversed nodes to the graph. The reverse only once rule is automatically handled by Dijkstra: the optimal path will not visit nodes twice anyway.
// bfs? how to take reversal into account?
// how to choose which node to reverse?
// dijkstra
//
// how to handle immediate traversal?
// just replace original node with reversed dest?
//
// how to reverse just *once*?
//
Approach
- we don’t have to track distance array, the visited flags + heap is enough
Complexity
-
Time complexity: \(O((v+e)logV)\)
-
Space complexity: \(O(v^2)\)
Code
// 124ms
fun minCost(n: Int, e: Array<IntArray>): Int {
val g = Array(n) {ArrayList<Int>()}; val v = IntArray(n)
for ((a,b,w) in e) { g[a] += w*n+b; g[b] += 2*w*n+a }
val q = PriorityQueue<Long>(); q += 0
return (0..4*n).firstNotNullOfOrNull {
val wi = q.poll()?:0; val i = (wi%n).toInt()
if (v[i]++==0) for (cj in g[i]) q += wi-i + cj
if (i == n-1) (wi/n).toInt() else null
} ?: -1
}
// 64ms
pub fn min_cost(n: i32, e: Vec<Vec<i32>>) -> i32 {
let (N, mut g, mut q, mut v) = (n as i64, vec![vec![]; n as usize],
BinaryHeap::from([0]), vec![0; n as usize]);
for x in e {
let (u, k, w) = (x[0] as usize, x[1] as usize, x[2] as i64);
g[u].push(w * N + k as i64); g[k].push(w * 2 * N + u as i64);
}
while let Some(c) = q.pop() {
let i = (-c % N) as usize;
if i == v.len() - 1 { return (-c / N) as i32; }
if v[i] == 0 { v[i] = 1; for x in &g[i] { q.push(c - c % N - x); }}
} -1
}
26.01.2026
1200. Minimum Absolute Difference easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1249
Problem TLDR
Min diff pairs #easy
Intuition
Sort, compare adjucent pairs, find min, collect.
Approach
- groupBy.min also works
- updating the min diff and collecting can be done in a single go
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(n)\)
Code
// 138ms
fun minimumAbsDifference(a: IntArray) = a.sorted()
.windowed(2).groupBy{(a,b)->b-a}.minBy{(k,v)->k}.value
// 3ms
pub fn minimum_abs_difference(mut a: Vec<i32>) -> Vec<Vec<i32>> {
a.sort(); let mut d = (1..a.len()).map(|i|a[i]-a[i-1]).min().unwrap();
a.windows(2).filter(|w|w[1]-w[0]==d).map(Vec::from).collect()
}
25.01.2026
1984. Minimum Difference Between Highest and Lowest of K Scores easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1248
Problem TLDR
Min k-diff #easy #sliding_window
Intuition
Sort, then do a sliding window.
Approach
- use windows(k) or zip(skip(k))
Complexity
-
Time complexity: \(O(nlog(n))\)
-
Space complexity: \(O(n)\) or O(1)
Code
// 18ms
fun minimumDifference(n: IntArray, k: Int) =
n.run{sort();(k..size).minOfOrNull{n[it-1]-n[it-k]}?:0}
// 1ms
pub fn minimum_difference(mut n: Vec<i32>, k: i32) -> i32 {
n.sort(); n.iter().zip(n.iter().skip(k as usize-1)).map(|(a,b)|b-a).min().unwrap_or(0)
}
24.01.2026
1877. Minimize Maximum Pair Sum in Array medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1247
Problem TLDR
Min max pair #medium #brainteaser
Intuition
Sort. Pair maxes with mins.
Approach
- counting sort works too
Complexity
-
Time complexity: \(O(nlog(n))\)
-
Space complexity: \(O(n)\)
Code
// 629ms
fun minPairSum(n: IntArray) =
n.run{sort();zip(reversed(),Int::plus).max()}
// 13ms
pub fn min_pair_sum(mut n: Vec<i32>) -> i32 {
let (mut c,mut i) = ([0; 100001],0); for &x in &n { c[x as usize]+=1 }
for v in 0..100001 { for _ in 0..c[v] { n[i]=v as i32;i+=1}}
n.iter().zip(n.iter().rev()).map(|(a,b)|a+b).max().unwrap()
}
23.01.2026
3510. Minimum Pair Removal to Sort Array II hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1246
Problem TLDR
Sort by removing min-sum pairs #hard
Intuition
Didn’t solve.
// seen it yesterday
// it's too hard
// i'll try to do it from memory
//
// the algo:
// make a linked list
// put pairs into sorted heap
// remove one by one
//
// LL L i R RR
// *
// remove
// i gave up
- put sums into heap
- poll and remove right value of the pair
- adjust count of unordered pairs before the removal and after
Approach
- careful with overflow, can’t put everything in Long
- sentinels at both sides will help to avoid some checks
Complexity
-
Time complexity: \(O(nlog(n))\)
-
Space complexity: \(O(n)\)
Code
// 805ms
fun minimumPairRemoval(n: IntArray): Int {
val A = LongArray(n.size) {1L*n[it]} + Long.MAX_VALUE/2
val q = PriorityQueue<Pair<Long,Int>>(compareBy({it.first},{it.second}))
val L = IntArray(A.size) { it-1 }; val R = IntArray(A.size) { it+1 }
q += (0..<n.size).map {(A[it]+A[it+1]) to it}; var res = 0
fun b(i: Int, j: Int) = if (i>=0&&A[i] > A[j]) 1 else 0
var c = (0..<n.size).sumOf{b(it,it+1)}
while (c > 0) {
val (s,i) = q.poll(); if (L[R[i]] != i || s != A[i]+A[R[i]]) continue
c -= b(L[i], i) + b(i, R[i]) + b(R[i], R[R[i]])
A[i] = s; R[i] = R[R[i]]; L[R[i]] = i
c += b(L[i], i) + b(i, R[i])
if (L[i] >= 0) q += (1L*s+A[L[i]]) to L[i]
if (R[i] <= n.size) q += (1L*s+A[R[i]]) to i
res++
}
return res
}
22.01.2026
3507. Minimum Pair Removal to Sort Array I easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1245
Problem TLDR
Sort by removing lowest sum pairs #easy
Intuition
Simulate the process.
Approach
- just create a new array each time
- or in Rust we can actually remove by index in-place
Complexity
-
Time complexity: \(O(n^2)\) n^2log(n) for golfing in Kotlin
-
Space complexity: \(O(n)\)
Code
// 76ms
fun minimumPairRemoval(l: IntArray): Int {
val l = l.toList()
if (l == l.sorted()) return 0
val j = (1..<l.size).minBy { l[it-1] + l[it] }
return 1 + minimumPairRemoval((l.take(j-1) + (l[j-1]+l[j]) + l.drop(j+1)).toIntArray())
}
// 0ms
pub fn minimum_pair_removal(mut l: Vec<i32>) -> i32 {
(0..).find(|_| {
let ok = l.windows(2).all(|w| w[0] <= w[1]);
if let Some(j) = (1..l.len()).min_by_key(|&i| l[i-1] + l[i]) { l[j-1] += l[j]; l.remove(j); }
ok
}).unwrap()
}
21.01.2026
3315. Construct the Minimum Bitwise Array II medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1244
Problem TLDR
Reverse operation x or (x+1) #medium #bits
Intuition
Forward operation: flips first one-bit in tail of ones. Reverse: flip rightmost zero bit.
/*
3 : 11 -> 1 : 1
5 : 101 -> 4 : 100
7 : 111 -> 3 : 11
11 : 1011 -> 9 : 1001
13 : 1101 -> 12 : 1100
17 : 10001 -> 16 : 10000
19 : 10011 -> 17 : 10001
23 : 10111 -> 19 : 10011
29 : 11101 -> 28 : 11100
31 : 11111 -> 15 : 1111
37 : 100101 -> 36 : 100100
41 : 101001 -> 40 : 101000
43 : 101011 -> 41 : 101001
47 : 101111 -> 39 : 100111
53 : 110101 -> 52 : 110100
59 : 111011 -> 57 : 111001
61 : 111101 -> 60 : 111100
67 : 1000011 -> 65 : 1000001
71 : 1000111 -> 67 : 1000011
73 : 1001001 -> 72 : 1001000
79 : 1001111 -> 71 : 1000111
83 : 1010011 -> 81 : 1010001
89 : 1011001 -> 88 : 1011000
97 : 1100001 -> 96 : 1100000
*/
// 79 : 1001111 -> 71 : 1000111
// +1 1010000
// & 1000000
// + 10001111
// /2 1000111
//
// 97 : 1100001 -> 96 : 1100000
// +1 1100010
// & 1100000
// + x+x in binary is 2*x which is shift left by 1
// 11000001 but we preserve a tail as is
// /2 1100000
One way: inv, &, /2, xor Second way: +1, &, +, /2
Approach
- or you can just manually find the rightmost zero bit and flip it
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 7ms
fun minBitwiseArray(n: List<Int>) = n.map {
if (it==2)-1 else it xor it.inv().takeLowestOneBit()/2
}
// 0ms
pub fn min_bitwise_array(n: Vec<i32>) -> Vec<i32> {
n.iter().map(|&n|if n==2{-1}else{(n+(n&(n+1)))/2}).collect()
}
20.01.2026
3314. Construct the Minimum Bitwise Array I easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1243
Problem TLDR
| Reverse x | (x+1) operation on prime numbers #easy |
Intuition
The op: x|(x+1) does set rightmost 0 to 1. 100: 100 | 101 = 101 Reversing it: set first suffix 1 bit to 0. 101: 100
// 111 +1
//1000
//
// 101 100 or 101
// 111 11 or 100
// 10 -
// 11 1 or 10
//
// 1011 1001 or 1010
// 1101 1100 or 1
// 11111 1111 or 10000
Approach
- do a brute-force
- learn from others
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 7ms
fun minBitwiseArray(n: List<Int>)=n.map {
if (it == 2) -1 else it xor it.inv().takeLowestOneBit()/2
}
// 0ms
pub fn min_bitwise_array(n: Vec<i32>) -> Vec<i32> {
n.iter().map(|&n| if n == 2 {-1} else {n^((n+1)&!n)/2}).collect()
}
19.01.2025
1292. Maximum Side Length of a Square with Sum Less than or Equal to Threshold medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1242
Problem TLDR
Max square with sum less than threshold #medium #prefix-sum
Intuition
// let's try with brute-force 300^4, its 10^6
// ok, this is TLE
// we have to do prefix sums...
Brute-force is not accepted. Optimize with prefix sums of all rectangles with top left corner 0,0.
Approach
- optimization: binary search the size
- optimization: increase the size by checking size+1 is a new max
- we only have to go +1 to the top-left, because the previous is at most S (it is not possible to “discover” bigger than s+1, otherwise we would already have the more than ‘s’)
Complexity
-
Time complexity: \(O(nm)\)
-
Space complexity: \(O(nm)\), can be in-place
Code
// 9ms
fun maxSideLength(m: Array<IntArray>, t: Int): Int {
var s = 0; val d = Array(301) { IntArray(301) }
for (y in m.indices) for (x in m[0].indices) {
d[y + 1][x + 1] = d[y][x + 1] + d[y + 1][x] - d[y][x] + m[y][x]
if (y>=s && x>=s && t>=d[y+1][x+1]-d[y-s][x+1]-d[y+1][x-s]+d[y-s][x-s])++s
}
return s
}
// 0ms
pub fn max_side_length(m: Vec<Vec<i32>>, t: i32) -> i32 {
let (mut d, mut s) = ([[0; 301]; 301], 0);
for (i, j) in iproduct!(0..m.len(), 0..m[0].len()) { if {
d[i+1][j+1] = d[i][j+1] + d[i+1][j] - d[i][j] + m[i][j];
i>=s && j>=s && t>=d[i+1][j+1]-d[i-s][j+1]-d[i+1][j-s]+d[i-s][j-s]}
{s+=1}} s as i32
}
18.01.2026
1895. Largest Magic Square medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1241
Problem TLDR
Max magic square #medium
Intuition
Brute-force is accepted.
Approach
- can be optimized with prefix sums: sum(a..b) = p[b]-p[a]
Complexity
-
Time complexity: \(O(n^4)\), or O(n^2) with prefix sums
-
Space complexity: \(O(1)\), or O(n^2) to store prefix sums
Code
// 54ms
fun largestMagicSquare(g: Array<IntArray>) = (min(g[0].size,g.size) downTo 1)
.first { s -> (0..g.size-s).any { y -> (0..g[0].size-s).any { x -> val o = 0..<s
val d = o.sumOf { g[y+it][x+it] }
d == o.sumOf { g[y+it][x-it+s-1] } && o.all { i ->
d == o.sumOf { g[y+i][x+it] } &&
d == o.sumOf { g[y+it][x+i] }}}}}
// 7ms
pub fn largest_magic_square(g: Vec<Vec<i32>>) -> i32 {
(2..=g.len().min(g[0].len())).rev().find(|&s|
iproduct!(0..=g[0].len()-s, 0..=g.len()-s).any(|(x, y)| {
let d = (0..s).map(|i| g[y+i][x+i]).sum::<i32>();
d == (0..s).map(|i| g[y+i][x+s-1-i]).sum::<i32>() && (0..s).all(|j|
d == (0..s).map(|i| g[y+j][x+i]).sum::<i32>() &&
d == (0..s).map(|i| g[y+i][x+j]).sum::<i32>())})).unwrap_or(1) as _
}
17.01.2026
3047. Find the Largest Area of Square Inside Two Rectangles medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1240
Problem TLDR
Max square in intersection #medium
Intuition
Brute-force is accepted. The intersection is max(bottom left) & min(top right)
Approach
- we also can sort and return inner loop early
- or freeze the result S length and binary search if it fits
- or sort and line sweep 2d or with segment tree
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(1)\)
Code
// 350ms
fun largestSquareArea(a: Array<IntArray>, b: Array<IntArray>) =
(0..<b.size-1).maxOf { i -> (i+1..<b.size).maxOf { j ->
(0..1).minOf { min(b[i][it],b[j][it])-max(a[i][it],a[j][it]) }
}}.let { 1L*it*max(0,it) }
// 77ms
pub fn largest_square_area(a: Vec<Vec<i32>>, b: Vec<Vec<i32>>) -> i64 {
a.iter().zip(&b).tuple_combinations().map(|((l1, r1), (l2, r2))|
(0..2).map(|k| r1[k].min(r2[k]) - l1[k].max(l2[k])).min().unwrap()
).max().map_or(0, |x| (x.max(0) as i64).pow(2))
}
16.01.2026
2975. Maximum Square Area by Removing Fences From a Field medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1239
Problem TLDR
Max square after remove vertical or horizontal bars #medium
Intuition
// possible horizontal widths
// intersect
// possible vertical heights
//
// 1D problem: collect possible gaps
//
// |*****|**|*|
// 5 2 1
// 1,2,5, 1+2, 2+5, 1+2+5
// |+1 -- all prev + x
// 1+1,(1+2)+1,(1+2+5)+1
// max size is 600, so O(n^2) should be acceptable
Solve 1D problem. Find all possible gaps. Intersect. Pick max.
Approach
- to find all gaps just use 2d for loop
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n^2)\)
Code
// 648ms
fun maximizeSquareArea(m: Int, n: Int, h: IntArray, v: IntArray) = listOf(h+1+m,v+1+n)
.map { buildSet { for (a in it) for (b in it) if (a>b) add(a-b) }}
.let {(a,b)->a.intersect(b).maxOrNull()}?.let {1L*it*it%1000000007} ?: -1
// 355ms
pub fn maximize_square_area(m: i32, n: i32, mut h: Vec<i32>, mut v: Vec<i32>) -> i32 {
let [a,b] = [(h,m),(v,n)].map(|(mut x,y)| {
let mut s = HashSet::new(); x.extend([1,y]);
for a in &x { for b in &x { if a > b { s.insert(a-b); }}}; s });
a.intersection(&b).max().map_or(-1, |&x| ((x as i64*x as i64)%1000000007) as i32)
}
15.01.2026
2943. Maximize Area of Square Hole in Grid medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1238
Problem TLDR
Max square area after removing bars in a grid #medium #intervals
Intuition
Count consequtive intervals separately for horizontal and vertical bars. Then min(max(h,v))^2.
One way: sort bars, count consequtive with counter Second way: use a HashMap(x, length) and update x-l, x+r with 1+m[x-1]+m[x+1]
Approach
- do +1 or just init counter with 2
- for the HashMap we can skip writing to the middle m[x]
Complexity
-
Time complexity: \(O(nlog(n))\), or O(n)
-
Space complexity: \(O(1)\) or O(n)
Code
// 22ms
fun maximizeSquareHoleArea(n: Int, m: Int, h: IntArray, v: IntArray) =
listOf(h,v).minOf { val m = HashMap<Int, Int>()
1 + it.maxOf { x -> val l = m[x-1]?:0; val r = m[x+1]?:0
(l+r+1).also{m[x-l]=it;m[x+r]=it}}
}.let{it*it}
// 0ms
pub fn maximize_square_hole_area(_: i32, _: i32, h: Vec<i32>, v: Vec<i32>) -> i32 {
[h, v].map(|s| s.into_iter().sorted().collect::<Vec<_>>()
.chunk_by(|a, b| b - a < 2).map(|c| c.len() + 1).max().unwrap_or(2)
).into_iter().min().unwrap().pow(2) as _
}
14.01.2026
3454. Separate Squares II hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1237
Problem TLDR
Min y to equal split areas exclude intersections #hard #line_sweep
Intuition
Didn’t solved.
// sort by y
// do a line sweep
//
// widths by y
//
// 0 0 0 1 1 2 0 0 3 0 0
// i area before & area after
// 1*2+2*1+3*1 total
// but how to find min y center?
//
// ok let's just start with making a widths list
// how to merge x segments?
// ok this is hard for me, let's go to hints
// gave up after 15 minute
Line sweep by Y. Record (x start, x end) pairs. On each next Y line sweep elapsed x-pairs to find non-overlapping w.
Approach
- accepted without segment tree
Complexity
-
Time complexity: \(O(nlogn)\), worst-case would be O(n^2log^2(n))
-
Space complexity: \(O(n)\)
Code
// 459ms
fun separateSquares(s: Array<IntArray>): Double {
val (e,xlr,slices) = List(3) {ArrayList<List<Double>>()}
for ((x,y,l) in s) {e+=listOf(1.0*y,1.0,1.0*x,1.0*x+l);e+=listOf(1.0*y+l,0.0,1.0*x,1.0*x+l)}
e.sortBy { it[0] }; var prev = 0.0; var total = 0.0
for ((y,e,xl,xr) in e) {
if (y > prev) {
xlr.sortBy {it[0]}; var w = 0.0; var x = 0.0
for ((l,r) in xlr) if (x<r) { w += r - max(x,l); x = r }
slices += listOf(total, prev, y-prev, w); total += (y-prev)*w
}
prev = y; if (e>0) xlr += listOf(xl,xr) else xlr -= listOf(xl,xr)
}
val (cur,sy,h,w) = slices.first { (cur, sy,h,w) -> cur + h * w >= total/2 }
return (total/2 - cur) / w + sy
}
// 373ms
pub fn separate_squares(s: Vec<Vec<i32>>) -> f64 {
let mut ev: Vec<_> = s.iter().flat_map(|v| {
let (x, y, l) = (v[0] as f64, v[1] as f64, v[2] as f64); [(y,1,x,x+l),(y+l,-1,x,x+l)]}).collect();
ev.sort_by(|a, b| a.0.total_cmp(&b.0)); let (mut xlr, mut sl, mut tot, mut py) = (vec![], vec![], 0., 0.);
for (y, op, l, r) in ev {
if y > py {
xlr.sort_by(|a: &(f64, f64), b| a.0.total_cmp(&b.0));
let (mut w, mut mx) = (0., 0.);
for &(al, ar) in &xlr { if mx < ar { w += ar - mx.max(al); mx = ar}}
sl.push((tot, py, y - py, w)); tot += (y - py) * w; py = y
}
if op > 0 { xlr.push((l, r)); }
else { xlr.remove(xlr.iter().position(|&x| x == (l, r)).unwrap()); }
}
let (cur, y, _, w) = sl.into_iter().find(|&(c, _, h, w)| c + h * w >= tot / 2.).unwrap();
(tot / 2. - cur) / w + y
}
13.01.2026
3453. Separate Squares I medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1236
Problem TLDR
Min Y to split into equal areas #medium #bs
Intuition
// 1. binary search, but with doubles
// 2. idk about any other ideas
// 3. why do we need X coordinate?
//
// binary search gives wrong result on big numbers
// ok 22 minute, lets read hints - "binary search"
// so, no extra hints
// overflow
//
// ok 50 minutes, let's gave up
Binary search on Y, compare the below and above areas.
Approach
- carefull with overflow
l*l
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 94ms
fun separateSquares(s: Array<IntArray>): Double {
var lo = 0.0; var hi = 1000000000.0; val t = s.sumOf {1.0*it[2]*it[2]}/2
while (abs(lo - hi) > 0.00001) {
val m = lo + (hi - lo) / 2.0
if (s.sumOf{(x,y,l)->if(m>y)min(m-y,1.0*l)*l else 0.0}>=t) hi = m else lo = m
}
return lo
}
// 96ms
pub fn separate_squares(s: Vec<Vec<i32>>) -> f64 {
let (mut l, mut h, t) = (0.,1e9, s.iter().map(|v| v[2]as f64 * v[2] as f64).sum::<f64>()/2.);
while h - l > 1e-5 {
let m = (l + h) / 2.;
if t > s.iter().map(|v| {
let (y,s) = (v[1] as f64, v[2] as f64);
if m > y { (m - y).min(s) * s } else { 0. }
}).sum::<f64>() { l = m } else { h = m }
} l
}
12.01.2026
1266. Minimum Time Visiting All Points easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1235
Problem TLDR
Euclid travel distance #easy #brainteaser
Intuition
D = max(dx,dy)
Approach
- indices: [1..n)
- zip, zipWithNext, windows, fold
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 6ms
fun minTimeToVisitAllPoints(p: Array<IntArray>) = (1..<p.size)
.sumOf {i->max(abs(p[i][0]-p[i-1][0]), abs(p[i][1]-p[i-1][1]))}
// 0ms
pub fn min_time_to_visit_all_points(p: Vec<Vec<i32>>) -> i32 {
p.iter().zip(&p[1..]).map(|(a,b)|(a[0]-b[0]).abs().max((a[1]-b[1]).abs())).sum()
}
11.01.2026
85. Maximal Rectangle hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1234
Problem TLDR
Max all-1 rectangle in 2D matrix #hard #monotonic_stack
Intuition
The histogram solution: use monotonic increasing stack for each row. Update result when popping values from it.
Approach
- to avoid duplicated code after the row is finished, use sentinel 0 or just one extra iteration
- we can store heights in a separate array or just modify matrix
- for the
leftx coordinate use the valuebeforepopped value
Complexity
-
Time complexity: \(O(nm)\)
-
Space complexity: \(O(m)\)
Code
// 31ms
fun maximalRectangle(m: Array<CharArray>) = Stack<Int>().run {
var res = 0; for (y in m.indices) for (x in 0..m[0].size) {
if (y>0&&x<m[0].size) if (m[y][x]>'0')m[y][x]+=m[y-1][x]-'0'
while (size > 0 && (x==m[0].size||m[y][peek()]>m[y][x]))
res = max(res, (m[y][pop()]-'0')*(x-if(size>0)peek()+1 else 0))
if (x < m[0].size) this += x else clear()
}; res
}
// 0ms
pub fn maximal_rectangle(mut m: Vec<Vec<char>>) -> i32 {
let (mut q, mut r) = (vec![], 0);
for y in 0..m.len() { for x in 0..=m[0].len() {
if y > 0 && x < m[0].len() { if m[y][x] > '0' { m[y][x] = ('1' as u8 + (m[y-1][x] as u8 -b'0'))as char}}
while q.len() > 0 && (x == m[0].len() || m[y][q[q.len()-1]] > m[y][x]) {
r = r.max((m[y][q.pop().unwrap()]as u8 -b'0')as i32 * if q.len()>0 {x-q[q.len()-1]-1} else {x}as i32)}
if x < m[0].len() { q.push(x) } else { q.clear() }
}} r
}
10.01.2026
712. Minimum ASCII Delete Sum for Two Strings medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1233
Problem TLDR
Min removed sum to make strings equal #medium #dp
Intuition
One way: DP[i][j] is the removed sum for suffix a[i..],b[j..], take a[i] or b[j] when a[i]!=b[j].
Second way: DP[i][j] is the Longest Common Substring for suffix a[i..],b[j..], take a[i] when a[i]==b[j].
Approach
- the DFS top-down is easier to write
- space optimize with i%2 trick: only the last row is needed
- forward write to simplify indices dp[i+1][j+1] = … a[i],b[j]
Complexity
-
Time complexity: \(O(nm)\)
-
Space complexity: \(O(m)\)
Code
// 30ms
fun minimumDeleteSum(a: String, b: String): Int {
val d = Array(2) { IntArray(b.length+1) }
for (i in a.indices) for (j in b.indices) d[(i+1)%2][j+1] =
if (a[i] == b[j]) a[i].code + d[i%2][j] else max(d[i%2][j+1], d[(i+1)%2][j])
return a.sumOf{it.code}+b.sumOf{it.code}-2*d[a.length%2][b.length]
}
// 3ms
pub fn minimum_delete_sum(a: String, b: String) -> i32 {
let (a, b, mut d) = (a.as_bytes(), b.as_bytes(), vec![vec![0; b.len() + 1]; 2]);
for j in 0..b.len() { d[0][j + 1] = d[0][j] + b[j] as i32 }
for i in 0..a.len() { for j in 0..=b.len() { d[(i + 1) & 1][j] =
if j < 1 { d[i & 1][0] + a[i] as i32 } else if a[i] == b[j - 1] { d[i & 1][j - 1] }
else { (a[i] as i32 + d[i & 1][j]).min(b[j - 1] as i32 + d[(i + 1) & 1][j - 1]) }
}}
d[a.len() & 1][b.len()]
}
09.01.2026
865. Smallest Subtree with all the Deepest Nodes medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1232
Problem TLDR
Lowest common ancestor of the deepest nodes #medium
Intuition
Do a DFS. One way: propagate depth down, compare on the way up. Second way: return both depth & result on the way up.
Approach
- how to use uniqness?
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(logn)\)
Code
// 1ms
fun subtreeWithAllDeepest(r: TreeNode?): TreeNode? {
fun dfs(n: TreeNode?): Pair<Int, TreeNode?> = n?.run {
val (l, a) = dfs(left); val (r, b) = dfs(right)
(1 + max(l, r)) to if (l > r) a else if (l < r) b else n
} ?: 0 to null
return dfs(r).second
}
// 0ms
pub fn subtree_with_all_deepest(r: Option<Rc<RefCell<TreeNode>>>) -> Option<Rc<RefCell<TreeNode>>> {
fn dfs(ro: &Option<Rc<RefCell<TreeNode>>>, d: i32, max: &mut i32, res: &mut Option<Rc<RefCell<TreeNode>>>) -> i32 {
let Some(n) = ro else { return d }; let n = n.borrow();
let (l,r) = (dfs(&n.left, d+1, max, res), dfs(&n.right, d+1, max, res)); *max = l.max(r).max(*max);
if l == *max && r == *max { *res = ro.clone() }; l.max(r)
}
let (mut max, mut res) = (0, None); dfs(&r, 0, &mut max, &mut res); res
}
08.01.2026
1458. Max Dot Product of Two Subsequences hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1231
Problem TLDR
Max product of 2 subsequencies #hard #dp
Intuition
The solution is stable for every suffix (a[i..],b[j..]), memoize by the key of (i,j).
Approach
- use forward trick to not check the bounds dp[i+1]=dp[i]…
- use ‘stop here’ trick to handle negatives a[i]*b[j] + 0 instead of calling dfs(i+1,j+1)
- as we only accessing +-1, we can store just one recent row of dp instead of a full table
Complexity
-
Time complexity: \(O(nm)\)
-
Space complexity: \(O(m)\)
Code
// 17ms
fun maxDotProduct(a: IntArray, b: IntArray): Int {
val d = Array(2) { IntArray(b.size+1) { -1000000 }}
for (i in a.indices) for (j in b.indices) d[(i+1)%2][j+1] =
maxOf(d[(i+1)%2][j], d[i%2][j+1], a[i]*b[j], a[i]*b[j]+d[i%2][j])
return d[a.size%2][b.size]
}
// 0ms
pub fn max_dot_product(a: Vec<i32>, b: Vec<i32>) -> i32 {
let mut d = vec![vec![-1000000;b.len()+1];2];
for i in 0..a.len() { for j in 0..b.len() {
d[(i+1)&1][j+1] = d[(i+1)&1][j].max(d[i&1][j+1]).max(a[i]*b[j]).max(a[i]*b[j]+d[i&1][j])
}} d[a.len()&1][b.len()]
}
07.01.2026
1339. Maximum Product of Splitted Binary Tree medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1230
Problem TLDR
Max sumA*sumB of a tree split #medium
Intuition
Find the total sum, then subtract each subtree to find the other sum.
Approach
- we can calculate in 32 bit if use extemum of x = s/2
- we can collect visited sums into a hashset
- we can skip sums that are smaller than max/2
- the fastest runtime speed is still calculation of x*(max-x) in-place
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(logn)\)
Code
// 11ms
fun maxProduct(r: TreeNode?): Long {
val a = ArrayList<Int>()
fun s(r: TreeNode?): Int = r
?.run {val s = s(left)+s(right)+`val`; a += s; s}?:0
val s = s(r); return a.maxOf {1L*it*(s-it)}%1000000007
}
// 3ms
pub fn max_product(r: Option<Rc<RefCell<TreeNode>>>) -> i32 {
fn s(r: &Option<Rc<RefCell<TreeNode>>>, res: &mut i64, max: &mut i32) -> i32 {
let Some(n) = r else { return 0 }; let n = n.borrow();
let s = s(&n.left,res,max)+s(&n.right,res,max)+n.val; *max = s.max(*max);
*res = (*res).max(s as i64*(*max - s)as i64); s
}
let (mut res,mut max) = (0,0); for _ in 0..2 {s(&r, &mut res, &mut max);} (res%1000000007) as i32
}
06.01.2026
1161. Maximum Level Sum of a Binary Tree medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1229
Problem TLDR
Min level max sum in tree #medium
Intuition
Use BFS or DFS.
Approach
- compute max only after all number are added in this level
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 34ms
fun maxLevelSum(r: TreeNode?) = ArrayDeque<TreeNode>().let { q ->
q += r!!; (1..25).maxBy { if (q.size < 1) -100001 else
(1..q.size).sumOf { q.removeFirst().run {
left?.let { q += it }; right?.let { q += it }; `val`
}}
}
}
// 6ms
pub fn max_level_sum(r: Option<Rc<RefCell<TreeNode>>>) -> i32 {
let (mut m, mut ml) = ([0;27],0);
fn dfs(m: &mut[i32], ml: &mut usize, l: usize, n: &Option<Rc<RefCell<TreeNode>>>) {
let Some(n) = n else { return }; if l > 25 { return }; let n = n.borrow();
m[l] += n.val; *ml = l.max(*ml); dfs(m, ml, l+1, &n.left); dfs(m, ml, l+1, &n.right)
}
dfs(&mut m, &mut ml, 0, &r); -(0..=ml).map(|i|(m[i],-(i as i32)-1)).max().unwrap().1
}
05.01.2026
1975. Maximum Matrix Sum medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1226
Problem TLDR
Max sum after multiply -1 adjacent cells #medium #brainteaser
Intuition
Notice that we can move “-“ to any cell in the matrix. Count “-“, find sum and find minimum value to subtract.
// we can propagate - to any cell
// if even -- count then all positive
// otherwise make it the smallest abs
Approach
- don’t forget to subtract 2*min
Complexity
-
Time complexity: \(O(m)\)
-
Space complexity: \(O(1)\)
Code
// 9ms
fun maxMatrixSum(m: Array<IntArray>): Long {
var cnt = 0; var min = Int.MAX_VALUE
return m.sumOf { it.sumOf { v ->
if (v < 0) cnt++
min = min(min, abs(v)); abs(v).toLong()
}} - (cnt%2)*2*min
}
// 0ms
pub fn max_matrix_sum(m: Vec<Vec<i32>>) -> i64 {
let (mut c, mut min) = (0, i64::MAX);
m.iter().map(|r| r.iter().map(|&x|{ let v = x.abs() as i64;
min = min.min(v); c += (x < 0) as i64; v
}).sum::<i64>()).sum::<i64>() - 2*min*(c&1)
}
04.12.2025
1390. Four Divisors medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1225
Problem TLDR
Sum of exactly four-divisors of each number #medium #math
Intuition
Brute-force divisors up to sqrt(n) for each number.
// math problem
// lets brute-force?
// two is 1 and number itself; two others we should find
//
// strange case: [7286,18704,70773,8224,91675] 10932
// 10932 = 8224 + 1 + a + b
// a*b = 10932
//
// 10932 = 8224 + 1 + 10932/b + b
//
// divisors are uniq for 4: 1 2 4, 2 is collapsed
//
// ok 27 minute looking for hints
// ok they suggest brute-force O(nsqrt(n))
//
Approach
- another way: pre-find all divisors for 1..max
Complexity
-
Time complexity: \(O(nsqrt(n))\)
-
Space complexity: \(O(1)\)
Code
// 33ms
fun sumFourDivisors(n: IntArray) = n.sumOf { n ->
var f = 0; var x = 1; var s = 1+n
while (++x*x <= n) if (n%x==0) {++f;s += x+n/x}
if (f==1&&--x*x<n) s else 0
}
// 31ms
pub fn sum_four_divisors(n: Vec<i32>) -> i32 {
let m = *n.iter().max().unwrap() as usize;
let (mut c, mut s, mut r) = (vec![0; m+1], vec![0;m+1], 0);
for a in 1..=m { for v in (a..=m).step_by(a) {c[v]+=1; s[v]+=a as i32}}
n.iter().map(|&n|if (c[n as usize]==4) {s[n as usize]}else{0}).sum::<i32>()
}
03.12.2026
1411. Number of Ways to Paint N × 3 Grid hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1224
Problem TLDR
Ways to color 3xN grid #hard #dp
Intuition
Do DFS + dp. The state is current cell and 3 previous colors.
Approach
- optimization 1: there are only two patterns A -> 2A+2B, B -> 2A+3B
- optimization 2: exponentiation matrix for O(log(n)) solution. Skipped this, too hard to implement
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 1ms
fun numOfWays(n: Int): Long {
var a = 6L; var b = a; val M = 1000000007
for (i in 2..n) { a += (a+b+b)%M; b += a }
return (a+b)%M
}
// 20ms
pub fn num_of_ways(n: i32) -> i32 {
let mut dp = vec![-1;(n*192) as usize];
fn dfs(dp: &mut [i32], i: i32, m: i32, n: i32) -> i32 {
if i == n { return 1 }; let k = ((i<<6)|m) as usize; if dp[k] != -1 { return dp[k] }
let res = ((0..3).map(|c|
if i%3>0 && c==m&3 || i>=3&&c==m>>4 {0} else { dfs(dp,i+1,((m<<2)|c)&63,n)as i64}
).sum::<i64>()%1000000007) as i32; dp[k] = res; res
}
dfs(&mut dp, 0, 0, 3*n)
}
02.01.2026
961. N-Repeated Element in Size 2N Array easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1223
Problem TLDR
Duplicate majority element #easy
Intuition
The easy intuition is just to count frequencies.
Approach
- frequency of 2 is enough
- if first element skipped then majority voting solution applicable
- another fun solution is to look at sum and uniq’s sum
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 35ms
fun repeatedNTimes(n: IntArray) =
(n.sum() - n.toSet().sum())/(n.size/2-1)
// 0ms
pub fn repeated_n_times(n: Vec<i32>) -> i32 {
let (mut j, mut f) = (0, 0);
n[(1..n.len()).find(|&i| {
if f == 0 { j = i }
f += (n[0]==n[i]||n[i]==n[j]) as i32 * 2 -1; f > 1
}).unwrap_or(j)]
}
01.01.2026
66. Plus One easy
blog post
substack
youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1222
Problem TLDR
Increment big number #easy
Intuition
The simplest and robust solution is a separate container for result digits and a counter for carry.
Approach
- optimization: stop at first non-nine
- optimization: count suffix nines in a forward cache-friendly pass
Complexity
- Time complexity: \(O(n)\)
- Space complexity:
\(O(n)\)
Code
// 0ms fun plusOne(d: IntArray): IntArray { for (i in d.size-1 downTo 0) if (d[i]<9) {++d[i]; return d} else d[i]=0 return IntArray(d.size+1).also {it[0]=1} }// 0ms pub fn plus_one(mut d: Vec<i32>) -> Vec<i32> { let (mut c,n) = (0,d.len()); for &d in &d {if d < 9 {c=0} else {c+=1}} if c==n { let mut r = vec![0;c+1];r[0]=1; return r} d[n-c..n].fill(0); d[n-c-1] += 1; d }
31.12.2025
1970. Last Day Where You Can Still Cross hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1221
Problem TLDR
Last day top connected to bottom in 2D matrix #hard #uf
Intuition
Invert the problem: go from back and the list becames a “rain of the ground cells”.
Approach
- we can store ground bits inside union-find jump array as an extra bit
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 68ms
val u=IntArray(21000){it*2}; fun f(a:Int):Int=if(u[a]/2==a)a else f(u[a]/2).also{u[a]=it*2+u[a]%2}
fun latestDayToCross(r: Int, c: Int, cs: Array<IntArray>) = (cs.lastIndex downTo 0).first { i ->
val (y,x)=cs[i]; val s = 1+2*f(if(y==1)0 else if(y==r)2 else y*c+x); u[y*c+x]=s
for ((x1,y1) in arrayOf(x-1 to y, x+1 to y, x to y-1, x to y+1))
if (y1 in 1..r && x1 in 1..c && u[y1*c+x1]%2>0) u[f(y1*c+x1)] = s
f(0) == f(2)
}
// 14ms
pub fn latest_day_to_cross(r: i32, c: i32, cs: Vec<Vec<i32>>) -> i32 {
let (r, c) = (r as usize, c as usize); let mut u: Vec<_> = (0..r*c+c+1).map(|i| i * 2).collect();
fn f(u: &mut Vec<usize>, a: usize)->usize{if u[a]/2==a{a}else{let t=f(u,u[a]/2);u[a]=t*2+u[a]%2;t}}
(0..cs.len()).rev().find(|&i| {
let (y, x) = (cs[i][0] as usize, cs[i][1] as usize);
let s = 1+2*f(&mut u,if y==1 {0} else if y == r {2} else {y * c + x}); u[y * c + x] = s;
for (dx, dy) in [(x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1)] {
if dy >= 1 && dy <= r && dx >= 1 && dx <= c && u[dy * c + dx] % 2 > 0
{ let r = f(&mut u, dy * c + dx); u[r] = s }}
f(&mut u, 0) == f(&mut u, 2)
}).map(|i| i as i32).unwrap_or(-1)
}
30.12.2025
840. Magic Squares In Grid medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1220
Problem TLDR
Count ‘magic’ 3x3 squares #medium
Intuition
Brute-force.
Approach
- we can enumerate each cell and translate into original matrix m[y-1][x-1] shift by y1,x1 of the magic cell
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 24ms
fun numMagicSquaresInside(g: Array<IntArray>) =
(1..<g.size-1).sumOf { y -> (1..<g[0].size-1).count { x ->
"012345678036147258048246".map { g[y-1+(it-'0')/3][x-1+(it-'0')%3] }
.run {toSet().size==9 && all{it in 1..9} && chunked(3).all{it.sum()== 15}}
}}
// 0ms
pub fn num_magic_squares_inside(g: Vec<Vec<i32>>) -> i32 {
(1..g.len()-1).map(|y|(1..g[0].len()-1).filter(|&x|{
let v=[0,1,2,3,4,5,6,7,8,0,3,6,1,4,7,2,5,8,0,4,8,2,4,6]
.map(|i| g[y-1+i/3][x-1+i%3]); let mut m=0u16;
v[..9].iter().all(|&t|0<t&&t<=9&&{m&1<<t<1&&{m|=1<<t;true}})
&& v.chunks(3).all(|c|c.iter().sum::<i32>()==15)
}).count()as i32).sum()
}
29.12.2025
756. Pyramid Transition Matrix medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1219
Problem TLDR
Can build a pyramid from transitions? #medium #backtracking
Intuition
DFS for each row. DFS with backtracking for each transition character in the row.
Approach
- speedup with arena allocation
-
speedup with Int keys: A«16 B - speedup with transitions matrix bitset: M[A][B] = bitmask
- speedup with HashSet of bad keys
Complexity
-
Time complexity: \(O(b^a)\)
-
Space complexity: \(O(b^2)\)
Code
// 15ms
fun pyramidTransition(b: String, a: List<String>): Boolean {
val m = IntArray(26 * 26); var j = b.length; val bad = HashSet<Long>()
val r = IntArray(j * (j + 1) / 2) { b[it % j] - 'A' }
for (s in a) { val x = s[0]-'A'; val y = s[1]-'A'; m[x*26+y] = m[x*26+y] or (1 shl (s[2]-'A'))}
fun dfs(st: Int, sz: Int, key: Long): Boolean {
if (j == r.size) return true; if (key in bad) return false
if (j == st + sz + 1 + sz) return dfs(j - sz, sz - 1, key)
var mask = m[r[j - sz - 1] * 26 + r[j - sz]]
while (mask > 0) {
val c = mask.countTrailingZeroBits(); mask = mask and (mask - 1); r[j++] = c
if (dfs(st, sz, key or (c.toLong() shl ((j-st-sz)*5)))) return true; --j
}
bad.add(key); return false
}
return dfs(0, j - 1, 0)
}
// 400ms
fun pyramidTransition(b: String, a: List<String>): Boolean {
val a = a.groupBy({ it.take(2) },{it[2]})
fun dfs(b: List<Char>): Boolean {
val r = ArrayList<Char>()
fun dfs2(i: Int): Boolean = if (i == b.size) dfs(r) else a["${b[i-1]}${b[i]}"]
?.any { r += it; val n = dfs2(i+1); r.removeLast(); n } == true
return b.size == 1 || dfs2(1)
}
return dfs(b.toList())
}
// 0ms
pub fn pyramid_transition(b: String, a: Vec<String>) -> bool {
let (mut m, mut j, mut bad) = ([0u32; 26 * 26], b.len(), HashSet::<u64>::new());
for s in a { let t = s.as_bytes(); m[(t[0]-b'A')as usize*26 + (t[1]-b'A')as usize] |= 1u32<<(t[2]-b'A')}
let mut r = vec![0u8; j*(j+1)/2]; for (i,&c) in b.as_bytes().iter().enumerate() {r[i] = c - b'A'}
fn dfs(m: &[u32; 26 * 26], r: &mut [u8], j: &mut usize, st: usize, sz: usize, key: u64, bad: &mut HashSet<u64>) -> bool {
if *j == r.len() { return true }; if *j == st+sz+1+sz { return dfs(m, r, j, *j-sz, sz-1, key, bad)}
if bad.contains(&key) { return false }
let mut mask = m[r[*j - sz - 1] as usize * 26 + r[*j - sz] as usize];
while mask != 0 {
let c = mask.trailing_zeros() as u8; mask &= mask - 1; r[*j] = c; *j += 1;
if dfs(m, r, j, st, sz, key | ((c as u64) << ((*j-st-sz-2)*5)), bad) { return true }; *j -= 1;
}
bad.insert(key); false
}
dfs(&m, &mut r, &mut j, 0, b.len() - 1, 0, &mut bad)
}
28.12.2025
1351. Count Negative Numbers in a Sorted Matrix easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1218
Problem TLDR
Count negatives in 2D sorted matrix #easy
Intuition
Brute force. Improve with either:
- binary search
- n+m walk on border of negatives
Approach
- use list.binarySearch {..} in Kotlin or partition_point in Rust
Complexity
-
Time complexity: \(O(nlogm)\)
-
Space complexity: \(O(nm)\)
Code
// 15ms
fun countNegatives(g: Array<IntArray>) =
g.sumOf { g[0].size+1+it.asList().binarySearch { if (it < 0) 1 else -1 } }
// 0ms
pub fn count_negatives(g: Vec<Vec<i32>>) -> i32 {
g.iter().map(|r| { (r.len() - r.partition_point(|&x| x >= 0)) as i32 }).sum()
}
27.12.2025
2402. Meeting Rooms III hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1217
Problem TLDR
Most frequent room 0..n for meetings [s,e] #hard #heap
Intuition
// 0 1 2 3 4 5 6 7 8 9 10
// * * * * * * * * * * * a
// * * * * * b
// * * * * * * b
// * * a
//
// time is complicated
//
// some corner case i didn't see
//
// 0 1 2 3 4 5 6 7 8 9 10
// * * * * * * * * * * a
// * * * * * * * * * b
// * * * * * * * * a
// * * * * * * * b
// * * * * * * a
// * * * * * b
Approach
Complexity
-
Time complexity: \(O(nmlogm)\)
-
Space complexity: \(O(n)\)
Code
// 269ms
fun mostBooked(n: Int, m: Array<IntArray>): Int {
m.sortBy { it[0] }; val f = IntArray(n); val t = LongArray(n)
for ((s,e) in m) {
val room = (0..<n).firstOrNull { t[it] <= s } ?: t.indexOf(t.min())
t[room] = 1L*e + max(0, t[room]-s)
++f[room]
}
return f.indexOf(f.max())
}
// 33ms
pub fn most_booked(n: i32, mut m: Vec<Vec<i32>>) -> i32 {
m.sort(); let (mut f, mut t, n) = ([0; 100], [0; 100], n as usize);
for m in m {
let (s, e, mut i, mut j, mut m) = (m[0] as i64, m[1] as i64, -1, -1, i64::MAX);
for r in 0..n { if t[r] <= s { j = r as i32; break }; if t[r] < m { i = r as i32; m = t[r] }}
let room = i.max(j) as usize; t[room] = e + 0.max(t[room] - s); f[room] += 1
}
(0..n).max_by_key(|&i| (f[i],Reverse(i))).unwrap() as _
}
26.12.2025
2483. Minimum Penalty for a Shop medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1216
Problem TLDR
Min close time by customers max volune #medium #counting
Intuition
Track of the customers volune running sum. YN pairs didn’t change the volume.
Approach
- ‘Y’-‘N’=11
- baseline can be anything
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 19ms
fun bestClosingTime(c: String): Int {
var v = 1337
return (0..c.length).maxBy { v += 2*(c[max(0,it-1)]-'N')/10-1; v }
}
// 0ms
pub fn best_closing_time(c: String) -> i32 {
let mut v = 404;
(0..=c.len()as i32).max_by_key(|&i|{
v += 2 * (c.as_bytes()[0.max(i-1) as usize]==b'Y')as i32-1; (v,-i)
}).unwrap()
}
25.12.2025
3075. Maximize Happiness of Selected Children medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1215
Problem TLDR
K max values, decreas each pick #medium #quickselect
Intuition
Sort and pick K largest.
Approach
- optimize with quickselect
- we still have to sort K items to check 0 overflow
Complexity
-
Time complexity: \(O(n + klog(k))\), for optimal; the simplest is O(nlogn)
-
Space complexity: \(O(1)\)
Code
// 693ms
fun maximumHappinessSum(h: IntArray, k: Int) =
h.sortedDescending().take(k).withIndex().sumOf {(i,h)->max(0,1L*h-i)}
// 12ms
pub fn maximum_happiness_sum(mut h: Vec<i32>, k: i32) -> i64 {
h.sort_unstable_by(|a,b|b.cmp(a));
h.iter().zip(0..k).map(|(h,i)|0.max(h-i)as i64).sum()
}
// 18ms
pub fn maximum_happiness_sum(mut h: Vec<i32>, k: i32) -> i64 {
let (l,m,_) = h.select_nth_unstable_by_key(k as usize-1, |h|-h);
l.sort_unstable_by(|a,b|b.cmp(a));
l.iter().chain(once(&*m)).zip(0..).map(|(h,i)|0.max(h-i)as i64).sum()
}
24.12.2025
3074. Apple Redistribution into Boxes easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1214
Problem TLDR
Min containers for all apples #easy #counting_sort
Intuition
Sum all apples. Take largest containers first.
Approach
- (1..51).first for number of containers
- sort by counting
Complexity
-
Time complexity: \(O(sort)\), the sort can be NlogN or N for counting
-
Space complexity: \(O(sort)\), Kotlin’s IntArray.sort is O(1) space complexity
Code
// 29ms
fun minimumBoxes(a: IntArray, c: IntArray) =
(1..c.size).first { a.sum() <= c.sortedDescending().take(it).sum() }
// 0ms
pub fn minimum_boxes(a: Vec<i32>, c: Vec<i32>) -> i32 {
let mut s = a.iter().sum::<i32>(); let mut f = [0;51];
for c in c { f[c as usize] += 1 }; let mut j = 50;
(1..51).find(|i| { while f[j] < 1 { j-=1 }; s -= j as i32; f[j] -= 1; s <= 0}).unwrap() as _
}
23.12.2025
2054. Two Best Non-Overlapping Events medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1213
Problem TLDR
Max at most two non-overlapping events #medium #prefix_max #bs #pq
Intuition
// ************
// *****
// *****
// *****
// *****
// *****
// .*****
// . *****
//
// need a way to map[time][maxv]
- One way: sort by starts, put visited into PriorityQueue, poll by ends
- Another way: sort by ends, put visited into prefix-max list, binary search start in ends
Approach
- the prefix-max requires initial (0,0) value
- there is also a suffix-max solution
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(n)\)
Code
// 135ms
fun maxTwoEvents(e: Array<IntArray>): Int {
var max = 0; val q = PriorityQueue<Int>(compareBy{e[it][1]})
return e.indices.sortedBy { e[it][0]}.maxOf { i ->
while (q.size > 0 && e[q.first()][1] < e[i][0])
max = max(max, e[q.poll()][2])
q += i; e[i][2] + max
}
}
// 10ms
pub fn max_two_events(mut e: Vec<Vec<i32>>) -> i32 {
let mut max = vec![(0,0)]; e.sort_unstable_by_key(|e|e[1]);
e.iter().map(|e|{
max.push((max[max.len()-1].0.max(e[2]), e[1]));
e[2] + max[max.partition_point(|m| m.1 < e[0]) - 1].0
}).max().unwrap()
}
22.12.2025
960. Delete Columns to Make Sorted III hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1212
Problem TLDR
Remove columns to sort strings #hard #dp
Intuition
// a b c
// c b c
// c a b
//
// i think just removing column greedily is not optimal
//
// a b c d e a
// e a b c d e
// **..*** we have sorted and usorted parts
// *.**... they can overlap
// abxycde find minimum to remove to make sorted? LIS?
// acceptance rate is 67% am i overthinking it?
//
// maybe it is dp, the tail should be all sorted
// 28minute; look at hints; ok it is a LIS and is a DP
Top down dp: take i or skip it, compare with previous j.
Approach
- 1-D dp, build longest substring: lookup prefixes to increase the length dp[j]+1
- 1-D dp, minimum removals: lookup prefixes to find min removals dp[j]+i-j-1 (more tricky with initial conditions)
Complexity
-
Time complexity: \(O(n^3)\)
-
Space complexity: \(O(n^2)\) or n^2 optimized
Code
// 20ms
fun minDeletionSize(s: Array<String>): Int {
val d = HashMap<Int, Int>()
fun dfs(i: Int, j: Int): Int = if (i == s[0].length) 0 else d.getOrPut(i*100+j) {
val skip = 1 + dfs(i + 1, j)
val take = if (j < 0 || s.all {it[j] <= it[i]}) dfs(i+1,i) else 100
min(skip, take)
}
return dfs(0, -1)
}
// 1ms
pub fn min_deletion_size(s: Vec<String>) -> i32 {
let m = s[0].len(); let mut d: Vec<_> = (0..m+2).collect();
for i in 2..m+2 { for j in 1..i {
if i > m || s.iter().all(|r| r[j-1..=j-1] <= r[i-1..=i-1]) {
d[i] = d[i].min(d[j] + i - j - 1);
}}} d[m+1] as i32 -1
}
21.12.2025
955. Delete Columns to Make Sorted II medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1211
Problem TLDR
Remove columns to sort strings #medium
Intuition
The brute-force works. Build the strings column by column and either accept the current column or not.
Approach
- optimization: keep only rows that have equal chars
Complexity
-
Time complexity: \(O(n^3)\) or n^2 optimized
-
Space complexity: \(O(n^2)\) or n oprimized
Code
// 32ms
fun minDeletionSize(s: Array<String>): Int {
var res = List(s.size) { "" }
return s[0].indices.count { i ->
val r = res.zip(s).map { (a,b) -> a + b[i] }
(1..<s.size).any { r[it-1] > r[it] }.also { if (!it) res = r }
}
}
// 0ms
pub fn min_deletion_size(s: Vec<String>) -> i32 {
let mut js: Vec<_> = (1..s.len()).collect();
(0..s[0].len()).filter(|&i| {
let rm = js.iter().any(|&j| s[j-1].as_bytes()[i] > s[j].as_bytes()[i]);
if !rm { js.retain(|&j| s[j-1].as_bytes()[i] == s[j].as_bytes()[i]) }; rm
}).count() as _
}
20.12.2025
944. Delete Columns to Make Sorted easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1210
Problem TLDR
Count unsorted columns #easy
Intuition
Compare column with its sorted variant.
Approach
- or compare adjucent rows in a column
Complexity
-
Time complexity: \(O(nm)\) or nmlogn
-
Space complexity: \(O(n)\) or O(1)
Code
// 84ms
fun minDeletionSize(s: Array<String>) =
s[0].indices.map{i -> s.map{it[i]}}.count { it != it.sorted() }
// 1ms
pub fn min_deletion_size(s: Vec<String>) -> i32 {
(0..s[0].len()).filter(|&i| (1..s.len()).any(|j| s[j-1].as_bytes()[i]>s[j].as_bytes()[i])).count() as _
19.12.2025
2092. Find All People With Secret hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1209
Problem TLDR
Time based secret spread in a graph #hard #uf
Intuition
Union-Find works, but naive gives TLE. Use path compression.
Approach
- to disconnect nodes collect them by time groups, then short-circuit uf[x]=x
- or collect mini-graphs by time and walk DFS from connected to 0
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 145ms
fun findAllPeople(n: Int, m: Array<IntArray>, f: Int): List<Int> {
m.sortBy { it[2] }; val u = HashMap<Int, Int>(); u[f] = 0
fun f(x: Int): Int = u[x]?.let { if (it==x) x else f(it).also { u[x] = it }} ?: x
val curr = ArrayList<Int>(); var prev = 0
for ((x,y,t) in m) {
if (t > prev) for (x in curr) if (f(x) != f(0)) u[x] = x
if (t > prev) curr.clear()
u[f(x)] = f(y); curr += x; curr += y; prev = t
}
return (0..<n).filter { f(it) == f(0) }
}
// 20ms
pub fn find_all_people(n: i32, mut m: Vec<Vec<i32>>, fst: i32) -> Vec<i32> {
m.sort_unstable_by_key(|v| v[2]); let mut u: Vec<_> = (0..n as usize).collect();
let mut c = vec![]; let mut p = 0; u[fst as usize] = 0;
fn f(u: &mut [usize], x: usize) -> usize { if x != u[x] { u[x] = f(u, u[x])} u[x]}
for v in m {
let (x, y, t) = (v[0] as usize, v[1] as usize, v[2]);
if t > p { for &x in &c { if f(&mut u, x) != f(&mut u, 0) { u[x] = x }}; c.clear() }
let rx = f(&mut u, x); u[rx] = f(&mut u, y); c.extend([x,y]); p = t
}
(0..n).filter(|&i| f(&mut u, i as usize) == f(&mut u, 0)).collect()
}
18.12.2025
3652. Best Time to Buy and Sell Stock using Strategy medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1208
Problem TLDR
Max Profit by modifying a sliding window sum #medum
Intuition
Use two separate sliding window sums.
The total max profit is sum + (modified window - original window)`
// 0 1 2 i
// 4 2 8
//-1 0 1 k=2
// i
// 9 2 9 5
//-1 0 1 1 k=4
// i
Approach
- use a single variable to hold sliding window sum
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 22ms
fun maxProfit(p: IntArray, st: IntArray, k: Int): Long {
var sm = 0L; var so = 0L; var diff = 0L
return p.indices.sumOf { i ->
sm += p[i] - if (i-k/2 >= 0) p[i-k/2] else 0
so += st[i] * p[i] - if (i-k >= 0) st[i-k] * p[i-k] else 0
if (i+1-k >= 0) diff = max(diff, sm - so)
1L * st[i] * p[i]
} + diff
}
// 0ms
pub fn max_profit(pr: Vec<i32>, st: Vec<i32>, k: i32) -> i64 {
let (mut sm, mut so, mut diff, k) = (0,0,0,k as usize);
pr.iter().zip(&st).enumerate().map(|(i, (&p, &s))|{
sm += (p - if i >= k/2 { pr[i-k/2] } else { 0 }) as i64;
so += (s*p - if i >= k { st[i-k] * pr[i-k] } else { 0 }) as i64;
if i + 1 >= k { diff = diff.max(sm - so) }
(s * p) as i64
}).sum::<i64>() + diff
}
17.12.2025
3573. Best Time to Buy and Sell Stock V medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1207
Problem TLDR
K best deals buy/short/sell stocks #medium #dp
Intuition
- the O(n^3) is accepted in Kotlin, dp state is (i,k) and inner loop to close the deal
- optimized version: use (i,k,s) as a state, s=0 -free, s=1 - bought, s=1 - short the stoks
Approach
- write DFS, then rewrite to iterative version
- then we can space optimize if necessary
Complexity
-
Time complexity: \(O(n^2)\), or O(n^3) with inner search
-
Space complexity: \(O(n^2)\)
Code
// 3791ms
fun maximumProfit(p: IntArray, k: Int): Long {
val dp = Array(p.size) { LongArray(p.size)}
fun dfs(i: Int, k: Int): Long = if (i==p.size || k==0)0L else
dp[i][k].takeIf { it > 0}?:{
val skip = dfs(i+1, k)
val start = (i+1..<p.size).maxOfOrNull { j -> abs(p[i]-p[j]) + dfs(j+1, k-1) }?:0L
dp[i][k] = max(start, skip); dp[i][k]
}()
return dfs(0,k)
}
// 61ms
pub fn maximum_profit(p: Vec<i32>, k: i32) -> i64 {
let n = p.len(); let k = k as usize;
let mut dp = vec![vec![vec![0i64; n+1]; k+1]; 3];
for i in (0..=n).rev() { for kk in 0..=k { for s in -1..=1 {
let idx = (s + 1) as usize;
dp[idx][kk][i] = if i == n || kk == 0 { 0 } else {
let skip = dp[idx][kk][i+1];
if s == 0 {
let buy = dp[2][kk][i+1] - p[i] as i64;
let sell = dp[0][kk][i+1] + p[i] as i64;
if i == n - 1 { skip } else { buy.max(sell).max(skip) }
} else {
let close = dp[1][kk-1][i+1] + (s * p[i] as i64);
if i == n - 1 { close } else { close.max(skip) }
}
}}}} dp[1][k][0]
}
16.12.2025
3562. Maximum Profit from Trading Stocks with Discounts hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1206
Problem TLDR
Max profit in a tree #hard
Intuition
// can't understand the description
// is the 'stock' a single or many?
// where are the stocks?
// why example 1 can buy by both
// and example 2 can not?
//
// why example two:
// boss: buy at 3 sell at 5: 5-3=2
// employee: buy at (4/2) sell at 8: 8-2=6
// profit: 6+2=8, budget (2+3) - ok, its out of budget=4
// ok, have some understanding: example 2 is out of budget
//
// so we have to pick either buy as a boss
// or buy as a subordinate
//
// it can be: dp + graph DFS
//
// ok but how to spread budget between children?
//
// interesting that the prices are so low 1..50
//
// 30 minute, look for hints; the main difficulty is how to pick the best children and how many?
// still the question: how to account to budget?
//
// just picking a single child is not working
//
// put children in a PriorityQueue by profit and update the tree?
//
// ok we have only 160 nodes; it is 2^160 ways of take/not take
//
// ok i kind of solved it, TLE is from kotlin slowness and usage of a HashMap
Approach
Complexity
-
Time complexity: \(O(n^2b^2)\)
-
Space complexity: \(O(n^2b^2)\)
Code
// 2822ms
fun maxProfit(n: Int, p: IntArray, f: IntArray, h: Array<IntArray>, b: Int): Int {
val ch = Array(n) { ArrayList<Int>() }; for ((p,c) in h) ch[p-1] += c-1
val dp = HashMap<Int, Int>(); val d = HashMap<Int, Int>()
fun dfs(i: Int, half: Int, budget: Int): Int =
dp.getOrPut(i * 10000000 + half*10000 + budget) {
fun maxp(j: Int, hf: Int, bgt: Int): Int = if (j == ch[i].size) 0 else
d.getOrPut(i * 100000000 + j * 100000 + hf*1000 + bgt) {
(0..bgt).maxOf { takeB -> dfs(ch[i][j], hf, takeB) + maxp(j+1, hf, bgt-takeB) }
}
val p1 = maxp(0, 0, budget); val spend = if (half==0) p[i] else p[i]/2
if (spend > budget) p1 else max(f[i] - spend + maxp(0, 1, budget-spend), p1)
}
return dfs(0, 0, b)
}
15.12.2025
2110. Number of Smooth Descent Periods of a Stock medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1205
Problem TLDR
Decreasing subarrays #medium
Intuition
Just count them like and arithmetic progression.
Approach
- res += count++
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 40ms
fun getDescentPeriods(p: IntArray) =
p.indices.fold(0 to 0L) { (cnt, res), i ->
val c = 1 + if (i > 0 && p[i] == p[i-1] - 1) cnt else 0
c to (res + c)
}.second
// 0ms
pub fn get_descent_periods(p: Vec<i32>) -> i64 {
(0..p.len()).fold((0,0), |(cnt,res), i| {
let c = 1 + if i > 0 && p[i] == p[i-1]-1 { cnt } else { 0 };
(c, res + c)
}).1
}
14.12.2025
2147. Number of Ways to Divide a Long Corridor hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1204
Problem TLDR
Ways to split pairs of S #hard
Intuition
// p p s p p s p p
Chunk by pairs of ‘s’, multiply counts of in-between ‘p’.
Approach
- or, rearrange the problem and add the accumulated value on each new ‘p’
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 34ms
fun numberOfWays(c: String): Int {
var a = 0; var b = 1; var s = 1
for (c in c) if (c == 'P') b = (a * (s%2) + b) % 1000000007
else if (++s%2>0) a = b
return a * (s%2)
}
// 3ms
pub fn number_of_ways(c: String) -> i32 {
let (mut a, mut b, mut even) = (0, 1, true);
for c in c.as_bytes().chunk_by(|x, y| x == y) {
if c[0] == b'P' {
if even && a > 0 { b = (b + c.len()* a) % 1_000_000_007 }
} else {
if !even || c.len() > 1 { a = b }
if c.len() & 1 > 0 { even = !even }
}
} even as i32 * a as i32
}
13.12.2025
3606. Coupon Code Validator easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1203
Problem TLDR
Filter a,b,c accroding to rules #easy
Intuition
Just read the rules.
Approach
- some rules can be hacked around
- the regex in koglin faster than in rust
Complexity
-
Time complexity: \(O(nlog(n))\)
-
Space complexity: \(O(n)\)
Code
// 57ms
fun validateCoupons(c: Array<String>, b: Array<String>, a: BooleanArray) =
c.indices.filter { a[it] && Regex("\\w+") matches c[it] && b[it][0] in "egpr" }
.sortedBy { b[it][0] + c[it] }.map { c[it] }
// 0ms
pub fn validate_coupons(c: Vec<String>, b: Vec<String>, a: Vec<bool>) -> Vec<String> {
b.iter().map(|b|b.as_bytes()[0]).zip(c).zip(a).filter(|((b,c),a)|
*a && b"egrp".contains(b) && c != "" && c.chars().all(|c|c.is_alphanumeric() || c == '_'))
.sorted().map(|((_,c),_)|c).collect()
}
12.12.2025
3433. Count Mentions Per User medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1201
Problem TLDR
Count messages and track online users #medium #simulation
Intuition
The problem is not that big. Sort by timestamp and put queries after offline modifications.
Approach
- use queue of coming online or just array of coming online times for all users
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n)\)
Code
// 61ms
fun countMentions(n: Int, e: List<List<String>>): IntArray {
val r = IntArray(n); val on = IntArray(n)
for ((type, ts, ids) in e.sortedBy { it[1].toInt()*100-it[0][0].toInt() })
if (type[0] == 'O') on[ids.toInt()] = ts.toInt() + 60
else if (ids[0] == 'A') for (i in 0..<n) ++r[i]
else if (ids[0] == 'i') for (i in ids.split(" ")) ++r[i.drop(2).toInt()]
else for (i in 0..<n) if (on[i]<=ts.toInt()) ++r[i]
return r
}
// 0ms
pub fn count_mentions(n: i32, mut e: Vec<Vec<String>>) -> Vec<i32> {
let n = n as usize; let (mut r, mut o) = (vec![0; n], vec![0; n]);
e.sort_unstable_by_key(|v| v[1].parse::<i32>().unwrap()*100-v[0].as_bytes()[0] as i32);
for v in &e {
let (tp, ts) = (v[0].as_bytes()[0], v[1].parse::<i32>().unwrap());
if tp == b'O' { o[v[2].parse::<usize>().unwrap()] = ts + 60 }
else if v[2].as_bytes()[0] == b'A' { for i in &mut r { *i += 1 }}
else if v[2].as_bytes()[0] == b'i' { for i in v[2].split(" ") { r[i[2..].parse::<usize>().unwrap()] += 1 }}
else { for i in 0..n { if o[i] <= ts { r[i] += 1 }}}
} r
}
11.12.2025
3531. Count Covered Buildings medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1200
Problem TLDR
Count surrounded dots on XY plane #medium
Intuition
// idea line sweep Y then X, collect in-betweens, intersect them
Line sweep: collect lines, sort each line, drop first and last, intersect with orthogonal sweep.
Approach
- optimization: instead of collecting, just look max and min on each line.
Complexity
-
Time complexity: \(O(nlog(n))\), or O(n) for min-max
-
Space complexity: \(O(n)\)
Code
// 463ms
fun countCoveredBuildings(n: Int, b: Array<IntArray>) =
listOf(b.indices.groupBy { b[it][0] }.values.map { it.sortedBy { b[it][1] }},
b.indices.groupBy { b[it][1] }.values.map { it.sortedBy { b[it][0] }})
.map { it.fold(HashSet<Int>()) { r, t -> r += t.drop(1).dropLast(1); r }}
.reduce(Set<Int>::intersect).size
// 17ms
pub fn count_covered_buildings(n: i32, b: Vec<Vec<i32>>) -> i32 {
let (mut minY, mut maxY) = (vec![100000; n as usize+1], vec![0; n as usize+1]);
let (mut minX, mut maxX) = (minY.clone(), maxY.clone());
for b in &b { let (x,y) = (b[0] as usize, b[1] as usize);
minY[x] = minY[x].min(y); maxY[x] = maxY[x].max(y);
minX[y] = minX[y].min(x); maxX[y] = maxX[y].max(x);
}
b.iter().filter(|&b| { let (x,y) = (b[0] as usize, b[1] as usize);
minX[y] < x && x < maxX[y] && minY[x] < y && y < maxY[x] }).count() as _
}
10.12.2025
3577. Count the Number of Computer Unlocking Permutations medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1199
Problem TLDR
Permutations to unlock all c[j] right and bigger than c[i] #medium #combinatorics
Intuition
// 123456
// 1 then take all values bigger as second position
// 1 p[23456]
// 12 p[3456]
// 13 p[2456], the number is n!
// what if we have duplicates?
// 1223456
// we are not allowed to sort
// 1654223
// 1 [654223] but every number can be at any place
// so it doesnt matter
// so it is (n-1)!
// how to calc factorial of 10^5?
//
//
- first should be the smallest
- other numbers doesn’t matter
Approach
- use longs
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 9ms
fun countPermutations(c: IntArray) = (1..<c.size)
.fold(1L) { r, t -> if (c[t] > c[0]) (r*t) % 1000000007 else 0 }
// 0ms
pub fn count_permutations(c: Vec<i32>) -> i32 {
(1..c.len()).fold(1, |r,t|
if c[t] > c[0] {(r*t)%1000000007} else { 0 })as _
}
09.12.2025
3583. Count Special Triplets medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1198
Problem TLDR
Count a[i]==a[j]*2==a[k] #medium #prefix_sum
Intuition
// 8 4 2 8 4
// * look for all 8 left and right
//
Count total frequency F. Count frequency so-far L. Add for each middle: L * (F - L)
Approach
- or a single pass solution from lee: count frequency so-far F, count pairs (2x,x) so-far C+=F[x], add each C[x/2]
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 176ms
fun specialTriplets(n: IntArray) = {
val f = LongArray(200002); val c = f.clone()
n.sumOf { x -> val r = 1L*c[x/2]*(1 - x%2); c[x] += f[x*2]; f[x]++; r }
}() % 1000000007
// 36ms
pub fn special_triplets(n: Vec<i32>) -> i32 {
let mut f = [0i32; 200002]; let mut c = f.clone();
n.iter().fold(0, |r, &x|{ let x = x as usize;
let rx = c[x>>1] * ((x&1)^1)as i32;
c[x] = (c[x] + f[x<<1])%1000000007;
f[x] += 1; (r + rx)%1000000007
})
}
08.12.2025
1925. Count Square Sum Triples easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1197
Problem TLDR
Count a^2+b^2=c^2 in 1..n range #easy
Intuition
O(n^3) is accepted O(n^2): precompute n^2 numbers, lookup (a+b) in them
Approach
- we have to be in range 1..n, not in 1..250
- or check sqrt(aa+bb)
Complexity
-
Time complexity: \(O(n^3)\) or O(n^2)
-
Space complexity: \(O(n)\)
Code
// 49ms
fun countTriples(n: Int): Int {
val s = (1..n).map { it * it }.toSet()
return s.sumOf { a-> s.count { b-> (a+b) in s}}
}
// 5ms
pub fn count_triples(n: i32) -> i32 {
(1..=n).map(|a| 2*(a..=n).filter(|b| {
let c = (a*a+b*b).isqrt(); c <= n && c*c==a*a+b*b}).count() as i32).sum::<i32>()
}
07.12.2025
1523. Count Odd Numbers in an Interval Range easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1196
Problem TLDR
Odds l..h #easy
Intuition
Look at total numbers count d:
- even d - just divide by 2
- odd d - divide by 2 plus look at first number if it is odd
// 1 2 2-1+1=2, l=o, h = e, 2/2
// 1 2 3 4 4, l=o h=e 4/2
// 1 2 3 3 l=o h=o 1+3/2
// 2 3 2 l=e 2/2
// 2 3 4 5 4 l=e 4/2
// 3 4 5 3 l=o 1+3/2
// 2 3 4 3 l=e 3/2
// 3 4 5 6 4 l=o 4/2
Approach
- or brillian lee compression of this logic: (h+1)/2-l/2
Complexity
-
Time complexity: \(O(1)\)
-
Space complexity: \(O(1)\)
Code
// 76ms
fun countOdds(l: Int, h: Int) =
(h-l+1)/2 + (l%2)*((h-l+1)%2)
// 0ms
pub fn count_odds(l: i32, h: i32) -> i32 {
(h+1)/2 - l/2
}
06.12.2025
3578. Count Partitions With Max-Min Difference at Most K medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1195
Problem TLDR
Ways to partition into parts (max-min) at most k #medium #dp #monotonic_queue
Intuition
Didn’t solve.
// at most means 0..k
// so for each position i
// look for all possible positions j
// abs(n[j]-n[i]) at most k
// or it is every position j..i
// and move j if n[j] is not in n[i]-k..n[i]+k
//
// corner case 3 3 4 k=0/1
// completely wrong solution
//
// 4 1 3 7
// j i
// j i when i goes to 7 it is out of bounds with 1
// but j stays at 4 and is ok
//
// from '1' look at ..0 and 5.. left and right
// let's only look left
// 9 4 1 3 7 k=4 TreeMap lookup? have to check all ranges 5+,0-
// i 1
// * i 2 1*2=2
// * * i 3 1*3
// * i 2 2*3
//
// 24 minute lets' look for hints, ok its dp
// f(9 4 1 3) = f(9)*f(4 1 3)
// 1 2 3 4 5 6 k=2
// * * *
// * * *
// * * *
// * * * 24=6x4 * * * = 6 = 3*4/2
// 32 minute hint 2&3, so the second trick is running min/max
// this is a hard problemm
// 1 hour mark
// my algo correclty detects j
// but i don't know how to count ways, tests are not passing
// look for solutions
// from lee solution, its not just about detecting j position
// we should track accumulated values
// and subtract them while we moving j
- i is the end of the window
- j is the left position, such that max - min at most k
- dp[i] = dp[j] + dp[j+1] + dp[j+2] + … + dp[i-1]
- use prefix sum of dp to calculate sum(dp[j..i])
- use decreasing queue to find max
- use increasing queue to find min
- pop both queues together while moving j
Approach
- this problem is hard
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 105ms
fun countPartitions(n: IntArray, k: Int): Int {
val dp = IntArray(n.size+1); dp[0] = 1; val M = 1000000007
val ps = IntArray(n.size+1); ps[0] = 1; var j = 0
val qmax = ArrayDeque<Int>(); val qmin = ArrayDeque<Int>()
for (i in n.indices) {
while (qmax.size > 0 && n[qmax.last()] < n[i]) qmax.removeLast()
while (qmin.size > 0 && n[qmin.last()] > n[i]) qmin.removeLast()
qmax += i; qmin += i
while (n[qmax.first()]-n[qmin.first()] > k) {
if (qmax.first() < ++j) qmax.removeFirst()
if (qmin.first() < j) qmin.removeFirst()
}
dp[i+1] = (M + ps[i] - if (j > 0) ps[j-1] else 0) % M
ps[i+1] = (ps[i] + dp[i + 1]) % M
}
return dp[n.size]
}
05.12.2025
3432. Count Partitions with Even Sum Difference easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1194
Problem TLDR
Count Left sum - Right sum % 2 #easy
Intuition
Just brute-force.
Approach
- a more interesting solution: A-B %2 == 0 only if both odd or both even.
- step i+0, […….even_sum][……….even_sum]
- step i+1, […….even_sum,odd][……….even_sum-odd]
- step i+1, […….even_sum,even][……….even_sum-even]
- basically, the even-ness will be the same for every partition
- same proof for odd-ness
Complexity
-
Time complexity: \(O(n^2)\), or O(n) for clever solution
-
Space complexity: \(O(1)\)
Code
// 11ms
fun countPartitions(n: IntArray) =
(n.size-1)* (1-n.sum()%2)
// 0ms
pub fn count_partitions(n: Vec<i32>) -> i32 {
(n.len()as i32-1)*(1-n.iter().sum::<i32>()%2)
}
04.12.2025
2211. Count Collisions on a Road medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1193
Problem TLDR
Collisions R vs L #medium
Intuition
Do separate pass for R, then backwards pass for L. Drop counter every time opposite meets.
Approach
- notice, only the prefix L and suffix R are excluded.
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\), can be O(1)
Code
// 42ms
fun countCollisions(d: String) =
d.trimStart('L').trimEnd('R').count { it != 'S' }
// 0ms
pub fn count_collisions(d: String) -> i32 {
d.trim_start_matches('L').trim_end_matches('R').bytes()
.filter(|&b| b != b'S').count() as _
}
03.12.2025
3625. Count Number of Trapezoids II hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1192
Problem TLDR
Count trapezoids from points #hard #geometry
Intuition
// i really don't like this problem
//
// line y = (dy/dx)x + b
// y*(x2-x1) = x*(y2-y1)
//
// how to track parallel lines?
// we have only 500 points, can be O(n^2)
//
// for each point pair: count same slope others
//
// the key should be the line, not the slope
//
// (y-y0)= (x-x0)*(y2-y1)/(x2-x1), slope + point of intersection of x and y coordinates
// line intersect X coordinate at x = x0, y = 0, Y coordinate at y0
//
// i don't have a time to remember geometry
//
// how to check y-intercept?; y = kx+b; b = y -kx
//
// ok the double is not precise enough, have false positive match
// -24,-89 42,11 and -75,-89 -9,11 (or maybe it is symmetrical)
//
// let's go for answer, feels pointless, how to use gcd here?
-
key slopes by normalized dy/gcd(dx,dy) dx/gcd(dx,dy) -
key parallelogram by equal distances between points (they are pairly-equal for parallelogram) dy dx - then count subprolem with points on parallel lines: sum+count, res += sum*count
Approach
- parallelogram’s keyed points gives exactly 2x for parallelograms and 1x otherwise, so /2 would gives only duplicates
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n^2)\)
Code
// 578ms
fun countTrapezoids(p: Array<IntArray>): Int {
val m = HashMap<Int, HashMap<Int, Int>>(); val d = m.toMutableMap()
fun gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b)
for (i in p.indices) for (j in i+1..<p.size) {
val (x1,y1) = p[i]; val (x2,y2) = p[j]; var dx = x2-x1; var dy = y2-y1
if (dx < 0 || dx == 0 && dy < 0) { dx = -dx; dy = -dy }
val g = gcd(dx, dy); val sx = dx / g; val sy = dy / g; val line = sx*y1-sy*x1
val slope = (sx shl 12) or (sy+2000); val dist = (dx shl 12) or (dy+2000)
m.getOrPut(slope) { HashMap() }.merge(line, 1, Int::plus)
d.getOrPut(dist) { HashMap() }.merge(line, 1, Int::plus)
}
fun cnt(m: Map<Int, Map<Int, Int>>): Int = m.values.sumOf {
it.values.fold(0 to 0) { (sum, r), t -> (sum + t) to (r + sum*t)}.second }
return cnt(m) - cnt(d)/2
}
02.12.2025
3623. Count Number of Trapezoids I medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1191
Problem TLDR
Trapezoids count #medium
Intuition
// * * 2
// * * * 3 2,3= 3
// * * 2 2,2=1 + 2,3=3 = 4
// * 1 skip
// * * * * 4 2,4=6 + 3,4=(6+6+6)=18 + 2,4=6 = 6*5=30
// * * * * 4 prev(30)+f(4,4)
// * * * 3 2*(3,2) + 3,3 + 2*(3,4)
// 1 - 0
// 2 - 1
// 3 - 3
// 4 - 6
// 5 - 4+3+2+1=10 5*(5-1)/2 * * * * *
// TLE? - yes, this is O(N^2), previous are too many
// 35 minute, look for hints: they propose n^2 algo, there are too many groups
// ugly math trick to solve this
Approach
- group by level Y
- each level count adds as c*(c-1)/2
- use previous levels sum
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 81ms
fun countTrapezoids(p: Array<IntArray>) =
p.groupingBy {it[1]}.eachCount().values.fold(0L to 0L){ (res,sum),c ->
val ways = 1L*c*(c-1)/2; res + ways*sum to ways+sum }.first % 1000000007
// 63ms
pub fn count_trapezoids(p: Vec<Vec<i32>>) -> i32 {
(p.iter().map(|v| v[1]).counts().values().fold((0,0), |(r,s),&c|{
let w = (c*(c-1)/2); (r+w*s,w+s) }).0 % 1000000007) as _
}
01.12.2025
2141. Maximum Running Time of N Computers hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1190
Problem TLDR
Max time to run n computers with batteries #hard #bs
Intuition
// n=3 b=[3,3,3] t= 3
// n=3 b=[3,3,3,3] t= 3
// 2 2 2 3
// 1 1 2
// 1 0 1
// 0 0 0 t=4
// b= 1 2 3 4 5 6 n=3
// 0 1 2
// 0 1 3
// 0 2 4
// 1 3 5
// 0 2 4 non optimal, left 6 which is 2*n
//
// 3 4 5
// 2 3 4
// 1 2 3
// 0 1 2
// 0 1 2
// 0 1 0 1+2 left, non optimal, 1+2=n
//
// 0 4 5
// 1 3 4
// 0 3 3
// 2 2 2
// 1 1 2
// 1 0 1
// 0 0 0 7 optimal, left is 0
// so the algo: take all bigger and one small
// does this always work?
//
// n=2 1 40 40 just take biggest
// ok looks like algo is not obvious, is it binary search?
//
// we have time, answer question can run?
// true true true | false false false
//
// now, given the time how to consume it?
//
// 1 2 3 4 5 6 n=3 time=7 sum=21;
// any minute we burn 3 points
// total = 7*3 = 21
// time=8 total < sum
// 3 3 3 n=2 time=5; sum=9 total=2*5=10
// time=4 total=2*4=8
//
// corner cases
// 1 1 10 n=2 sum=12 maxtime=6
// 2 2 10 n=2 sum=14
// let t = 4, 4*2 = 8
// 2+2+4 = 8
//
// 1 40 40 n=2, let t=40, 2*40=80
//
// 30minute, look for hint: already knew;
// the actual hardness is how to determine if can run
With given time answer canRun n computers.
Total required energy is t*n.
Each battery can’t give more than it have or more than t (it can’t be alone used in parallel).
Approach
- another intuition is: average
sum/n, take max while it is bigger than average (they are not relevant to detection of max time); the leftoversum/nis the answer
Complexity
-
Time complexity: \(O(nlog(n))\)
-
Space complexity: \(O(1)\)
Code
// 13ms
fun maxRunTime(n: Int, b: IntArray): Long {
var lo = 0L; var hi = Long.MAX_VALUE/n
while (lo <= hi) {
val t = lo + (hi - lo) / 2
if (t*n <= b.sumOf { min(1L*it, t) }) lo = t + 1 else hi = t - 1
}
return hi
}
// 14ms
pub fn max_run_time(n: i32, b: Vec<i32>) -> i64 {
let (mut lo, mut hi) = (0, i64::MAX / n as i64);
while lo <= hi {
let t = lo + (hi - lo) / 2;
if t * n as i64 <= b.iter().map(|&x|t.min(x as i64)).sum::<i64>()
{ lo = t + 1 } else { hi = t - 1 }
}; hi
}
30.11.2025
1590. Make Sum Divisible by P medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1189
Problem TLDR
Min removal to make sum%p #medium #hashmap
Intuition
// 3 1 4 2 sum=10 p=6
// idea: prefix sums
// 3 4 8 10
// idea: all subarrays ending at position
// 3 1 4 2
// * 1, 3+1=4
// sum = remove + stay, where stay % p == 0
// stay_a .. remove .. stay_b
// stay_a + stay_b % p == 0
// (prefix_sum + suffix_sum) % p == 0
// and we want them as big as possible
//
// 3 1 4 2
// i j 3+2
// i j 3+1+2=6
// or
// i j 3+4+2=9 we don't know which pointer to move
// is this dp?
//
// idea: invert the problem
// subarray should be divisible by %(sum%p)
// check
// 6 3 5 2 p=9 sum=16, 16%9=7, subarray %7
// [..]
// ok seems works; how can we find it?
// prefix sum
//
// 6 9 14 16
// reminder to position
// 6 2 0 2
// i 6-0, 2-1, 0-2, currSum=16, currRem=2 (lookup last pos of 2)
//
// check
// 3 1 4 2 sum=10, p=6, sum%p = 4
// 3 4 8 10
// 3 0 0 2
// i len=2
// i len=1
//
// ok failed on 4 4 2 p=7
//
// 4 4 2
// 4 8 10 k=10%7=3
// 1 2 1 looks like it completely not working; we want to find %3 subarray
// so, 4 2 is %3 but the leftover 4 is not %7, looks like wrong intuition
// maybe we want to find at most 3, 10-7=3
// another fail
// 3 6 8 1 p=8 sum=18 k=18%8=2
// 31 minute
// 1 1 1 0 remove 6 because it is %2, looks like a wrong idea
//
// 34 minute go for hints: same ideas as mine, but put s%p instead of s%k in map
// looks like i overcomplicated and got lost
// 3 1 4 2 p=6
// 3 4 2 4
//
// 6 3 5 2 p=9 k=7
// 6 2 0 2
//
// so the wrong part is that k should match exactly, not by %k
(pref_i - pref_j) % p = k pref_j %p = pref_i % p - k
Approach
- store and lookup pref % p
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 55ms
fun minSubarray(n: IntArray, p: Int): Int {
val m = HashMap<Int, Int>(); m[0] = -1; var s = 0
val k = n.fold(0) {r,t->(r+t)%p}
return if (k == 0) 0 else n.indices.minOf { i ->
s = (s + n[i])%p; val j = m[(s-k+p)%p]; m[s] = i
i - (j?:-n.size)
}.takeIf { it < n.size } ?: -1
}
// 15ms
pub fn min_subarray(n: Vec<i32>, p: i32) -> i32 {
let k = n.iter().fold(0, |r, &t| (r + t) % p); if k < 1 { return 0 }
let (mut m, mut s) = (HashMap::from([(0,-1)]), 0);
n.iter().enumerate().map(|(i, &x)| { s = (s + x) % p;
let d = m.get(&((s-k+p)%p)).map_or(n.len() as i32, |&j|i as i32 - j);
m.insert(s, i as i32); d
}).min().filter(|&r|r < n.len() as i32).unwrap_or(-1)
}
29.11.2025
3512. Minimum Operations to Make Array Sum Divisible by K easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1188
Problem TLDR
Sum % k #easy
Intuition
The number of operations is the remainder of %k
Approach
- %k
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 11ms
fun minOperations(n: IntArray, k: Int) =
n.sum() % k
// 0ms
pub fn min_operations(n: Vec<i32>, k: i32) -> i32 {
n.iter().sum::<i32>() % k
}
28.11.2025
2872. Maximum Number of K-Divisible Components hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1187
Problem TLDR
Max cuts where every subtree sum %k #hard #dfs
Intuition
// any subtree sum %k is a valid cut
Approach
- DFS: start from any, return sum, track %k each
- BFS: start from leafs, accumulate sums in v, track %k each
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 34ms
fun maxKDivisibleComponents(n: Int, e: Array<IntArray>, v: IntArray, k: Int): Int {
val g = Array(n) { ArrayList<Int>() }; for ((a,b) in e) { g[a] += b; g[b] += a }
fun dfs(i: Int, p: Int): Int =
(g[i].sumOf { j -> if (j==p) 0 else dfs(j, i)} + if (v[i]%k<1)1 else 0)
.also { v[p] += v[i]%k }
return dfs(0, 0)
}
// 32ms
pub fn max_k_divisible_components(n: i32, e: Vec<Vec<i32>>, mut v: Vec<i32>, k: i32) -> i32 {
let (mut g, mut d) = (vec![Vec::new(); v.len()], vec![0; v.len()]);
for p in e {let (a,b) = (p[0]as usize,p[1]as usize);g[a].push(b);g[b].push(a);d[a]+=1;d[b]+=1}
let mut q = VecDeque::from_iter((0..v.len()).filter(|&i|d[i]<2)); let mut r = 0;
while let Some(u) = q.pop_front() { if v[u] % k < 1 { r += 1 }
for &x in &g[u] { if d[x] > 0 { v[x] += v[u]%k; d[x] -=1; if d[x]==1 { q.push_back(x);}}}
}; r
}
27.11.2025
3381. Maximum Subarray Sum With Length Divisible by K medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1186
Problem TLDR
Max sum of %k-length subarray #medium
Intuition
// -1 1 -1 1 -1 1 %3
// *
// * * *
//
// all sums O(n^2)
// all subarrays O(n^2) k=1
// find just max subarray sum, then expand/shrink?
// use two pointers and shrink from both ends until %k?
// 2 -5 3 2 1 %3, which pointer to move?
// i j
//
// i ending at i we have i/k possible starting points
// all of them are moving with i + 1,
// **s**s**s*i %3
// ***
// ******
// *********
// the algo is O(n*(n/k)) = O(n^2)
//
// looks like a hard problem
// 17 minutes, use hint - min prefix sum ending at every i%k (didn't tell much)
- dp[i] = sum(i-k..i)+max(0, dp[i-k]), where dp[i] is answer for array ending at i
Approach
- solution from lee (i copied it in rust) is uncomprehensible, let’s just say it is compressed
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 44ms
fun maxSubarraySum(n: IntArray, k: Int): Long {
val dp = LongArray(n.size); val p = LongArray(n.size+1)
for (i in n.indices) p[i+1] = n[i].toLong()+p[i]
for (i in n.indices) dp[i] = (p[i+1]-if(i-k+1>=0)p[i-k+1]else 0) +
max(0, if(i-k+1>=k)dp[i-k]else 0)
return dp.drop(k-1).max()
}
// 7ms
pub fn max_subarray_sum(n: Vec<i32>, k: i32) -> i64 {
let k = k as usize; let (mut p, mut s) = (vec![i64::MAX/2; k], 0); p[k-1] = 0;
(0..n.len()).map(|i| { s += n[i] as i64;
let r = s - p[i%k]; p[i%k] = s.min(p[i%k]); r}).max().unwrap()
}
26.11.2025
2435. Paths in Matrix Whose Sum Is Divisible by K hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1185
Problem TLDR
Paths in 2D matrix %k #hard
Intuition
Each cell hash exactly k possible remainders of all paths, so memo by [y][x][k]
Approach
- top down is just a memo+bruteforce DFS
Complexity
-
Time complexity: \(O(nk)\)
-
Space complexity: \(O(nk)\)
Code
// 479ms
fun numberOfPaths(g: Array<IntArray>, k: Int): Int {
val M = 1000000007; val dp = HashMap<Int, Int>()
fun dfs(y: Int, x: Int, s: Int): Int =
if (y==g.size-1&&x==g[0].size-1) {if ((g[y][x]+s)%k==0) 1 else 0}
else if (y==g.size||x==g[0].size) 0 else
dp.getOrPut(y*1000000+x*100+s) {
(dfs(y+1, x, (g[y][x] + s)%k) + dfs(y, x+1, (g[y][x]+s)%k))%M
}
return dfs(0, 0, 0)
}
// 29ms
pub fn number_of_paths(g: Vec<Vec<i32>>, k: i32) -> i32 {
let k = k as usize; let mut r = vec![vec![0; k+1]; g[0].len()+1];
let mut n = r.clone(); r[1][0] = 1;
for row in g {
for x in 0..r.len()-1 { let v = row[x]as usize; for i in 0..k {
n[x+1][(i+v)%k] = (n[x][i] + r[x+1][i])%1000000007 }}
(r,n)=(n,r)
}; r[r.len()-1][0]
}
25.11.2025
1015. Smallest Integer Divisible by K medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1184
Problem TLDR
Smallest number 11..1 % k #medium
Intuition
// k 10^5
// x*k = n, n is '1(1)`
// return length(n) or lg(n)
// smallest
// 11 = 10 + 1
// 111 / 3 = 37
// this is math brainteaser
//
// what numbers gives 1 at the end
// 1 7 11
//
// how to make result all of ones?
//
// or, if we take long string of ones how to find if it is %k
// we have to multiply by 10 and add 1
// can we do %k every time and check first that is 0?
// how to stop?
Approach
- to stop look for remainder loops or just stop at k steps
Complexity
-
Time complexity: \(O(k)\)
-
Space complexity: \(O(1)\)
Code
// 11ms
fun smallestRepunitDivByK(k: Int): Int {
var x = 0
return (1..k).firstOrNull { x = (x * 10 + 1) % k; x == 0 } ?: -1
}
// 0ms
pub fn smallest_repunit_div_by_k(k: i32) -> i32 {
let mut x = 0;
(1..=k).find(|i| {x=(x*10+1)%k; x==0}).unwrap_or(-1)
}
24.11.2025
1018. Binary Prefix Divisible By 5 easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1183
Problem TLDR
Prefixes divisible by 5 #easy #brainteaser
Intuition
// its not easy; its brainteaser
// the 10^5 length
// how to convert base_2 to base_5 directly?
// to convert to base_10
// let's try convert to long base_10
// it goes out of range too fast
// can we trim it % 5?
Approach
- the remainder of %5 is enough
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 3ms
fun prefixesDivBy5(n: IntArray) =
{ var x = 0; n.map {x = (x*2+it)%5; x<1 }}()
// 0ms
pub fn prefixes_div_by5(n: Vec<i32>) -> Vec<bool> {
let mut x = 0; n.iter().map(|&n|{x=(x*2+n)%5; x<1}).collect()
}
23.10.2025
1262. Greatest Sum Divisible by Three medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1182
Problem TLDR
Max sum that %3 #medium
Intuition
// add all numbers that are %3
// search the remaining
// they can be %3=1, %3=2
// we need pairs 1+2
// now take max pairs from 1+2
// or tripples from %3=1 is this a choice?
// big_1 big_1 big_1 small_2
// this makes us loose big_1 + big_1 compared to small_2
// what if we take from single sorted list
// big_1 big_2 (take)
// big_2 big_2 (skip) big_2(skip) big_1 big_1 wrong skip
// what if we take from two lists big_1 sorted and big_2 sorted
// take big_1 big_1 big_1 if it is bigger then big_1 big_2
// edge case: 5 2 2 2 so three %3=2 is also %3
// + some big corner case (my not optimal)
// probably case where 111 == 222 == 12 and we have to choose
// is this dp?
// 23 minute, let's look hints: yes it is dp
// 28 minute: MLE
// i have another idea: all sum can be %3==0,1, or 2
// if %3==0 just return sum
// if %3==1 remove smallest %3==1 or two %3==2
// if %3==2 remove smallest %3==2 or two %3==1
- remove the smallest from sum
- only 3 cases possible
Approach
- another approach is dp: keep three running sums: %3=0,1,2; evaluate where to place
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 4ms
fun maxSumDivThree(n: IntArray): Int {
var s=0; var s1=20000; var s11=s1; var s2=s1; var s22=s1
for (x in n) {
s += x
if (x%3==1) if (x<s1) {s11=s1; s1=x} else if (x<s11) s11=x
if (x%3==2) if (x<s2) {s22=s2; s2=x} else if (x<s22) s22=x
}
return s - if (s%3==2) min(s2,s1+s11) else (s%3)*min(s1,s2+s22)
}
// 0ms
pub fn max_sum_div_three(n: Vec<i32>) -> i32 {
let mut s = [0,0,0];
for x in n { for y in [x+s[0], x+s[1], x+s[2]] {
let i = (y%3) as usize; s[i] = s[i].max(y) }}; s[0]
}
22.11.2025
3190. Find Minimum Operations to Make All Elements Divisible by Three easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1181
Problem TLDR
Min steps inc/dec to make %3 #easy
Intuition
- min(x%3, 3-x%3)
Approach
- it is actually always min(1,2) = 1
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 1ms
fun minimumOperations(n: IntArray) =
n.count { it%3>0 }
// 0ms
pub fn minimum_operations(n: Vec<i32>) -> i32 {
n.iter().filter(|&x| x%3>0).count() as _
}
21.11.2025
1930. Unique Length-3 Palindromic Subsequences medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1180
Problem TLDR
3-palindroms subsequences #medium
Intuition
// how many pairs we have for alphabet?
// 26*26 - 500*10^5 = 10^7 too big
// a b c d a so, between same chars every uniq counts
// a......b........a.......b can intersect
Approach
- we can use bitmask for speedup
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 121ms
fun countPalindromicSubsequence(s: String) =
('a'..'z').sumOf { s.slice(s.indexOf(it)+1..<s.lastIndexOf(it)).toSet().size }
// 127ms
pub fn count_palindromic_subsequence(s: String) -> i32 {
('a'..='z').filter_map(|c| {
let r = s.rfind(c)?; let l = s[..r].find(c)?;
Some(s[l+1..r].chars().unique().count() as i32)
}).sum()
}
20.11.2025
757. Set Intersection Size At Least Two hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1179
Problem TLDR
Min set each interval have two values in it #hard #sorting
Intuition
// 1 2 3 4 5
// * * *
// * * * *
// * * * *
// * * *
// i drop 1..3, should take two values from it +2
// take the last two: 2,3
// i drop 1..4, the last two is in 1..4, so skip
// i drop 2..5, 2 in 2..5, 3in2..5, skip
// drop 3..5, 2 !in 3..5, take 5, 3 in 2..5 +1
// 1 2 3 4 5
// * *
// * *
// * * *
// * *
// i drop 1..2, +2 (a=1,b=2)
// i drop 2..3, +1 (a=3,b=2)
// i drop 2..4, skip
// drop 4..5, +2 a=5,b=4
// 1 2 3 4 5 6 7 8
// * * *
// * * * * *
// * * *
// * *
// i=2 drop 1..3, +2, a=2 b=3
// i=3 drop 3..7, +1, a=7 b=3 then a=3 b=7
// drop 5..7, +1,
- sort by the ends: this tells you that interval has ended and you should do something with it
Approach
- no need to store visited intervals in a heap
- no need for a hashset, just use two variables
- don’t even need for while loop: just check if every interval has ‘a’ and ‘b’ in it
Complexity
-
Time complexity: \(O(nlog(n))\)
-
Space complexity: \(O(1)\)
Code
// 25ms
fun intersectionSizeTwo(v: Array<IntArray>): Int {
v.sortBy { it[1] }; var a = -1; var b = -1; var res = 0
for ((l,r) in v) {
if (a < l) { a = if (r==b) b-1 else b; b=r; res++}
if (a < l) { a = b-1; res++}
}
return res
}
// 3ms
pub fn intersection_size_two(mut v: Vec<Vec<i32>>) -> i32 {
v.sort_by_key(|v|v[1]); let (mut a, mut b, mut r) = (-1,-1,0);
for v in &v {
if a < v[0] { a = if b == v[1] { b-1 } else { b }; b = v[1]; r += 1 }
if a < v[0] { a = b - 1; r += 1 }
}; r
}
19.11.2025
2154. Keep Multiplying Found Values by Two easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1178
Problem TLDR
First original=original*2 not in array #easy
Intuition
Simulate the proces. Use hashset to speedup.
Approach
- for 1000 elements O(n^2) is acceptable
Complexity
-
Time complexity: \(O(n + log(max))\)
-
Space complexity: \(O(n)\)
Code
// 15ms
fun findFinalValue(n: IntArray, o: Int) =
o shl (0..10).first { o shl it !in n }
// 0ms
pub fn find_final_value(n: Vec<i32>, o: i32) -> i32 {
o << (0..11).find(|b| !n.contains(&(o << b))).unwrap()
}
18.11.2025
717. 1-bit and 2-bit Characters easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1177
Problem TLDR
Is ‘0’ last from characters ‘0’,’10’,’11’ concatenation #easy
Intuition
I had to start with DP: in each i position if b[i] zero go next, otherwise go next->next. Then it is just a linear solution without a choice.
Approach
- optimization: go from back
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 0ms
fun isOneBitCharacter(b: IntArray): Boolean {
var i = b.size - 2
while (i >= 0 && b[i] > 0) i -= b[i]
return (b.size - i) % 2 < 1
}
// 0ms
pub fn is_one_bit_character(b: Vec<i32>) -> bool {
b[..b.len()-1].split(|&x|x<1).last().unwrap().len()%2<1
}
17.11.2025
1437. Check If All 1’s Are at Least Length K Places Away easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1176
Problem TLDR
All ones k-distant #easy
Intuition
Count zeros in-between.
Approach
- we can write it with 1 extra variable
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 3ms
fun kLengthApart(nums: IntArray, k: Int): Boolean {
var z = k
return nums.all { n -> (n < 1 || z >= k).also { z = (1-n)*(z+1-n)}}
}
// 0ms
pub fn k_length_apart(n: Vec<i32>, k: i32) -> bool {
let mut z = k;
n.iter().all(|&n|{ let r = n < 1 || z >= k; z = (1-n)*(z+1-n); r})
}
16.11.2025
1513. Number of Substrings With Only 1s medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1175
Problem TLDR
Substrings of ones #medium #counting
Intuition
Sum the separate islands of ones. Each island length is n(n+1)/2 arithmetic sum.
Approach
- or compute the arithmetic sum on the go
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 21ms
fun numSub(s: String) = s.fold(0 to 0) { (r,curr), c ->
val curr = (c-'0')*curr + (c-'0')
(r + curr) % 1000000007 to curr
}.first
// 0ms
pub fn num_sub(s: String) -> i32 {
s.bytes().fold((0, 0), |(r, curr), c| {
let curr = (c-b'0')as i32*curr + (c-b'0')as i32;
((r+curr)%1000000007, curr)
}).0
}
15.11.2025
3234. Count the Number of Substrings With Dominant Ones medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1174
Problem TLDR
Subarray zeros^2 less than ones #medium #sliding_window
Intuition
// 000110011(+21 ones tail, can't move j)
// j i z=5 o=3
// j i z=4 o=3
// j i z=3 o=3
// j i z=2 o=3
// for each i how many 'j' we have
// z = zeros[i]-zeros[j]
// o = ones[i]-ones[j]
// `z*z` less or equal `o`
// (z[i]-z[j])^2 +o[j] = o[i]
// z[i]^2 -2z[i]z[j]+z[j]^2+o[j]=o[i]
// -2z[i]z[j]+z[j]^2+o[j]=o[i]-z[i]^2
//
// solve around j, looks like a math problem
// ok this is a hard problem but let's try brute force O(n*sqrt(n))
// 32 minute - TLE on input all of ones; because the answer is n^2 of them good
// hints are not giving any obvious ideas
// but i suspect we can skip islands of ones
Approach
- use prefix sums
- use jump array
- if we good we can jump all ones in current island of ones
- if we not, jump to the difference z^2-o
Complexity
-
Time complexity: \(O(nsqrt(n))\)
-
Space complexity: \(O(n)\)
Code
// 58ms
fun numberOfSubstrings(s: String): Int {
val z = IntArray(s.length+1); val o = IntArray(s.length+1)
val io = IntArray(s.length) { it-1 }; var res = 0
for (i in 0..<s.length) {
if (s[i]=='0') ++z[i+1] else ++o[i+1]
if (i > 0 && s[i]=='1' && s[i-1]=='1') io[i] = io[i-1]
z[i+1] += z[i]; o[i+1] += o[i]; var j = i
while (j >= 0) {
val z = z[i+1]-z[j]; val d = z*z-o[i+1]+o[j]
if (d > 0) j -= d else { res += j-io[j]; j = io[j] }
}
}
return res
}
// 63ms
pub fn number_of_substrings(s: String) -> i32 {
let (n, s) = (s.len(), s.as_bytes());
let (mut z, mut o, mut io)=(vec![0;n+1],vec![0;n+1],vec![0;n]);
let mut r = 0; for i in 0..n { io[i] = i as i32 - 1; }
for i in 0..n {
if s[i]==b'0' { z[i+1] = 1 } else { o[i+1] = 1 }
if i>0 && s[i]==b'1'&&s[i-1]==b'1' { io[i] = io[i-1] }
z[i+1] += z[i]; o[i+1] += o[i]; let mut j = i;
while j<n {
let z = z[i+1]-z[j]; let d = z*z-o[i+1]+o[j];
if d>0 { j -= d as usize } else { r += j as i32-io[j]; j=io[j]as usize }
}
}; r
}
14.11.2025
2536. Increment Submatrices by One medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1173
Problem TLDR
Increase matrix by query of rectangles of ones #medium #linesweep
Intuition
Expand 1D line sweep pattern to 2D: mark entire rows with +1 for start and -1 to end.
Approach
- -1 should be on the next cell
- or, you can mark just 4 cells and compute prefix sum in a separate step
Complexity
-
Time complexity: \(O(q*n)\)
- Space complexity: \(O(n^2)\)
Code
// 31ms
fun rangeAddQueries(n: Int, q: Array<IntArray>): Array<IntArray> {
val cnt = Array(n) { IntArray(n+1) }
for (q in q) for (y in q[0]..q[2]) {++cnt[y][q[1]]; --cnt[y][q[3]+1]}
return Array(n) { y -> var c=0; IntArray(n) { x -> c += cnt[y][x];c}}
}
// 4ms
pub fn range_add_queries(n: i32, q: Vec<Vec<i32>>) -> Vec<Vec<i32>> {
let n = n as usize; let mut m = vec![vec![0; n];n];
for q in q {
let (a,b,c,d) = (q[0]as usize,q[1]as usize,q[2]as usize,q[3]as usize);
m[a][b] += 1; if d+1 < n { m[a][d+1] -= 1}; if c+1 < n { m[c+1][b] -= 1}
if c+1 < n && d+1 < n { m[c+1][d+1] += 1}
}
for row in &mut m { for col in 1..n { row[col] += row[col-1] }}
for row in 1..n { for col in 0..n { m[row][col] += m[row-1][col] }}; m
}
13.11.2025
3228. Maximum Number of Operations to Move Ones to the End medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1172
Problem TLDR
Max steps to move all ones to the right #medium
Intuition
// 1010101010
// 1010101001
// 1010100011
// 1010000111
// 1000001111
// 0000011111
//
// a b c d e
// 1010101010
// 0110101010 a-1
// 0101101010 b-1
// 0011101010 b-2
// 0011011010 c-1
// 0010111010 c-2
// 0001111010 c-3
// 0001110110 d-1
// 0001101110 d-2
// 0001011110 d-3
// 0000111110 d-5
// 0000111110 e-5 bubble '0' to the left
// go from left to right, each zero gives +(number of ones)
// dedup zeros
Go from left to right and count ones; each zero adds +count_ones
Approach
- skip duplicate consequent zeros
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 39ms
fun maxOperations(s: String) = s.indices.fold(0 to 0) {(o,r),i->
o+(s[i]-'0') to if (s[i]>'0'||i>0 && s[i]==s[i-1]) r else r+o}.second
// 0ms
pub fn max_operations(s: String) -> i32 {
let (mut o, s) = (0, s.as_bytes());
(0..s.len()).map(|i| { o += (s[i] - b'0') as i32;
if i>0&&s[i]==s[i-1]||s[i]==b'1'{0}else{o}
}).sum()
}
12.11.2025
2654. Minimum Number of Operations to Make All Array Elements Equal to 1 medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1171
Problem TLDR
Min steps to make all ‘1’ by gcd #medium
Intuition
- gcd of array = reduce(::gcd)
3 cases:
- have ones in array - then just propagate it in ‘size-ones’ steps
- gcd(array)>1 - no answer, -1
- gcd(array)==1 - then it is
min_window_gcd1steps to make a single1plus propagate itsize-single onessteps
Approach
- this is a hard problem
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n)\)
Code
// 27ms
fun minOperations(n: IntArray): Int {
val n = n.asList(); val ones = n.count { it<2 }
fun gcd(a: Int, b: Int): Int = if (b==0) a else gcd(b, a%b)
return if (ones > 0) n.size - ones else if (n.reduce(::gcd) > 1) -1
else n.size - 2 + (2..n.size).first { L -> n.windowed(L).any { it.reduce(::gcd)<2}}
}
// 0ms
pub fn min_operations(n: Vec<i32>) -> i32 {
let o = n.iter().filter(|&&x|x==1).count() as i32;
if o > 0 { n.len()as i32 - o} else {
fn g(mut a:i32,b:&i32)->i32 { let mut b = *b; while b>0 { let t=b;b=a%b;a=t;} a}
if n.iter().fold(0,g)>1 { -1 } else { n.len() as i32 - 2 +
(2..=n.len()).find(|&l|n.windows(l).any(|w|w.iter().fold(0,g)==1)).unwrap()as i32}
}
}
11.11.2025
474. Ones and Zeroes medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1170
Problem TLDR
Longest subsequence (ones,zeros) at most (m,n) #medium #dp
Intuition
At each string do a choice take it or not. Cache by (i, zeros, ones).
Approach
- bottom up intuition: “update [zeros x ones] matrix if we take the current string”
Complexity
-
Time complexity: \(O(nl^2)\)
-
Space complexity: \(O(nl^2)\)
Code
// 179ms
fun findMaxForm(s: Array<String>, m: Int, n: Int): Int {
val os = s.map { it.count { it == '1' }}; val dp = HashMap<Int, Int>();
fun dfs(i: Int, no: Int, nz: Int): Int = dp.getOrPut(i*10000+no*100+nz) {
if (no > n || nz > m) return Int.MIN_VALUE / 2; if (i == s.size) return 0
max(1 + dfs(i + 1, no + os[i], nz + s[i].length - os[i]), dfs(i + 1, no, nz))
}
return dfs(0, 0, 0)
}
// 17ms
pub fn find_max_form(s: Vec<String>, m: i32, n: i32) -> i32 {
let (m,n)=(m as usize, n as usize); let mut dp = vec![vec![0; n+1];m+1];
for s in s {
let o = s.matches('1').count(); let z = s.len() - o;
for i in (z..=m).rev() { for j in (o..=n).rev() {
dp[i][j] = dp[i][j].max(dp[i - z][j - o] + 1) }}
}; dp[m][n]
}
10.11.2025
3542. Minimum Operations to Convert All Elements to Zero medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1169
Problem TLDR
Min ops to zeros by making min of subarrays 0 #medium #monotonic_stack
Intuition
// 1 2 3 1 2 3 4 1 2 3
// 0 2 3 0 2 3 4 0 2 3
// 0 0 3 0 2 3 4 0 2 3
// 0 0 0 0 2 3 4 0 2 3
// 0 0 0 0 0 3 4 0 2 3
// 0 0 0 0 0 0 4 0 2 3
// 0 0 0 0 0 0 0 0 2 3
// 0 0 0 0 0 0 0 0 0 3
// 0 0 0 0 0 0 0 0 0 0
//
// 1 2 3 2 1
// 0 2 3 2 0
// 0 0 3 0 0
// 0 0 0 0 0
//
// 3 2 1 2 3
// 3 2 0 2 3
// 3 0 0 2 3
// 0 0 0 2 3
// 0 0 0 0 3
// 0 0 0 0 0
//
// 3 2 1 2 3 2 1
// * 3
// * 2<3, +ops
// * 1<2, +ops
// 2 2 1
// 3 3 2 1
// 2 2<3, +ops; 2 1
// 1 1<2, +ops; 1
// 1 + ops
// total = 5
- each decrease means the previous value goes to the separate operation
Approach
- the remainig values in stack are all separate operations
- or, we can count increases as operations instead of decreases
- dirty trick to O(1) memory: use input array as a stack
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 32ms
fun minOperations(n: IntArray): Int {
var s = -1
return n.count { x ->
while (s >= 0 && n[s] > x) s--
(x > 0 && (s < 0 || n[s] < x)).also { if (it) n[++s] = x}
}
}
// 12ms
pub fn min_operations(n: Vec<i32>) -> i32 {
let (mut r, mut s) = (0, vec![0]);
for x in n {
while s[s.len()-1] > x { s.pop(); }
if s[s.len()-1] < x { r += 1; s.push(x) }
}; r
}
09.11.2025
2169. Count Operations to Obtain Zero easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1168
Problem TLDR
Count numbers subtractions until 0 #easy
Intuition
Simulate the process.
Another way to look at it: the biggest would be subtracted big/small times until numbers flip.
Approach
- recursion space complexity is log(depth)
- it is Euclidian algorithm (a,b) to (b, a%b)
- there is a golden ratio hidden here
- consequtive Fibonacci numbers would give the slowest path: Fibonacci sequence backwards
Complexity
-
Time complexity: \(O(log(n))\)
-
Space complexity: \(O(log(n))\)
Code
// 0ms
fun countOperations(a: Int, b: Int): Int =
if (a<1||b<1) 0 else a/b + countOperations(b,a%b)
// 0ms
pub fn count_operations(a: i32, b: i32) -> i32 {
if a<1 || b<1 { 0 } else { a/b + Self::count_operations(b,a%b) }
}
08.11.2025
1611. Minimum One Bit Operations to Make Integers Zero hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1167
Problem TLDR
Min steps to make zero by xor 1 or xor rightmost+1 #hard #bits
Intuition
Didn’t solve myself.
// 000010101
// **
// 000100000 1
// 000100001 2
// 000100011 3
// 000100010 4
// 000100110 5
// 000100101 6
// 000100100 7
// 000101100 8
// 000101101 9
// 000101111 10
// 000101110 11
// 000101010 12
// 000101011 13
// 000101001 14
// 000101000 15
// 000111000 16
// 000111001 17
// 000111011 18
// 000111010 19
// 000111110 20
// 000111111 21
// 000111101 22
// 000111100 23
// 000110100 24
// 000110101 25
// 000110111 26
// 000110110 27
// 000110010 28
// 000110011 29
// 000110001 30
// 000110000 31
// 000010000 0
// 000010001 1
// 000010011 2
// 000010010 3
// 000010110 4
// 000010111 5
// 000010101 6
// 000010100 7
// 000011100 8
// 000011101 9
// 000011111 10
// 000011110 11
// 000011010 12
// 000011011 13
// 000011001 14
// 000011000 15
// 000001000 0
// 000001001 1
// 000001011 2
// 000001010 3
// 000001110 4
// 000001111 5
// 000001101 6
// 000001100 7
// 000000100 0
// 000000101 1
// 000000111 2
// 000000110 3
// 000000010 0
// 000000011 1
// 000000001 0
//
// the brute force gives TLE (19 minute)
// bit 8
// bit 7 255 128
// bit 6 - 127 step 64
// bit 5 - 63 step 32
// bit 4 - 31 steps 16
// bit 3 - 15 steps 8
// bit 2 - 7 steps 4
// bit 1 - 3 steps 2
// bit 0 - 1 steps 1
// the law bit - 2^(bit+1)-1 it is to make zero, not just remove bit
// but what if we start not from a single bit? any additional bit decrease the steps needed
// or, its all steps for the next bit plus tail
// maybe brute force until find some power of two? - TLE
// Hint 2 (45 minute) useless, i don't know how to transition from a single bit to several bits
// ok, hint from discussion: the tail bits treated like separate subtractions
//
// 1011 = 1000 + 0010 + 0001
// 3 1 0
// a b c
// a - ( b - c)
- The law for the single bit set is
2^(bit+1)-1- just check testcases with 2,4,8,16,32,64,.. - Solve for the most significant bit. The steps already include the tail, so subtract the tail. Do the recursion.
Approach
- to find the 2 intuition you can spend a day or month of thinking
Complexity
-
Time complexity: \(O(log(n))\)
-
Space complexity: \(O(1)\)
Code
// 0ms
fun minimumOneBitOperations(n: Int): Int {
if (n == 0) return 0
val bit = n.takeHighestOneBit()
return (bit shl 1) - 1 - minimumOneBitOperations(n xor bit)
}
// 0ms
pub fn minimum_one_bit_operations(n: i32) -> i32 {
if n < 1 { return 0 }
let b = 1 << (31 - n.leading_zeros());
(b << 1) - 1 - Self::minimum_one_bit_operations(n^b)
}
07.11.2025
2528. Maximize the Minimum Powered City hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1166
Problem TLDR
Max min r-range sum after adding total of k #hard #bs #sliding_window
Intuition
Define a target minimum range and binary search it. To check if each value can add up to range in total of k budget use a sliding window. Add to the rightmost position.
// 1 2 4 5 0 r=1 k=2
// * 1+2 3 +2
// * 1+2+4 7
// * 2+4+5 11
// * 4+5+0 9
// * 5+0 5
// the greedy idea: take the lowest city, but how many to add?
// the k is 10^9, adding by constant can be too much steps
// also adding to city propagates to range, so it O(adds*range)
//
// binary search idea: define the target minimum, greedily add up to it
// how to add to a city in a linear way?
//
// we can have two ranges and a single optimal spot
//
// [ range1 ]
// [ ] the optimal spot
// [ range2 ]
//
// anyway, if we see the first city that needs more power add lazily
// [i + range - 1] += 1
// to calculate powers we need O(n)
// 1 1 1 1 1 1
// [ 3 ]
// [ x ]
// x = prev+1-1
Approach
- use a separate long array to keep track of the additions
Complexity
-
Time complexity: \(O(nlog(n))\)
-
Space complexity: \(O(n)\)
Code
// 89ms
fun maxPower(s: IntArray, R: Int, k: Int): Long {
var lo = 0L; var hi = Long.MAX_VALUE
while (lo <= hi) {
val m = lo + (hi - lo) / 2; var good = true
val s = LongArray(s.size) { s[it].toLong() }
var sum = 0L; var k = k.toLong(); var r = 0
for (i in s.indices) {
while (r < s.size && r - i <= R) sum += s[r++]
if (sum < m) {
s[min(s.lastIndex,i+R)] += m - sum
k -= m - sum; sum = m
}
if (i - R >= 0) sum -= s[i-R]
if (k < 0) { good = false; break }
}
if (good) lo = m + 1 else hi = m - 1
}
return hi
}
06.11.2025
3607. Power Grid Maintenance medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1165
Problem TLDR
Smallest in subgraph after turning some nodes off #medium #uf
Intuition
Union-Find to build subgraphs. Group by roots and put into TreeSets.
Approach
- use Map<Root,TreeSet>
Complexity
-
Time complexity: \(O(nlog(n))\)
-
Space complexity: \(O(n)\)
Code
// 223ms
fun processQueries(c: Int, conn: Array<IntArray>, q: Array<IntArray>)=buildList<Int>{
val u = IntArray(c+1) { it }
fun f(x: Int): Int = if (x == u[x]) x else f(u[x]).also {u[x] = it}
for ((a,b) in conn) u[f(a)] = f(b)
val g = (1..c).groupBy { f(it) }.mapValues {TreeSet<Int>(it.value)}
for ((t, v) in q) g[f(v)]?.let {if (t == 2) it.remove(v) else
add(if (v in it) v else it.firstOrNull()?:-1) }
}
// 99ms
pub fn process_queries(c: i32, conn: Vec<Vec<i32>>, q: Vec<Vec<i32>>) -> Vec<i32> {
let mut u: Vec<_> = (0..=c as usize).collect();
fn f(u: &mut Vec<usize>, x: usize) -> usize { if x==u[x] { x } else { let r = f(u,u[x]); u[x]=r; r} }
for e in conn { let (a,b) = (e[0]as usize,e[1]as usize); let r = f(&mut u,a); u[r]=f(&mut u,b);}
let mut g = HashMap::new();
for i in 1..=c as usize {g.entry(f(&mut u,i)).or_insert_with(BTreeSet::new).insert(i as i32);}
q.iter().map(|p|{
let (t,v) = (p[0],p[1]); let s = g.get_mut(&f(&mut u,v as usize)).unwrap();
if t > 1 { s.remove(&v);-2} else { if s.contains(&v) { v} else { *s.iter().next().unwrap_or(&-1)}}
}).filter(|&r| r > -2).collect()
}
05.11.2025
3321. Find X-Sum of All K-Long Subarrays II hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1164
Problem TLDR
Sums of x most frequent from k-windows #hard
Intuition
The main hardness is how to maintain the top sorted X values in a sliding window.
There is a trick from:
- use TreeSet for the X values
- when removing from X, place removed numbers in a second TreeSet B
- balance if the best number from B is better than lowest from X
// 3 3 1 3 3
// how to speed up/re-use the sum of most frequent
// 1 1 2 2 3 4 2 3
// 1 1 2 2 3 4 2 1 4 3 top 2 is 2 1 or sum(1 1 2 2)
// 1 2 2 3 4 2 2 4 3 1 top 2 is 2 4 or sum(2 2 2 4) -1 +2 binarysearch n is in topX?
// 2 2 3 4 2 3 2 3 4 2 top 2 is 2 3 or sum(2 2 2 3 3) -4(all) + 3(all)
// how to find which values are out of top
// the add to top is simple: only when frequency increases, same value can became in top
// but what values are out of top? maybe the last in the top
// can we only keep X values in set? - no, because we loose some promising big numbers like 4 from 1,1,2,2,3,4,2,3
// 11122333 x=1
// 111
// 112
// 122
// time 55, look for hint: the misteriuos second set
Approach
- related problem: https://leetcode.com/problems/sliding-window-median/description/
Complexity
-
Time complexity: \(O(nlogx)\)
-
Space complexity: \(O(n)\)
Code
// 1054ms
fun findXSum(n: IntArray, k: Int, x: Int): LongArray {
val f = HashMap<Int, Long>(); val res = LongArray(n.size-k+1)
val q = TreeSet<Int>(compareBy<Int>{f[it]?:0L}.thenBy<Int>{it})
val o = TreeSet<Int>(q.comparator()); var sum = 0L
fun poll() = if (q.size > x) {
sum -= 1L * (f[q.first()] ?: 0) * q.first()
o += q.pollFirst()
} else Unit
fun add(n: Int) { q += n; sum += 1L * f[n]!! * n; poll() }
fun balance() {
poll()
if (o.size > 0 && (q.size < x || q.comparator().compare(o.last(),q.first()) > 0)) add(o.pollLast())
}
for (i in n.indices) {
val oldF = f[n[i]] ?: 0L; val newF = 1L + oldF
if (n[i] in q) sum -= oldF * n[i]
q -= n[i]; o -= n[i]; f[n[i]] = newF; add(n[i])
if (i >= k-1) {
balance()
res[i-k+1] = sum
val n = n[i-k+1]; val oldF = f[n] ?: 0L; val newF = oldF - 1L
if (n in q) sum -= oldF * n
o -= n; q -= n; f[n] = newF; if (newF > 0L) add(n) else f -= n
}
}
return res
}
04.11.2025
3318. Find X-Sum of All K-Long Subarrays I easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1163
Problem TLDR
Sums of x most frequent from k-windows #easy
Intuition
Not actually easy. Brute-force: solve for each window, count frequency map, sort, take x.
Approach
- only 50 numbers; use an array instead of a HashMap
Complexity
-
Time complexity: \(O(nklogk)\)
-
Space complexity: \(O(n)\)
Code
// 62ms
fun findXSum(n: IntArray, k: Int, x: Int) =
(0..n.size-k).map { val g = n.slice(it..<it+k).groupBy {it}
g.keys.sortedWith(compareBy({-(g[it]!!).size},{-it}))
.take(x).map { it * g[it]!!.size }.sum()
}
// 1ms
pub fn find_x_sum(n: Vec<i32>, k: i32, x: i32) -> Vec<i32> {
n.windows(k as usize).map(|w| {
let mut f = [0;51]; for &v in w.iter() { f[v as usize] += 1 }
(0..51).map(|v|(-f[v],-(v as i32))).sorted().into_iter()
.take(x as usize).map(|(f,v)|v*f).sum()
}).collect()
}
03.11.2025
1578. Minimum Time to Make Rope Colorful medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1162
Problem TLDR
Min weighted removals to dedup #medium #greedy
Intuition
Scan from left to right, keep only max from islands of duplicates.
Approach
- how many extra variables you need?
- add all time at each step, remove max at change
- or, add all sum(window(min))
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 23ms
fun minCost(c: String, t: IntArray) =
(1..<c.length).sumOf { i -> if (c[i] != c[i-1]) 0 else
min(t[i], t[i-1]).also { t[i] = max(t[i], t[i-1]) }
}
// 3ms
pub fn min_cost(c: String, t: Vec<i32>) -> i32 {
c.bytes().zip(t.iter()).chunk_by(|(a,_)| *a).into_iter()
.map(|(_, c)| {
let (s,m) = c.fold((0, 0), |(s,m), (_, &t)| (s+t,m.max(t))); s-m
}).sum()
}
02.11.2025
2257. Count Unguarded Cells in the Grid medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1161
Problem TLDR
Count unseen cells by rays from guards #medium #grid
Intuition
- 4 rays iterations: left, top, right, bottom
- or, rays from guards until another guard or wall
- or, rays from guards, but mask by direction; don’t have to place guards
Approach
- count in-place or in another iteration
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 168ms
fun countUnguarded(m: Int, n: Int, g: Array<IntArray>, w: Array<IntArray>): Int {
val c = Array(m) { IntArray(n) }; for ((y, x) in g+w) c[y][x] = 2; var x=0; var y=0
for ((i, j) in g) for (f in setOf({--x;1},{++x;1},{--y;1},{++y;1})) { y=i; x=j; f()
while (y in 0..<m && x in 0..<n && c[y][x] < 2) c[y][x] = f() }
return c.sumOf { it.count { it < 1 }}
}
// 31ms
pub fn count_unguarded(m: i32, n: i32, g: Vec<Vec<i32>>, w: Vec<Vec<i32>>) -> i32 {
let mut c = vec![vec![0;n as usize];m as usize]; for g in chain(&g,&w) { c[g[0] as usize][g[1] as usize]=2}
for g in &g { for (i,j) in &[(-1,0),(0,1),(1,0),(0,-1)] { let (mut y, mut x)=(g[0]+i, g[1]+j);
while y.min(x)>=0 && y<m && x<n && c[y as usize][x as usize] < 2 { c[y as usize][x as usize]=1; y+=i; x+=j}
}} c.iter().flatten().filter(|&&v|v<1).count() as _
}
01.11.2025
3217. Delete Nodes From Linked List Present in Array medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1160
Problem TLDR
Remove an array from linked list #medium #ll
Intuition
Convert the array to HashSet.
Approach
- use a dummy node in a case of a removal of the first node from LL
- use a nested while loop
- code can be rewritten to a single while loop
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 47ms
fun modifiedList(n: IntArray, h: ListNode?): ListNode? {
val dummy = ListNode(0).apply { next = h }
val s = n.toSet(); var curr = dummy
while (curr.next != null)
if (curr.next.`val` in s) curr.next = curr.next.next
else curr = curr.next ?: break
return dummy.next
}
// 20ms
pub fn modified_list(n: Vec<i32>, h: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
let mut dummy = ListNode { val: 0, next: h };
let mut cur = &mut dummy; let mut s: HashSet<_> = n.iter().collect();
while let Some(next_box) = cur.next.as_mut() {
if s.contains(&next_box.val) {
cur.next = next_box.next.take();;
} else { cur = cur.next.as_mut().unwrap() }
}
dummy.next
}
31.10.2025
3289. The Two Sneaky Numbers of Digitville easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1159
Problem TLDR
Two extra numbers from 0..n #easy
Intuition
Use any of:
- HashSet for visited
- bitmask for visited
- array itself for visited
The clever solution with bit manipulation:
- total xor, no extras: a^b^c – can compute as x1
- total xor for single extra: a^b^c^a
- total xor for two extras: a^b^c^a^b – can compute as x2
- xor of x1^x2: a^b^c ^ a^b^c^a^b = a^b – can compute as x1^x2
Now we have a^b, each bits is a different between a and b.
Split all given numbers by have or have-nots of this bit. xor(have_bit) = xx1 xor(have_not_bit) == xx2
Then split range numbers similarly: xor(have_bit) == yy1 xor(have_not_bit) == yy2
Then a = xx1 ^ yy1, b = xx2 ^ yy2
Approach
- just brute-force
Complexity
-
Time complexity: \(O()\)
-
Space complexity: \(O()\)
Code
// 17ms
fun getSneakyNumbers(n: IntArray) =
n.indices.filter { x -> n.count { it == x } > 1 }
// 0ms
pub fn get_sneaky_numbers(n: Vec<i32>) -> Vec<i32> {
let mut m = 0u128;
n.into_iter().filter(|x| { let u = (1 << x) & m > 0; m |= 1<<x; u}).collect()
}
30.10.2025
1526. Minimum Number of Increments on Subarrays to Form a Target Array hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1158
Problem TLDR
Min +1 range increases to make target from zeros #hard
Intuition
// ********* 1
// ** ***** 2, 3
// ** ** ** 4, 5, 6
// * 7
// 331143233
// 6 7 7 2 1 2 2 1 3
// 6 6 levels
// 7 +1 level, (6..1 levels continue)
// 7 +0 levels, (7..1 levels continue)
// 2 -5 levels (7..3 stop, 2..1 continue) +5 ops
// 1 -1 (2..2 stop, 1..1 continue) +1 ops
// 2 +1 (1..2 continue)
// 2 +0
// 1 -1 (2..2 stop, 1..1 continue) +1 ops
// 3 +2 1..3 continue
// end (1..3 stop) +2 ops and +1 for level 1
Optimal strategy is the Tetris game: remove islands from the bottom. The number of ops is the number of islands. The number of islands is the number of decreases.
Approach
- draw the picture
- assume algorithm is linear, try to gain as much information at each step as possible
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 58ms
fun minNumberOperations(t: IntArray) =
t.zip(t.drop(1)+0).sumOf { (a,b) -> max(0, a-b)}
// 0ms
pub fn min_number_operations(t: Vec<i32>) -> i32 {
t[0] + t.windows(2).map(|w| 0.max(w[1]-w[0])).sum::<i32>()
}
29.10.2025
With All Set Bits easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1157
Problem TLDR
Next all bits set number #easy #bits
Intuition
HighestOneBit shl 1 - 1
101
100 highest one bit
1000 shl 1
0111 -1
Approach
- how to find highestOneBit?
- we can brute force too
(n..2*n).first { (it+1) and it == 0 }
Complexity
-
Time complexity: \(O(1)\)
-
Space complexity: \(O(1)\)
Code
// 0ms
fun smallestNumber(n: Int) =
(n.takeHighestOneBit() shl 1) - 1
// 0ms
pub fn smallest_number(n: i32) -> i32 {
i32::MAX >> n.leading_zeros() - 1
}
28.10.2025
3354. Make Array Elements Equal to Zero easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1156
Problem TLDR
Places & directions that lead the simulation to all zeros #easy #simualtion
Intuition
Try every combination of place and direction
Approach
- without simulation: sum diff (left, right) must be less than 2
Complexity
-
Time complexity: \(O(n^3)\), n^2 for the simulation
-
Space complexity: \(O(n)\)
Code
// 261ms
fun countValidSelections(n: IntArray) =
n.indices.sumOf { s -> if (n[s] == 0) listOf(-1,1).count { d ->
val n = n.clone(); var c = s; var d = d
while (c in 0..<n.size)
if (n[c] > 0) { n[c]--; d *= -1; c += d } else c += d
n.all { it == 0 }
} else 0 }
// 2ms
pub fn count_valid_selections(n: Vec<i32>) -> i32 {
let (mut r, mut l, mut res) = (n.iter().sum::<i32>(),0,0);
for n in n {
l += n; r -= n;
if n < 1 {
if (l - r).abs() < 2 { res += 1 }
if l == r { res += 1 }
}
} res
}
27.10.2025
2125. Number of Laser Beams in a Bank medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1155
Problem TLDR
Count multiplications between rows #medium
Intuition
Total += previous * current (count ‘1’)
Approach
- empty rows are irrelevant
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\) or O(1)
Code
// 56ms
fun numberOfBeams(b: Array<String>) = b
.mapNotNull { it.sumOf { it - '0' }.takeIf { it > 0 }}
.windowed(2).sumOf { it[0]*it[1] }
// 0ms
pub fn number_of_beams(b: Vec<String>) -> i32 {
b.iter().map(|s| s.bytes().filter(|&b| b == b'1').count())
.filter(|&c| c > 0).tuple_windows().map(|(a,b)| (a*b) as i32).sum()
}
26.10.2025
2043. Simple Bank System medium blog post substack youtube
https://assets.leetcode.com/users/images/537d3343-674d-4aca-855d-70851800629b_1761473639.0489593.webp
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1154
Problem TLDR
Design a bank #medium
Intuition
Reuse transfer = withdraw & deposit.
Approach
- carefull with off-by-ones
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 144ms
class Bank(val b: LongArray) {
fun transfer(a1: Int, a2: Int, m: Long) =
a2 <= b.size && withdraw(a1, m) && deposit(a2, m)
fun deposit(a: Int, m: Long) =
a <= b.size && { b[a-1] += m; true }()
fun withdraw(a: Int, m: Long) =
a <= b.size && b[a-1] >= m && { b[a-1] -= m; true }()
}
// 13ms
struct Bank(Vec<i64>); impl Bank {
fn new(b: Vec<i64>) -> Self { Self(b) }
fn transfer(&mut self, a1: i32, a2: i32, m: i64) -> bool
{ a2 as usize <= self.0.len() && self.withdraw(a1, m) && self.deposit(a2, m) }
fn deposit(&mut self, a: i32, m: i64) -> bool
{ let a = a as usize - 1; a < self.0.len() && { self.0[a] += m; true }}
fn withdraw(&mut self, a: i32, m: i64) -> bool {
let a = a as usize - 1;
a < self.0.len() && self.0[a] >= m && { self.0[a] -= m; true }
}
}
25.10.2025
1716. Calculate Money in Leetcode Bank easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1153
Problem TLDR
Add increasing sum of money, drop weekly gain on mondays #easy
Intuition
Simulate.
// 0 1 2 3 4 5 6
// 7 8 9 10 11 12 13
// 14
// 1 2 3 4 5 6 7
// 2 3 4 5 6 7 8 or prev + 7
// 3 4 5 6 7 8 9 or prev + 7
// 4 5 6 7 8 9 10 or prev + 7
The O(1) solutino: count weeks and remainder of days.
Each week contributes as a sum of base7. Contribution of each bases is w(w-1)/2.
Another week contribution is weekly gains, 7*(7+1)/2. They are just w*gains
Approach
- draw the numbers to better understand the laws
Complexity
-
Time complexity: \(O(n)\) or O(1)
-
Space complexity: \(O(1)\)
Code
// 8ms
fun totalMoney(n: Int) = (0..<n).sumOf { it % 7 + it / 7 + 1 }
// 0ms
pub fn total_money(n: i32) -> i32 {
let w = n/7; let d = n-7*w;
let fullweeks = 28*w + 7*w*(w-1)/2;
let taildays = d*(d+1)/2 + w*d;
fullweeks + taildays
}
24.10.2025
2048. Next Greater Numerically Balanced Number medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1152
Problem TLDR
First bigger number freq[digit]=digit #medium
Intuition
Brute-force is accepted. For the problem size of 10^6 the next value is 1224444 which is just 200k loop.
Approach
- or we can try to generate all permutations; prune by length of the initial number
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 425ms
fun nextBeautifulNumber(n: Int) = (n+1..n*21+1)
.first { "$it".groupBy { it }.all { it.key-'0' == it.value.size }}
// 22ms
pub fn next_beautiful_number(n: i32) -> i32 {
(n+1..n*22+2).find(|&x| { let (mut y,mut f) = (x, [0;10]);
while y > 0 { f[(y%10)as usize] += 1; y /= 10 }
(0..=9).all(|x| f[x] == x || f[x] < 1)
}).unwrap()
}
23.10.2025
3461. Check If Digits Are Equal in String After Operations I easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1151
Problem TLDR
Fold each pair to (a+b)%10 until 2 left #easy
Intuition
Just do the simulation
Approach
- use windows
- this problem has a hard solution for O(n): each digit repeats in Pascal triangle pattern coefficients, that is
nCr(size-2, i) % 10. Then there are hard tricks to find %10.
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n)\)
Code
// 86ms
fun hasSameDigits(s: String): Boolean = if (s.length < 3) s[0] == s[1] else
hasSameDigits(s.map {it-'0'}.windowed(2).map {it.sum()%10}.joinToString(""))
fun hasSameDigits(s: String): Boolean {
fun nCr(n: Int, k: Int): Int {
if (k < 0 || k > n) return 0
var k = if (k > n - k) n - k else k; var c = 1.toBigInteger()
for (j in 1..k) c = c.multiply((n - k + j).toBigInteger())
.divide(j.toBigInteger())
return c.mod(10.toBigInteger()).toInt()
}
var a = 0; var b = 0
for (i in s.indices) {
a = (a + nCr(s.length - 2, i) * (s[i] - '0')) % 10
b = (b + nCr(s.length - 2, i - 1) * (s[i] - '0')) % 10
}
return a == b
}
fun hasSameDigits(s: String): Boolean {
fun pascal(p: Int) = Array(p) { IntArray(p) }.also {
for (i in 0..<p) {
it[i][0] = 1; it[i][i] = 1
for (j in 1..<i) it[i][j] = (it[i-1][j-1] + it[i-1][j])%p
}
}
val pas2 = pascal(2); val pas5 = pascal(5)
fun nCrLucas(nn: Int, kk: Int, p: Int, m: Array<IntArray>): Int {
var n = nn; var k = kk; var res = 1
while (n > 0 || k > 0) {
val ni = n % p; val ki = k % p; if (ki > ni) return 0
res = (res * m[ni][ki]) % p
n /= p; k /= p
}
return res
}
fun nCr10(n: Int, k: Int): Int {
if (k < 0 || k > n) return 0
val r2 = nCrLucas(n, k, 2, pas2); val r5 = nCrLucas(n, k, 5, pas5)
var r = r5 + if ((r5 and 1) != (r2 and 1)) 5 else 0
return r % 10
}
var a = 0; var b = 0
for (i in s.indices) {
a = (a + nCr10(s.length-2, i) * (s[i] - '0')) % 10
b = (b + nCr10(s.length-2, i-1) * (s[i] - '0')) % 10
}
return a == b
}
// 0ms
pub fn has_same_digits(s: String) -> bool {
let mut v: Vec<_> = s.bytes().map(|c| c - b'0').collect();
while v.len() >= 3 { v = v.windows(2).map(|w| (w[0] + w[1]) % 10).collect() }
v[0] == v[1]
}
22.10.2025
3347. Maximum Frequency of an Element After Performing Operations II hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1150
Problem TLDR
Max frequency after changing +k..-k ops elements #medium #sliding_window
Intuition
// its like yesterday problem
// so we have two numbers 5,11 the k=5 but ops=1
// we can't change both
// can we have same situation for 3 numbers?
// 5,5,11 k=5 ops=2 the strategy min(o,2)*k didn't work
Solve two separate problems:
- choose every number as baseline, window b-k..b+k
- no baseline, just 2k window
Approach
- the first is the frequency of baseline plus all opeations restricted by the window size
- the second is the entire window restricted by the number of operations
Complexity
-
Time complexity: \(O(nlog(n))\)
-
Space complexity: \(O(n)\)
Code
// 180ms
fun maxFrequency(n: IntArray, k: Int, o: Int): Int {
n.sort(); var l = 0; var j = 0; var r = 0; var f = HashMap<Int,Int>()
return n.withIndex().maxOf { (i,x) ->
while (r < n.size && n[r] <= x+k) f[n[r]] = 1 + (f[n[r++]] ?: 0)
while (l < n.size && n[l] < x-k) f[n[l]] = -1 + f[n[l++]]!!
while (x - n[j] > 2*k) ++j
max(min(f[x]!!+o, r-l), min(i-j+1, o))
}
}
// 42ms
pub fn max_frequency(mut n: Vec<i32>, k: i32, o: i32) -> i32 {
n.sort_unstable(); let (mut l, mut j, mut r, mut f) = (0,0,0,HashMap::new());
n.iter().enumerate().map(|(i,&x)|{
while r < n.len() && n[r] <= x+k { *f.entry(n[r]).or_insert(0) += 1; r += 1 }
while l < n.len() && n[l] < x-k { *f.get_mut(&n[l]).unwrap() -= 1; l += 1 }
while x - n[j] > 2*k { j += 1 }
o.min((i-j+1)as i32).max((r-l) as i32).min(f[&x]+o)
}).max().unwrap_or(0)
}
21.10.2025
3346. Maximum Frequency of an Element After Performing Operations I medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1149
Problem TLDR
Max frequency after changing +k..-k ops elements #medium #sliding_window
Intuition
Didn’t solved.
// 5 6 7 8 10 15 20 k=5
// maybe binary search? for resulting number in lowest..highest
// no rule for bs
// sliding window
// how to track how many was changed?
// group?
// 0 0 0 0 5 5 10 10 10 k=5 o=2
// 0 0 0 0 5 5 10 10 10 k=5 o=1
// 0 0 5 5 5 5 k=5 o=1
// 0 1 1 1 5 5 k=5 o=1
// maintain frequency of each element in window, know max frequency,
// ans = min(max_frequency_in_window+ops, window_size)
// for frequencies: running sorted window, keep map num:freq; when add sorted-f[num]+(++f[num])
// looks complicated, maybe wrong
// 1: window is 2*k
// 2: can't just use most frequent
// 35 minute: let's look for hints
// try each as candidate (j)
// how to count number of operations? window-curr_freq is not correct
// 5 11 20 20 when current freq = 2 of '20'; to do the 2*k range we have to use 2 operations
// and to do 1*k range we can use 0 operations
// 1:14 failed on 58 80 5 let's give up
Solve two separate problems:
- choose every number as baseline, window b-k..b+k
- no baseline, just 2k window
Approach
- sometimes there is no single algorithm, just separate tasks for different cases
Complexity
-
Time complexity: \(O(nlog(n))\)
-
Space complexity: \(O(n)\)
Code
// 125ms
fun maxFrequency(n: IntArray, k: Int, o: Int): Int {
n.sort(); var res = 0; var l = 0; var r = 0; var f = HashMap<Int,Int>()
for (x in n) {
while (r < n.size && n[r] <= x+k) f[n[r]] = 1 + (f[n[r++]] ?: 0)
while (l < n.size && n[l] < x-k) f[n[l]] = -1 + f[n[l++]]!!
res = max(res, min(f[x]!!+o, r - l))
}
l = 0
return max(res, n.indices.maxOf { r -> while (n[r] - n[l] > 2*k) ++l; min(r-l+1, o) })
}
20.10.2025
2011. Final Value of Variable After Performing Operations easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1148
Problem TLDR
do ++ or – operation from 0 #easy
Intuition
Simulate the process.
Approach
- just check ‘+’ in string
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 7ms
fun finalValueAfterOperations(o: Array<String>) =
2 * o.count { '+' in it } - o.size
// 1ms
pub fn final_value_after_operations(o: Vec<String>) -> i32 {
(o.join("").matches('+').count() - o.len()) as _
}
19.10.2025
1625. Lexicographically Smallest String After Applying Operations medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1147
Problem TLDR
Min string after shifting by b and rotating odd indice by a #medium #bruteforce
Intuition
// s is small, up to 100
// if b is even: 12345678 34567812 56781234 78123456
// 1234567 3456712 5671234 7123456 2345671 4567123 6712345 1234567
// if b is odd: 12345678 45678123 78123456 23456781 56781234 81234567 3.. 6..
// 1234567 4567123 7123456 3456712 6712345 2345671 5671234
// so only when b%2 == 0 && size%2 == 0 we don't have access to all elements
// the size is small, we can brute-force every possible rotation to get the minimum
// rotation of digit: 1, a = 3: 1,4,7,0,3,6,9,2
// 25 minute: forgot about odd indices
// 40 minute: we can't change indices independently ?
// 43987654 b=3
// * * *
// 01234567
// 34567012
// 67012345
// 12345670
// 45670123
// 70123456
// 23456701
// 56701234
// 01234567 so, all indices can be on the first position
// 50 minute: wrong steps calculation
// 12345678901234 14, step=6
// 58016941393090
// 41393090580169
// * * *
// 123456789abcde
// 56789abcde1234
Two situations:
- odd length and odd shift: we can rotate only odd indices
- otherwise we can rotate odd indices and even indices
Approach
- rotations should be for all indices; separate value of rotations for odd and even
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n)\)
Code
// 50ms
fun findLexSmallestString(s: String, a: Int, b: Int) = s.indices.minOf { i ->
fun rot(c: Char) = (0..9).minBy { (c-'0'+it*a)%10 }
var sh = s.drop((i*b)%s.length)+s.take((i*b)%s.length)
val eo = listOf(if (s.length % 2 == 0 && b % 2 == 0) 0 else rot(sh[0]), rot(sh[1]))
sh.mapIndexed { i,c -> '0'+(c-'0' + eo[i%2]*a)%10 }.joinToString("")
}
// 0ms
pub fn find_lex_smallest_string(s: String, a: i32, b: i32) -> String {
(0..s.len()).map(|i| {
let rot = |c: u8| {(0..10).min_by_key(|&x| (c - b'0' + x * a as u8) % 10).unwrap()};
let sh = s.chars().cycle().skip((i * b as usize)%s.len()).take(s.len()).collect::<String>();
let eo = [if (s.len() as i32|b)&1 < 1 {0} else {rot(sh.as_bytes()[0])}, rot(sh.as_bytes()[1])];
sh.bytes().enumerate().map(|(i, c)| (b'0' + (c - b'0' + eo[i&1]*a as u8)%10) as char).collect()
}).min().unwrap()
}
18.10.2025
3397. Maximum Number of Distinct Elements After Operations medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1146
Problem TLDR
Distincts count after adding -k..k to each #medium
Intuition
Sort. There is a window we can take from duplicates: -k, -k+1, …, k-1, k. Slide from the left, greedily apply lowest possible change to the number. Update max of used values.
Approach
- don’t stop when current value is out of range, the next can be bigger
Complexity
-
Time complexity: \(O(nlog(n))\)
-
Space complexity: \(O(1)\)
Code
// 515ms
fun maxDistinctElements(n: IntArray, k: Int): Int {
var m = Int.MIN_VALUE; n.sort()
return n.count { val r = m < it + k; if (m < it+k) m = max(m+1,it-k); r }
}
// 20ms
pub fn max_distinct_elements(n: Vec<i32>, k: i32) -> i32 {
let mut m = i32::MIN;
n.iter().sorted().filter(|&x| { let r = m < x+k; if (r) { m = (m+1).max(x-k)}; r }).count() as _
}
17.10.2025
3003. Maximize the Number of Partitions After Operations medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1145
Problem TLDR
Max k-uniq parts after changing one letter #hard #prefix
Intuition
Didn’t solve.
// accca k=2
// 12222
// abcca
// 123 cca
// acbca
// 123 bca bc a
// accba
// 1223 ba
// 47 minutes: my algo stuck in corner cases, looking for hints
// partition_start is not very obvious
// 56 minute: look for solution
Precompute suffix & prefix: parts count and uniqs count so far at i.
Heuristic to split into three parts: left and right parts are full and uniqs are not full.
Heuristic to not split: count uniqs is less than k, so letter should go to left or right.
Otherwise split once.
Approach
- prefix can be computed on the go
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 9ms
fun maxPartitionsAfterOperations(s: String, k: Int): Int {
val sf = Array(s.length) { IntArray(2) }
var msk = 0; var part = 0; var res = 0
for (i in s.lastIndex downTo 1) {
val bit = 1 shl (s[i]-'a'); msk = msk or bit
if (msk.countOneBits() > k) { part++; msk = bit }
sf[i-1][0] = part; sf[i-1][1] = msk
}
msk = 0; part = 0
for (i in 0..<s.lastIndex) {
val cntall = (msk or sf[i][1]).countOneBits()
res = max(res, part + sf[i][0] +
if (msk.countOneBits() == k && sf[i][1].countOneBits() == k && cntall < 26) 2
else if (min(cntall + 1, 26) <= k) 0 else 1)
val bit = 1 shl (s[i]-'a'); msk = msk or bit
if (msk.countOneBits() > k) { part++; msk = bit }
}
return res + 1
}
16.10.2025
2598. Smallest Missing Non-negative Integer After Operations medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1144
Problem TLDR
First positive number can’t be build by adding/subtracting value #medium #hashmap
Intuition
Iterate from zero and look for the reminder. Use it or stop.
Approach
- corner case: negatives
- we can use array size of
vas a frequency map
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 135ms
fun findSmallestInteger(n: IntArray, v: Int): Int {
val m = n.groupBy{ (it%v+v)%v }.mapValues{ it.value.size }.toMutableMap()
return (0..n.size).first { val c = m[it%v]?:0; m[it%v]=c-1; c < 1 }
}
// 0ms
pub fn find_smallest_integer(n: Vec<i32>, v: i32) -> i32 {
let mut f = vec![0; v as usize]; for &x in &n { f[((x%v+v)%v) as usize] += 1 }
(0..=n.len()).find(|x| { let c = f[x%v as usize]; f[x%v as usize] -= 1; c < 1 }).unwrap() as _
}
15.10.2025
3350. Adjacent Increasing Subarrays Detection II medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1143
Problem TLDR
Max k of adjucent increasing k-windows #medium #counting
Intuition
In a single iteration, count of increasing numbers. Drop on non-increasing. Compare with previous.
Approach
- can use
chunk_byandwindowsin Rust
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\), or O(n)
Code
// 870ms
fun maxIncreasingSubarrays(n: List<Int>): Int {
var a = 0; var b = 0; var p = 0
return n.maxOf { n ->
if (n > p) ++a else { b = a; a = 1 }
p = n; max(a/2, min(a, b))
}
}
// 26ms
pub fn max_increasing_subarrays(n: Vec<i32>) -> i32 {
once(0).chain(n.chunk_by(|a,b| a < b).map(|c| c.len() as i32)).collect::<Vec<_>>()
.windows(2).map(|c| c[0].min(c[1]).max(c[1]/2)).max().unwrap()
}
14.10.2025
3349. Adjacent Increasing Subarrays Detection I medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1142
Problem TLDR
Any increasing consequent windows size k #easy
Intuition
Just brute-force every index. O(1) memory solution: count increasings, keep previous and current, check
Approach
- corner case: single 2k increasing chunk
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\), can be O(1)
Code
// 379ms
fun hasIncreasingSubarrays(n: List<Int>, k: Int) = n.indices
.any { i -> fun List<Int>.g()=this==sorted()&&toSet().size==k;
n.slice(i..<min(n.size,i+k)).g() &&
n.slice(min(n.size-1,i+k)..<min(n.size,i+k+k)).g()
}
// 5ms
pub fn has_increasing_subarrays(n: Vec<i32>, k: i32) -> bool {
once(0).chain(n.chunk_by(|a,b| a < b).map(|c|c.len() as i32))
.collect::<Vec<_>>().windows(2).any(|c| c[0].min(c[1]).max(c[1]/2) >= k)
}
13.10.2025
2273. Find Resultant Array After Removing Anagrams medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1141
Problem TLDR
Dedup anagrams #easy
Intuition
Simulate the process. The islands of equal-by-anagram are not influence each other when split by non-equal word.
Approach
- going from left to right, take value if previous is not anagram to current
- check anagrams by: a) sorting b) comparing the frequency map
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 42ms
fun removeAnagrams(w: Array<String>) = w.take(1) + w.asList()
.zipWithNext().mapNotNull {(a,b) -> b.takeIf{a.groupBy{it}!=b.groupBy{it}}}
// 3ms
pub fn remove_anagrams(mut w: Vec<String>) -> Vec<String> {
w.dedup_by_key(|w| w.bytes().counts()); w
}
12.10.2025
3539. Find Sum of Array Product of Magical Sequences medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1140
Problem TLDR
Product of all good subsequences and permutations #hard #combinatorics
Intuition
// by looking at the constraints: full search may be possible
// take 30 indices out of 50 nums
// how to use sum(2^seq[i]) = k set bits
// set bits are the sum of 2^bit1 + 2^bit2 + 2^bit3, where 1,2,3 are the set bits
// 1..k..m..30
//
// after sequence is found, we should count permutations and multiply by product
// 0 1 2 3 4 5 k=2 m=2
// 2^0 + 2^1 = 1+2=3 = b011
// 2^0 + 2^2 = 1+4=5 = b101
// so it is just any-to-any permutations
// 0: 1 2 3 4 5
// 1: 0 2 3 4 5
// 2: 0 1 3 4 5
// 3: 0 1 2 4 5
// 4: 0 1 2 3 5
// 5: 0 1 2 3 4 5^5=25
// choose k from n
// no examples where k < m
// 0 1 2 3 4 5 k=2 m=3
// let's write brute-force to see the picture 2^50 too much
// 39 minute: brute-force works, TLE for n=50,m=30,k=20
// this can be about combinatorics, let's look for hint
// 1 dp?, the nums can't be split, so we have to look at m and k
// m=1,k=1: single bit, single index, powers of two 0 2 4 8 16 32
// m=2,k=1: single bit, two indices, choose two from previous
// m=2,k=2: two bits, two indices:
// 53 minute: ok, i looked at hints and decided to give up
// basically inline checkmagic and prod compute in the dfs or not
Approach
- maybe I should learn combinatorics
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 405ms
fun magicalSum(m: Int, k: Int, nums: IntArray): Int {
val dp = HashMap<Long, Long>(); val M = 1000000007L
fun fact(n: Long): Long = if (n == 0L) 1L else (fact(n-1L)*n)%M
fun pow(a:Long,x:Long):Long=if (x==1L)a else if(x==0L)1L else (pow(a*a%M,x/2)*pow(a,x and 1L))%M
val fc = LongArray(m + 1); fc[m] = pow(fact(1L* m), M-2); for (i in m-1 downTo 0) fc[i] = (fc[i+1] * (i+1))%M
fun nCr(n: Int, r: Int):Long = (((fact(1L*n) * fc[r]) % M) * fc[n-r])%M
fun f(mask: Long, m: Int, k: Int, i: Int): Long = dp.getOrPut(mask*1000000+m*10000+k*100+i) {
if (m == 0) return@getOrPut if (mask.countOneBits() == k) 1L else 0L
if (i == nums.size) return@getOrPut 0L
var res = 0L
for (c in 0..m) {
val perm = (nCr(m, c)*pow(1L*nums[i], 1L*c)) % M
val sp = f((mask+c)/2, m-c, k-((mask+c) and 1).toInt(), i+1)
res = (res + (perm * sp) % M)%M
}
res
}
return f(0, m, k, 0).toInt()
}
11.10.2025
3186. Maximum Total Damage With Spell Casting medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1139
Problem TLDR
Max sum of choosen values, skip v[i]+1+2-1-2 #medium #dp #sorting
Intuition
Thoughts process:
// 31 minute: greedy doesn't work
// 6 5 4 3
// 12 15 8 6
// * x x *
// x * x x
// x x * x
// * x x *
// * x x x x * skip up to 4 elements
// don't see greedy, try dp
// 53 minute TLE
- sort and deduplicate
- dp[i] is the result for suffix [i..]
- dp[i] = max(take, notTake)
- if take, find the next index of p[i]+2
Approach
- to find next index you can use TreeMap.higherEntry(p+2)
- solution from u/votrubac/: dp[i+1] is the result if dp[i] is taken; dp[i]=max(dp[..j]), p[j]+2 is less than p[i]
Complexity
-
Time complexity: \(O(nlog(n))\), solution uses TreeMap retrieval of
log(n). Sorting is nlog(n). -
Space complexity: \(O(n)\)
Code
// 813ms
fun maximumTotalDamage(p: IntArray): Long {
val pc = p.groupBy { it }.mapValues { it.value.size }
val pi = TreeMap<Int, Int>(); val dp = HashMap<Int,Long>()
val keys = pc.keys.sorted(); for (i in keys.indices) pi[keys[i]] = i
fun dfs(i: Int): Long = if (i==keys.size) 0L else dp.getOrPut(i) {
val p = keys[i]
max(1L*p*pc[p]!! + (pi.higherEntry(p+2)?.let { dfs(it.value)}?:0), dfs(i+1))
}
return dfs(0)
}
// 38ms
pub fn maximum_total_damage(mut p:Vec<i32>)->i64{
let (mut d, mut m) = (vec![(0,0)], 0);
p.iter().sorted().chunk_by(|&x|x).into_iter().map(|(&v, g)| {
while d.len() > 0 && d[0].1+2 < v as i64 { m = d.remove(0).0.max(m) }
d.push((v as i64 * g.count() as i64 + m, v as i64)); d[d.len()-1].0
}).max().unwrap()
}
10.10.2025
3147. Taking Maximum Energy From the Mystic Dungeon medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1138
Problem TLDR
Max k-distant suffix sum #medium #array
Intuition
Each k sums have stable positions. Track k sums, drop if negative.
Approach
- can be done in-place
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\) or O(1) with input mutation
Code
// 724ms
fun maximumEnergy(e: IntArray, k: Int) = (e.size-1 downTo 0)
.maxOf { e[it] += if (it+k < e.size) e[it+k] else 0; e[it] }
// 21ms
pub fn maximum_energy(mut e: Vec<i32>, k: i32) -> i32 {
let k = k as usize; for i in k..e.len() { e[i%k] = e[i] + 0.max(e[i%k]) }
*e[..k].iter().max().unwrap()
}
09.10.2025
3494. Find the Minimum Amount of Time to Brew Potions medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1137
Problem TLDR
Min total time to finish all skills[i]*mana[j], non-intersecting #medium #bs
Intuition
The order is preserved. Binary Search the start time for each potion. Check if all next times are bigger then previous.
Approach
- use Long.MAX_VALUE / 2 for right border of bs
- n^2 solution from lee: optimal start(mana) = max_i(finish[i+1]-mana * sum(skills[0..i]))
Complexity
-
Time complexity: \(O(n^2log(n))\)
-
Space complexity: \(O(n)\)
Code
// 1681ms
fun minTime(s: IntArray, m: IntArray): Long {
val ts = LongArray(s.size + 1)
for (p in m) {
var lo = ts[0]; var hi = Long.MAX_VALUE / 2
while (lo <= hi) {
val m = (lo + hi)/2; var curr = m
for (i in 1..<ts.size) {
if (curr < ts[i]) { curr = -1; break }
curr += s[i-1] * p
}
if (curr >= 0) hi = m - 1 else lo = m + 1
}
ts[0] = lo; for (i in 1..<ts.size) ts[i] = ts[i-1] + 1L * s[i-1] * p
}
return ts.last()
}
// 53ms
pub fn min_time(mut s: Vec<i32>, m: Vec<i32>) -> i64 {
for i in 1..s.len() { s[i] += s[i - 1] }; let mut p = 0i64;
(1..m.len()).map(|i|
(1..s.len()).fold(s[0] as i64 * m[i - 1] as i64, |min, j|
min.max(m[i-1] as i64 * s[j] as i64 - m[i] as i64 * s[j-1] as i64))
).sum::<i64>() + s[s.len()-1] as i64 * m[m.len()-1] as i64
}
08.10.2025
2300. Successful Pairs of Spells and Potions medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1136
Problem TLDR
Number of potions * spells[i] bigger than success #midium #bs #sort
Intuition
Sort potions. Binary search value spells[i] * potions[j] < success.
Approach
- or search for
success + spells - 1 / spellswithoud converting to double
Complexity
-
Time complexity: \(O(nlog(n))\)
-
Space complexity: \(O(n)\)
Code
// 105ms
fun successfulPairs(sp: IntArray, p: IntArray, s: Long) = run { p.sort()
sp.map { v -> 1 + p.size + p.asList().binarySearch{ if (1L*it*v < s) -1 else 1 }}}
// 17ms
pub fn successful_pairs(sp: Vec<i32>, mut p: Vec<i32>, s: i64) -> Vec<i32> {
p.sort_unstable(); let l = p.len() as i32;
sp.iter().map(|&v| l - p.partition_point(|&p| v as i64 * (p as i64) < s) as i32).collect()
}
07.10.2025
1488. Avoid Flood in The City medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1135
Problem TLDR
Replace zeros with numbers to avoid duplicates #medium #binary_search #greedy
Intuition
// 0 1 2 3 4 5 6 7 8 9 1011
// 1 2 0 0 3 4 0 0 3 4 1 2
// i - first filled, use zero at index 2
// 0 1 1 - corner case
// i -- can't use zero, because no zero before previous 1
// 0 0 0 0 0 0 2 1 2
// 0 0 0 0 0 0 2 0 0 1 2 1
// ^
// can i use any of these? - no
// 1 2 0 0 3 4 0 0 3 4 1 2
// * * i
// * * * * i i can use zeros between duplicates
// or, zero can be used for any element before it
//
// which one to choose? closest
// 1 2 0 0 2 1
// 1 2 0 2 0 1
// 1 0 2 0 2 1
// 1 2 0 1 0 2
// 1 0 2 0 1 2
// 0 1 1
// i zi = [0]
// i fi[1] = 1
// 0 1 2 3 4 5 6
// 1 0 2 3 0 1 2
// i . fi[1] = 0
// i . zi = [1]
// i . fi[2]=2
// i . fi[3]=3
// i . zi=[1,4]
// i prev=fi[1]=0, 4>1, res[4]=1, ok so this breaks 2
// closest is not optimal
// "smallest after"
- remember zero days
- when seeing a duplicate, pick the first zero after the previous duplicate instance
Approach
- use the BinarySearch or TreeSet .higher(x)
Complexity
-
Time complexity: \(O(nlog(n))\)
-
Space complexity: \(O(n)\)
Code
// 64ms
fun avoidFlood(r: IntArray): IntArray {
val zi = TreeSet<Int>(); val fi = HashMap<Int, Int>()
for ((i, l) in r.withIndex()) if (l > 0) {
if (fi[l] != null) r[zi.higher(fi[l]) ?: return intArrayOf()] = l
.also { zi -= zi.higher(fi[l]) }
fi[l] = i; r[i] = -1
} else { zi += i; r[i] = 1 }
return r
}
// 21ms
pub fn avoid_flood(mut r: Vec<i32>) -> Vec<i32> {
let (mut f, mut z) = (HashMap::new(), BTreeSet::new());
for i in 0..r.len() { let l = r[i];
if l == 0 { z.insert(i); r[i] = 1; continue }
if let Some(&j) = f.get(&l) {
let Some(&d) = z.range(j+1..).next() else { return vec![] };
r[d] = l; z.remove(&d); }
f.insert(l, i); r[i] = -1
} r
}
06.10.2025
778. Swim in Rising Water hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1134
Problem TLDR
Min time to swim to end, flooding every second #hard #bfs
Intuition
Iterate over time (0..50^2) and do BFS step while less than time. Or, just put time variable in a PriorityQueue.
Approach
- another way is the BinarySearch: check reachability in O(n^2), do log(n) search in time
- the simple 0-1 BFS didn’t work here: all times should be sorted
Complexity
-
Time complexity: \(O(nlog(n))\)
-
Space complexity: \(O(n)\)
Code
// 42ms
fun swimInWater(g: Array<IntArray>): Int {
val q = PriorityQueue<IntArray>(compareBy { it[0] })
var r = g[0][0]; q += intArrayOf(r,0,0); g[0][0] = -1
while (q.size > 0) {
val (t,y,x) = q.poll(); r = max(r,t); if (y==g.size-1&&x==g[0].size-1) break
for ((u,r) in listOf(0,1,0,-1,0).zipWithNext())
if (x+r in g[0].indices && y+u in g.indices && g[y+u][x+r]>=0)
{ q += intArrayOf(g[y+u][x+r],y+u,x+r); g[y+u][x+r] = -1 }
}; return r
}
// 0ms
pub fn swim_in_water(mut g: Vec<Vec<i32>>) -> i32 {
let (n,m,mut h) = (g.len(),g[0].len(), BinaryHeap::from([(-g[0][0],0,0)]));
g[0][0] = -1; let mut r = 0;
while let Some((t,y,x)) = h.pop() {
r = r.max(-t); if (y,x) == (n-1,m-1) { break }
for (u,r) in [(y-1,x),(y+1,x),(y,x-1),(y,x+1)] {
if u < n && r < m && g[u][r] >= 0 { h.push((-g[u][r],u,r)); g[u][r] = -1 }
}} r
}
05.10.2025
417. Pacific Atlantic Water Flow medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1133
Problem TLDR
Cells travel to TL&BR in decrease order #medium #dfs
Intuition
Think in reverse: travel from oceans in increase order and mark with 1 and 2. Collect both marks.
Approach
- you already can collect on a second DFS run
- the marking DFS can run in any order
- for BFS: put (y,x,mask) to queue, go from walls, same logic
Complexity
-
Time complexity: \(O()\)
-
Space complexity: \(O()\)
Code
// 31ms
fun pacificAtlantic(h: Array<IntArray>) = buildList<List<Int>> {
val v = Array(h.size) { IntArray(h[0].size) }
fun dfs(y: Int, x: Int, m: Int) {
if (v[y][x] and m > 0) return; v[y][x] = v[y][x] or m
if (v[y][x] > 2) add(listOf(y, x))
for ((r,u) in listOf(-1,0,1,0,-1).zipWithNext())
if (x+r in h[0].indices && y+u in h.indices && h[y+u][x+r]>=h[y][x]) dfs(y+u,x+r,m)
}
for (y in h.indices) { dfs(y, 0, 1); dfs(y, h[0].size-1, 2) }
for (x in h[0].indices) { dfs(0, x, 1); dfs(h.size-1, x, 2) }
}
// 0ms
pub fn pacific_atlantic(h: Vec<Vec<i32>>) -> Vec<Vec<i32>> {
let (m,n) = (h.len(),h[0].len()); let mut q = Vec::with_capacity(m*n);
let (mut v,mut res) = (vec![0u8;m*n],vec![]);
for i in 0..m { q.push((i,0,1)); q.push((i,n-1,2)) }
for i in 0..n { q.push((0,i,1)); q.push((m-1,i,2)) }
while let Some((y,x,b)) = q.pop() {
if v[y*n+x]&b<1 { v[y*n+x] |= b; if v[y*n+x]>2 { res.push(vec![y as i32,x as i32]) }
for (u,r) in [(y-1,x),(y+1,x),(y,x-1),(y,x+1)] {
if u<m && r<n && h[u][r] >= h[y][x] { q.push((u,r,b)) }
}}} res
}
04.10.2025
11. Container With Most Water medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1132
Problem TLDR
Max water container from two heights #medium #two-pointers
Intuition
Start with two pointer at max distance. Decrease distance by 1 by moving the lower height pointer. The length only decreases, so drop the lower height, it will not be better than the current.
Approach
- if heights are equal move any pointer or both (to change minimum)
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 38ms
fun maxArea(h: IntArray) =
(h.lastIndex downTo 0).fold(0 to 0) { (r,i), l ->
max(r,l*min(h[i],h[i+l])) to if (h[i]<h[i+l]) i+1 else i
}.first
// 1ms
pub fn max_area(h: Vec<i32>) -> i32 {
(0..h.len()).rev().fold((0,0),|(r,i),l|
(r.max(l as i32*h[i].min(h[i+l])),i+((h[i]<h[i+l])as usize))).0
}
03.10.2025
407. Trapping Rain Water II hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1131
Problem TLDR
Fill water in 3D #hard #dfs #sorting
Intuition
I solved it not optimally in 50 minutes O(n^2) (accepted).
Go layer-by-layer, DFS in each layer and find the min value of greater cells.
The optimal solution: go layer-by-layer, advance just single step, put back into queue with new height value min(lvl, next).
Approach
- use priority_queue
- use visited set or modify the grid
Complexity
-
Time complexity: \(O(n^2)\) or O(nlog(n))
-
Space complexity: \(O(n)\)
Code
// 1968ms
fun trapRainWater(h: Array<IntArray>): Int {
val w = h[0].size;
val q = PriorityQueue<Int>(compareBy{h[it/w][it%w]}); q += (0..<w*h.size)
var lvl = 0; var res = 0; var curr = 0; val visited = HashSet<Int>()
while (q.size > 0) {
val yx = q.poll(); val (y, x) = yx/w to yx%w; val clvl = h[y][x]
if (clvl > lvl) { res += curr; curr = 0; lvl = clvl; visited.clear() }
var min = Int.MAX_VALUE
fun dfs(y: Int, x: Int): Int {
if (y<0||x<0||y>h.size-1||x>w-1) { min = 0; return@dfs 0 }
if (h[y][x] > clvl) {min = min(min, h[y][x]);return@dfs 0}
if (!visited.add(y*w+x)) return@dfs 0
return@dfs 1 + dfs(y-1,x) + dfs(y+1,x) + dfs(y,x-1) + dfs(y,x+1)
}
curr += max(0, dfs(y,x)*(min-clvl))
}
return res
}
// 7ms
pub fn trap_rain_water(mut height_map: Vec<Vec<i32>>) -> i32 {
let (m, n, mut r) = (height_map.len(), height_map[0].len(), 0);
let mut q = BinaryHeap::new();
for y in 0..m { for x in 0..n { if (y.min(x) < 1 || y == m - 1 || x == n - 1) {
q.push((-height_map[y][x], y, x)) }}}
while let Some((min, y, x)) = q.pop() {
height_map[y][x] = -1; let min = -min;
for (y1, x1) in [(y, x - 1), (y - 1, x), (y, x + 1), (y + 1, x)] {
if (0..m).contains(&y1) && (0..n).contains(&x1) && height_map[y1][x1] >= 0 {
q.push((-min.max(height_map[y1][x1]), y1, x1));
r += 0.max(min - height_map[y1][x1]); height_map[y1][x1] = -1
}}
}; r
}
02.10.2025
3100. Water Bottles II medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1130
Problem TLDR
Total drinks with growing exchange rate empty for full #medium #simulation
Intuition
Simulate the process. Don’t forget to keep lefover empty bottles.
Approach
- there is a O(1) math solution exists
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 103ms
fun maxBottlesDrunk(b: Int, x: Int, e: Int = 0): Int =
b + if (b+e<x) 0 else maxBottlesDrunk(1,x+1,b+e-x)
// 3ms
pub fn max_bottles_drunk(mut b: i32, mut x: i32) -> i32 {
let (mut e, mut d) = (0, 0);
while b > 0 || e >= x {
d += b; e += b; b = if (e < x) {0} else {e-=x;x+=1;1};
} d
}
01.10.2025
1518. Water Bottles easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1129
Problem TLDR
Total drinks with exchange empty for full #easy #simulation
Intuition
Simulate the process. Don’t forget to keep lefover empty bottles.
Approach
- the single math formula can be derived from:
s = b + b/x + (b/x+b%x)/x + ((b/x+b%x)/x+(b/x+b%x)%x)/x... - or
s = b*(1 + 1/x + 1/x^2 + 1/x^3 + ...), geometric series converges to1/(1-r)wherer=1/x - so
s = b*(1/(1-1/x)) = b/(1-1/x) = b*x/(x-1)(ask chatgpt why it is (b*x-1) instead)
Complexity
-
Time complexity: \(O(1)\)
-
Space complexity: \(O(1)\)
Code
// 0ms
fun numWaterBottles(b: Int, x: Int, e: Int = 0): Int =
b + if (b < 1) 0 else numWaterBottles((b+e)/x, x, (b+e)%x)
// 0ms
pub fn num_water_bottles(b: i32, x: i32) -> i32 {
(b*x-1)/(x-1)
}
30.09.2025
2221. Find Triangular Sum of an Array medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1128
Problem TLDR
Triangle sum % 10 #medium #simulation
Intuition
The problem is small 1000, O(n^2) simulation is accepted.
The O(n) intuition (from Stefan Pochmann):
- each position get repeated Pascal’s Triangle times
1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 1 6 15 20 15 6 1Each new row value is a binomial coefficient (https://en.wikipedia.org/wiki/Binomial_coefficient)
mC(k+1) = mCk *(n-1-k)/(k+1)Division by/(k+1)can’t be safely done with%10.
Approach
- windows.map = zipWithNext
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n)\)
Code
// 226ms
fun triangularSum(n: IntArray) = (2..n.size)
.fold(n.asList()){r,_->r.zipWithNext{a,b->(a+b)%10}}[0]
fun triangularSum(n: IntArray): Int {
var f = 1.toBigInteger()
var r = 0.toBigInteger()
for ((i, x) in n.withIndex()) {
r = (r + f * x.toBigInteger()).mod(10.toBigInteger())
f = f * (n.size - 1 - i).toBigInteger() / (i + 1).toBigInteger()
}
return r.toInt()
}
// 27ms
pub fn triangular_sum(n: Vec<i32>) -> i32 {
(1..n.len()).fold(n,|r,t|r.into_iter().tuple_windows().map(|(a,b)|(a+b)%10).collect())[0]
}
29.09.2025
1039. Minimum Score Triangulation of Polygon medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1127
Problem TLDR
Min sum of triangle product for every possible triangulation #medium #dp
Intuition
Used the hint.
How to triangulate: keep first and last vertice, try every possible third between them.
Memorize for every possible from and to.
// 3745
//
// 3 7
//
//
// 5 4
//
// 375+457 or 345+347
//
// 1 3 1 4 1 5
//
// 1 3
// 1
//
// 4
// 5 1
//
// 113 114 115 111
//
// how to triangulate? can't do 111+345
// maybe recursive? (is it 50^50?)
// 1 3 1 4 1 5
// 1 3 1 + 1 1 4 1 5
// 29 minute: every time we have a ring, just choose the top 2 and split at them
// but what if they are consequtive?
//
// 0 1 2 3 4 5 6
// * *
// 43 minute (solved for max instead of min)
// 45 minute (the two vertex algo is not optimal)
// should we peek 3 vertices?
// 51 minute: wrong answer 2144
//
// 2 1
//
// 4 4
// looks like just picking min values is not enough
// 54 minute take hints: just a single split?
// 76 minute TLE (with dp?) [5,80,62,45,96,100,17,72,67,64,20,66,41,68,34,67,35,24,76,2]
// ^ language syntax error
Approach
- the hardest part is to find a clever triangulation technique
Complexity
-
Time complexity: \(O(n^3)\)
-
Space complexity: \(O(n^2)\)
Code
// 58ms
fun minScoreTriangulation(v: IntArray): Int {
val l = v.asList(); val dp = HashMap<Pair<Int, Int>, Int>()
fun d(from: Int, to: Int): Int = if (to-from+1 < 3) 0 else dp.getOrPut(from to to)
{ (from+1..<to).minOf { l[it]*l[from]*l[to] + d(from, it) + d(it, to) } }
return d(0, v.lastIndex)
}
// 0ms
pub fn min_score_triangulation(v: Vec<i32>) -> i32 {
let mut d = [[0;50];50];
for i in (0..v.len()).rev() { for j in (i+1..v.len()) { for k in (i+1..j) {
d[i][j]=(d[i][k]+d[k][j]+v[i]*v[j]*v[k]).min(if d[i][j]==0 {i32::MAX}else {d[i][j]})
}}}; d[0][v.len()-1]
}
28.09.2025
976. Largest Perimeter Triangle easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1126
Problem TLDR
Max triangle perimeter from array of lengths #easy #sliding_window
Intuition
Sort. Consider every 3-sliding window from biggest: when a+b <= c move next, discard the c, otherwise finish.
When c is bigger than closes a+b, then it will be bigger than any other pair sum.
Approach
- this is not an easy problem
Complexity
-
Time complexity: \(O(nlog(n))\)
-
Space complexity: \(O(n)\) or O(1)
Code
// 81ms
fun largestPerimeter(n: IntArray) =
max(0, n.sorted().windowed(3)
.maxOf{(a,b,c) -> (a+b+c)*(a+b).compareTo(c)})
// 0ms
pub fn largest_perimeter(n: Vec<i32>) -> i32 {
n.iter().sorted_by_key(|&x|-x).tuple_windows()
.find(|&(c,b,a)| a+b>*c).map_or(0, |(a,b,c)| a+b+c)
}
27.09.2025
812. Largest Triangle Area easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1125
Problem TLDR
Max area triangle #easy
Intuition
Brute-force & Google for formula.
Approach
- max are triangle lies on a convex-hull
Complexity
-
Time complexity: \(O(n^2log(n))\) or n^2
-
Space complexity: \(O(1)\)
Code
// 31ms
fun largestTriangleArea(p: Array<IntArray>) =
p.maxOf {(x1,y1)-> p.maxOf{(x2,y2)-> p.maxOf{(x3,y3) ->
abs((x2-x1)*(y3-y1)-(x3-x1)*(y2-y1)) }}} * 0.5
// 3ms
pub fn largest_triangle_area(p: Vec<Vec<i32>>) -> f64 {
let mut r = 0f64;
for p1 in &p { for p2 in &p { for p3 in &p {
r = r.max(((p2[0]-p1[0])*(p3[1]-p1[1])-(p3[0]-p1[0])*(p2[1]-p1[1])).abs()as f64)
}}}; r * 0.5
}
26.09.2025
611. Valid Triangle Number medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1124
Problem TLDR
Count triangles can be made from numbers #medium #binary_search #two_sum
Intuition
Sort. Binary Search: for every pair of numbers a and b search for c in [b-a..b+a] Two Sum: same idea, but left border is always goes forward, so we can do increament instead of bs
Approach
- for the BinarySearch upper bound is already less than a+b, the range is [0..a]
Complexity
-
Time complexity: \(O(n^2log(n))\) or n^2
-
Space complexity: \(O(1)\)
Code
// 113ms
fun triangleNumber(n: IntArray): Int {
n.sort()
return (2..<n.size).sumOf { i ->
(1..<i).sumOf { j ->
var lo = 0; var hi = j-1
while (lo <= hi) {
val m = (lo + hi) / 2
if (n[m] > n[i]-n[j]) hi = m - 1 else lo = m + 1
}
j - lo
}
}
}
// 44ms
fun triangleNumber(n: IntArray): Int {
n.sort()
return (2..<n.size).sumOf { i ->
var l = 0; var r = i-1; var c = 0
while (l < r) if (n[l] + n[r] > n[i]) c += r-- -l else ++l
c
}
}
// 18ms
pub fn triangle_number(mut n: Vec<i32>) -> i32 {
n.sort_unstable();
(2..n.len()).map(|i| {
let (mut l, mut r, mut c) = (0, i-1, 0);
while l < r { if n[l]+n[r] > n[i] { c += r-l; r-=1} else { l+=1}}
c as i32
}).sum()
}
25.09.2025
120. Triangle medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1123
Problem TLDR
Min path sum in triangle #medium #dp
Intuition
Go from top to bottom, keeping the previous result: curr[i] = t[j][i] + min(prev[i], prev[i-1])
Approach
- careful with out of bounds exceptions
- use Int.MAX_VALUE / 200
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 19ms
fun minimumTotal(t: List<List<Int>>) = t.drop(1)
.fold(t[0]) { p,t -> listOf(p[0] + t[0]) + (1..<t.size)
.map { i-> t[i]+min(p[min(i, p.size-1)],p[i-1])}}.min()
// 0ms
pub fn minimum_total(t: Vec<Vec<i32>>) -> i32 {
t.iter().skip(1).fold(vec![t[0][0]], |p, r| { once(p[0]+r[0])
.chain((1..r.len()).map(|i| r[i]+p[i.min(p.len()-1)].min(p[i-1]))).collect()
}).into_iter().min().unwrap()
}
24.09.2025
166. Fraction to Recurring Decimal medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1122
Problem TLDR
Calc a/b to string x.y(z) #medium #math
Intuition
Gave up to implement this correctly.
// how to know it is repeating?
// let's just brute-force 10^4 digits
// ok, how to find repeats? kmp (i forgot it)?
// just store visited "(a/b)"
// ok 43 minute, looks for hints, any simpler ideas? (no)
// decide to give up, no time for debugging this
The ideas:
- to divide 1/3 multiply 1*10, and repeat the problem for 1%3 / 3
- to find the repeating part remember the problem “1/3” or just “1”
- to find where the repeating part start, remember the positions for each key “1”
- solve the part before “.” before going next
Approach
- abs(Int.MIN_VALUE) == Int.MIN_VALUE, convert to longs before
abs
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 2ms
fun fractionToDecimal(n: Int, d: Int) = buildString {
if (1L * n.sign * d.sign < 0) append("-")
var n = abs(1L*n); val d = abs(1L*d)
append(n / d); n %= d; if (n > 0L) append(".")
val visited = HashMap<Long, Int>()
while (n > 0L) {
n *= 10; append(n / d); n %= d
visited.put(n, length)?.let {
insert(it, "("); append(")"); n = 0L
}
}
}
// 0ms
pub fn fraction_to_decimal(n: i32, d: i32) -> String {
let (n, d, mut s) = (n as i64, d as i64, String::new());
if n * d < 0 { s.push('-') }; let (n, d) = (n.abs(), d.abs());
s.push_str(&(n/d).to_string()); let mut n = n % d; if n > 0 {s.push('.')};
let mut m = HashMap::new();
while n > 0 {
if let Some(&i) = m.get(&n) { s.insert(i, '('); s.push(')'); break }
m.insert(n, s.len()); n *= 10; s.push_str(&(n/d).to_string()); n %= d
} s
}
23.09.2025
165. Compare Version Numbers medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1121
Problem TLDR
Compare versions x.x.x.x #medium
Intuition
Pad start strings or convert to ints.
Approach
- 25 characters for pad start
- pad lists of numbers length to the largest
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 23ms
fun compareVersion(v1: String, v2: String) = listOf(v1, v2)
.map { it.split('.').map {it.toInt()}}
.let { (a, b) -> val d = List(abs(a.size - b.size)){0}; (a+d).zip(b+d)}
.map { (a, b) -> a.compareTo(b) }.firstOrNull { it != 0 } ?: 0
// 0ms
pub fn compare_version(v: String, w: String) -> i32 {
v.split('.').zip_longest(w.split('.')).map(|e|e.or("0","0"))
.map(|(l,r)|l.parse::<i32>().unwrap().cmp(&r.parse::<i32>().unwrap()) as i32)
.find(|&x| x != 0).unwrap_or(0)
}
22.09.2025
3005. Count Elements With Maximum Frequency easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1120
Problem TLDR
Count max-freq elements #easy #counting
Intuition
Maintain frequency map. Count on-line or in the second iteration.
Approach
- for n=100 brute force is accepted
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n)\)
Code
// 13ms
fun maxFrequencyElements(n: IntArray) =
n.groupBy{it}.values.map{it.size}.run {max()*count{it==max()}}
// 1ms
fun maxFrequencyElements(n: IntArray): Int {
var res = 0; var maxF = 0; val f = IntArray(101)
for (x in n) if (++f[x] > maxF) { maxF = f[x]; res = 1 }
else if (f[x] == maxF) ++res;
return res * maxF
}
// 0ms
pub fn max_frequency_elements(mut n: Vec<i32>) -> i32 {
n.sort_unstable(); n.chunk_by(|a, b| a == b)
.fold((0, 0, 0), |r, c| if c.len() > r.0 { (c.len(), 1, c.len())}
else if c.len() == r.0 { (r.0, r.1 + 1, r.0 * (r.1+1))} else { r }).2 as _
}
21.09.2025
1912. Design Movie Rental System medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1119
Problem TLDR
Design Movie Rent: rent,drop,search(5 lowest), report(5 lowest rented) #hard #ds
Intuition
| To search by movie use a HashMap movie-TreeSet(price | shop). | |
| To report 5 lowest rented use a TreeSet<(price | shop | movie)>. |
Approach
- TreeSet uses comparator to check uniqness, add movie to the key
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(n)\)
Code
// 608ms
class MovieRentingSystem(n: Int, e: Array<IntArray>):
TreeSet<IntArray>(compareBy({it[2]},{it[0]},{it[1]})) {
val smp = e.groupBy {it[0]}.mapValues{(_,v) -> v.associate {it[1] to it}}
val mps = e.groupBy {it[1]}.mapValues{(_,v) -> TreeSet(comparator()).also{it+=v}}
fun search(m: Int) = mps[m]?.take(5)?.map {it[0]} ?: listOf()
fun rent(s: Int, m: Int) = smp[s]!![m]!!.let {this += it; mps[m]!! -= it}
fun drop(s: Int, m: Int) = smp[s]!![m]!!.let {this -= it; mps[m]!! += it}
fun report() = take(5).map {it.take(2)}
}
// 99ms
type PSM = (i32,i32,i32); #[derive(Default)]
struct MovieRentingSystem(BTreeSet<PSM>,HashMap<i32,HashMap<i32,PSM>>,HashMap<i32,BTreeSet<PSM>>);
impl MovieRentingSystem {
fn new(_: i32, e: Vec<Vec<i32>>) -> Self {
let mut s = Self::default(); for v in e { let t=(v[2],v[0],v[1]);
s.1.entry(v[0]).or_default().insert(v[1],t); s.2.entry(v[1]).or_default().insert(t);}; s }
fn search(&self, m: i32)->Vec<i32>{self.2.get(&m).iter().flat_map(|s|s.iter().take(5).map(|t|t.1)).collect() }
fn rent(&mut self, s: i32, m: i32){let t=self.1[&s][&m];self.0.insert(t);self.2.get_mut(&m).unwrap().remove(&t);}
fn drop(&mut self, s: i32, m: i32){let t=self.1[&s][&m];self.0.remove(&t);self.2.get_mut(&m).unwrap().insert(t);}
fn report(&self) -> Vec<Vec<i32>> {self.0.iter().take(5).map(|t|vec![t.1,t.2]).collect()}
}
20.09.2025
3508. Implement Router medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1118
Problem TLDR
Design Router: addPacket, forwardPacket, getCount(dst, ts start..end) #medium #ds
Intuition
The main difficulty is the getCount, we have to maintain some sorted order of timestamps, but there are duplicates.
- use map
dst to sorted timestampsfor getCount; do binarysearch - use
LinkedListorArrayDequeorIntArray(limit)for FIFO adding/removal - use
HashSetto skip duplicates
Approach
- remember binary search: always check
lo <= hi, always dohi=m-1 or lo=m+1, update value if in condition - skip the second binary search if the first gives out of range idx
- when removing
forwardPacketfrombyDstlist we always remove the first (it is theoretically O(n) call, but there is no testcase for this; to improve have to track pointer to first and do garbage collection)
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(n)\)
Code
// 291ms
class Router(val limit: Int) : LinkedHashSet<List<Int>>() {
val byDst = HashMap<Int, ArrayList<Int>>()
fun addPacket(src: Int, dst: Int, ts: Int) =
add(listOf(src,dst,ts)) && { if (size > limit) forwardPacket()
byDst.getOrPut(dst) { ArrayList() } += ts; true }()
fun forwardPacket() = firstOrNull()?.also {
this -= it; byDst[it[1]]?.removeFirst()
}?.toIntArray() ?: intArrayOf()
fun getCount(dst: Int, st: Int, et: Int) = byDst[dst]?.run {
binarySearch { if (it < st) -1 else 1 } -
binarySearch { if (it <= et) -1 else 1 } } ?: 0
}
// 76ms
#[derive(Default)] struct Router(i32, VecDeque<[i32;3]>,HashMap<i32,Vec<i32>>,HashSet<[i32;3]>);
impl Router {
fn new(l: i32) -> Self { let mut s = Self::default(); s.0 = l; s }
fn add_packet(&mut self, s: i32, d: i32, t: i32) -> bool {
let k = [s,d,t]; self.3.insert(k) && {
self.1.push_back(k); self.2.entry(d).or_default().push(t);
if self.1.len() as i32 > self.0 { self.forward_packet(); } true }
}
fn forward_packet(&mut self) -> Vec<i32> {
self.1.pop_front().map(|k|{
self.3.remove(&k); self.2.get_mut(&k[1]).map(|v|v.remove(0)); k.into()
}).unwrap_or_default()
}
fn get_count(&self, d: i32, s: i32, e: i32) -> i32 {
self.2.get(&d).map_or(0, |v|v.partition_point(|&x|x<=e)-v.partition_point(|&x|x<s)) as _
}
}
19.09.2025
3484. Design Spreadsheet medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1117
Problem TLDR
Design Spreadsheet: setCell, resetCell, getValue(a+b) #medium #ds
Intuition
Rows count is small 1000, we can store all in two-dimensional array. Formula are just a single shot, without going recursive.
Approach
- using a HashMap saves LOC and string parsing
- single array:
key = (c[0]-'A') * rows + c[1..].toInt()
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 205ms
class Spreadsheet(rows: Int) : HashMap<String, Int>() {
fun setCell(c: String, v: Int) = put(c, v)
fun resetCell(c: String) = put(c, 0)
fun getValue(f: String) = f.drop(1).split("+")
.sumOf { if (it[0].isDigit()) it.toInt() else get(it) ?: 0 }
}
// 30ms
struct Spreadsheet([i32;26001]); impl Spreadsheet {
fn new(_: i32) -> Self { Spreadsheet([0;26001]) }
fn k(&self, c: &str) -> usize { let b = c.as_bytes();
(b[0]-b’A’)as usize*1000+c[1..].parse::
# 18.09.2025
[3408. Design Task Manager](https://leetcode.com/problems/design-task-manager/description) medium
[blog post](https://leetcode.com/problems/design-task-manager/solutions/7201935/kotlin-rust-by-samoylenkodmitry-5a7v/)
[substack](https://open.substack.com/pub/dmitriisamoilenko/p/18092025-3408-design-task-manager?r=2bam17&utm_campaign=post&utm_medium=web&showWelcomeOnShare=true)
[youtube](https://youtu.be/HdtbT_rT1v0)

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
#### Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1116
#### Problem TLDR
Design Scheduler: add, edit, remove, execute by priority #medium #ds
#### Intuition
Use TreeMap + TreeSet
#### Approach
* we can use a single key mask for priority `p * 10^5 + tid`
* lazy removal seems to speed up; didn't implemented it here
#### Complexity
- Time complexity:
$$O(nlogn)$$
- Space complexity:
$$O(n)$$
#### Code
```kotlin
// 358ms
class TaskManager(tasks: List<List<Int>>): TreeMap<Long, Int>() {
val tp = HashMap<Int, Int>()
init { for ((uid, tid, p) in tasks) add(uid, tid, p) }
fun add(uid: Int, tid: Int, p: Int) { put(key(p, tid), uid); tp[tid] = p }
fun key(p: Int, tid: Int): Long = 1L * p * 100_000 + tid
fun key(tid: Int): Long = key(tp[tid]!!, tid)
fun edit(tid: Int, p: Int) = add(rmv(tid), tid, p)
fun rmv(tid: Int) = remove(key(tid)) ?: -1
fun execTop(): Int = pollLastEntry()?.value ?: -1
}
// 118ms
#[derive(Default)] struct TaskManager(BTreeMap<(i32, i32), i32>, HashMap<i32, i32>);
impl TaskManager {
fn new(v: Vec<Vec<i32>>) -> Self {
let mut m = Self::default();
for a in v { m.add(a[0], a[1], a[2]) }; m
}
fn add(&mut self, u: i32, i: i32, p: i32)
{ self.0.insert((p, i), u); self.1.insert(i, p); }
fn edit(&mut self, i: i32, p: i32) { let u = self.rmv(i); self.add(u, i, p) }
fn rmv(&mut self, i: i32) -> i32 {
let k = (self.1[&i], i); self.1.remove(&i); self.0.remove(&k).unwrap_or(-1)
}
fn exec_top(&mut self) -> i32 { self.0.pop_last().map(|(_, v)| v).unwrap_or(-1) }
}
17.09.2025
2353. Design a Food Rating System medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1115
Problem TLDR
Food rating system: change rating, peek highest by type #medium #ds
Intuition
Make TreeSet buckets for each cuisine.
Approach
- don’t modify the rating while item in the
TreeSet
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(n)\)
Code
// 340ms
class FoodRatings(val foods: Array<String>, val cuisines: Array<String>, val ratings: IntArray) {
val foodToIdx = foods.indices.associate { foods[it] to it }
val csToIdx = foods.indices.groupBy { cuisines[it] }.mapValues { (k, v) ->
val q = TreeSet<Int>(compareBy({-ratings[it]}, {foods[it]})); q += v; q }
fun changeRating(food: String, newRating: Int) {
val i = foodToIdx[food]!!; val q = csToIdx[cuisines[i]]!!
q -= i; ratings[i] = newRating; q += i
}
fun highestRated(cuisine: String) = foods[csToIdx[cuisine]!!.first()]
}
// 56ms
#[derive(Default)] struct FoodRatings(Vec<String>, Vec<String>, Vec<i32>, HashMap<String, usize>, HashMap<String, BTreeSet<(i32, String)>>);
impl FoodRatings {
fn new(f: Vec<String>, c: Vec<String>, r: Vec<i32>) -> Self {
let fi: HashMap<_,_> = (0..f.len()).map(|i| (f[i].clone(), i)).collect();
let mut ct = HashMap::new();
for i in 0..f.len() { ct.entry(c[i].clone()).or_insert(BTreeSet::new()).insert((-r[i],f[i].clone())); }
Self(f, c, r, fi, ct)
}
fn change_rating(&mut self, f: String, v: i32) {
let i = self.3[&f]; let c = &self.1[i];
self.4.get_mut(c).unwrap().remove(&(-self.2[i],self.0[i].clone())); self.2[i] = v;
self.4.get_mut(c).unwrap().insert((-v,self.0[i].clone()));
}
fn highest_rated(&self, c: String) -> String { self.4[&c].iter().next().unwrap().1.clone() }
}
16.09.2025
2197. Replace Non-Coprime Numbers in Array hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1114
Problem TLDR
Simulate gcd to lcm adjacent pair removal #hard #simulation
Intuition
Solved with the hint: only update values to the left.
As all the ways lead to the same result, that means we can pick the more comfortable way: just scan from the left to the right.
GCD(a, b) = (b, a%b) LCM(a, b) = a*b/GCD(a,b)
Approach
- careful with int overflow
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 64ms
fun replaceNonCoprimes(nums: IntArray) = buildList {
fun gcd(a: Int, b: Int): Int = if (a % b == 0) b else gcd(b, a % b)
fun lcm(a: Int, b: Int): Int = ((1L * a * b) / gcd(a, b)).toInt()
for (x in nums) {
this += x
while (size > 1 && gcd(last(), this[size-2]) > 1)
this += lcm(removeLast(), removeLast())
}
}
// 18ms
pub fn replace_non_coprimes(nums: Vec<i32>) -> Vec<i32> {
fn gcd(a: i32, b: i32) -> i32 { if a%b > 0 { gcd(b, a%b)} else { b }};
let lcm = |a: i32, b: i32| (a as i64 * b as i64/ gcd(a, b) as i64) as i32;
let mut res = vec![];
for x in nums { res.push(x); while res.len() > 1 && gcd(res[res.len()-1], res[res.len()-2]) > 1 {
let (a, b) = (res.pop().unwrap(), res.pop().unwrap()); res.push(lcm(a, b))
}} res
}
15.09.2025
1935. Maximum Number of Words You Can Type easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1113
Problem TLDR
Count words with all letters #easy
Intuition
No special algo here. Broken letters is up to 26, no hashset needed.
Approach
- write a one-liner
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 14ms
fun canBeTypedWords(txt: String, bl: String) =
txt.split(" ").count { it.all { it !in bl}}
// 0ms
pub fn can_be_typed_words(txt: String, bl: String) -> i32 {
txt.split(" ").filter(|w| !w.chars().any(|c| bl.contains(c))).count() as _
}
14.09.2025
966. Vowel Spellchecker medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1112
Problem TLDR
Spellcheck with priority: original, case, vowels #medium #regex
Intuition
Understand the priority:
- Exact match
- Ignore-case match
- Vowel-as-wildcard match
Approach
- do full-search for vowels (7 symbols max, 5 wovels = 7^5) or precompute a wildcards
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 73ms
fun spellchecker(wl: Array<String>, q: Array<String>): List<String> {
val orig = wl.groupBy { it }; val lower = wl.groupBy { it.lowercase() }
val vowel = wl.groupBy { Regex("[eiou]").replace(it.lowercase(), "a")}
return q.map { q ->
orig[q]?.first() ?: lower[q.lowercase()]?.first() ?:
vowel[Regex("[eiou]").replace(q.lowercase(), "a")]?.first() ?: ""
}
}
// 13ms
pub fn spellchecker(w: Vec<String>, q: Vec<String>) -> Vec<String> {
use itertools::Itertools;
let exact: HashMap<_,_> = w.iter().map(|s| (s.as_str(), s.as_str())).collect();
let lower: HashMap<_,_> = w.iter().rev().map(|s| (s.to_lowercase(), s.as_str())).collect();
let vowel: HashMap<_,_> = w.iter().rev().map(|s| (s.to_lowercase().replace(|c|"eiou".contains(c),"a"), s.as_str())).collect();
q.iter().map(|s| {
exact.get(s.as_str()).copied()
.or(lower.get(&s.to_lowercase()).copied())
.or(vowel.get(&s.to_lowercase().replace(|c|"eiou".contains(c),"a")).copied())
.unwrap_or("").into()
}).collect()
}
13.09.2025
3541. Find Most Frequent Vowel and Consonant easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1111
Problem TLDR
Max freq vowels + consonants #easy
Intuition
Make a frequency array, then find max of vowel and max of consonant.
Approach
- can we do a one-liner?
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 27ms
fun maxFreqSum(s: String) = s.partition { it in "aeiou" }.toList()
.sumOf { it.groupBy { it }.maxOfOrNull { it.value.size } ?: 0 }
12.09.2025
3227. Vowels Game in a String medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1110
Problem TLDR
Can Alice win Bob both removeing odd-even vowel count substring optimally #medium
Intuition
Naive dp: at every position i check every position j=i..n if the tail is loosing.
Optimization trick: check in reverse j=n..i to end game faster
Approach
- the final solution is that Alice always wins: odd on the first move, even - on the third
Complexity
-
Time complexity: \(O(n^2)\), or O(n)
-
Space complexity: \(O(n)\), or O(1)
Code
// 16ms
fun doesAliceWin(s: String) =
"[aeiou]".toRegex() in s
// 33ms
fun doesAliceWin(s: String): Boolean {
val f = IntArray(s.length)
for ((i, c) in s.withIndex()) f[i] = f[max(0, i-1)] + if (c in "aeiou") 1 else 0
val dp = HashMap<Pair<Int, Boolean>, Boolean>()
fun dfs(i: Int, odd: Boolean): Boolean =
i < s.length && dp.getOrPut(i to odd) {
for (j in s.length-1 downTo i) {
var cnt = f[j] - (if (i > 0) f[i-1] else 0)
if (odd == (cnt % 2 > 0))
if (!dfs(j+1, !odd)) return@getOrPut true
}
false
}
return dfs(0, true)
}
// 3ms
pub fn does_alice_win(s: String) -> bool {
s.chars().any(|c| "aeiou".contains(c))
}
11.09.2025
2785. Sort Vowels in a String medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1109
Problem TLDR
Sort vowels #medium
Intuition
Just implementation, no extra tricks.
Approach
- copy vowels, sort, put back
- or do a counting sort
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 102ms
fun sortVowels(s: String) = buildString {
val vw = s.filter { it in "aeiouAEIOU" }.toList().sorted()
var i = 0
for (c in s) append(if (c in "aeiouAEIOU") vw[i++] else c)
}
// 27ms
fun sortVowels(s: String) = buildString {
val v = "AEIOUaeiou"; val vw = IntArray(12)
for (c in s) ++vw[1 + v.indexOf(c)]
for (c in s) append(if (c in v)
v[(0..10).first {vw[it+1] > 0}.also {--vw[it+1]}] else c)
}
// 10ms
pub fn sort_vowels(s: String) -> String {
let mut t = s.chars().filter(|&c| "AEIOUaeiou".contains(c)).sorted();
s.chars().map(|c| if "AEIOUaeiou".contains(c) { t.next().unwrap() } else { c }).collect()
}
10.09.2025
1733. Minimum Number of People to Teach medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1108
Problem TLDR
Min friends to teach common language to communicate in graph #medium
Intuition
Only one language is allowed.
// user1: knows lang1, friends with user2,user3
// user2: knows lang2, friends with user1,user3
// user3: knows lang1,lang2, friends with user2
// users graph:
// l1 l2 l1,l2
// u1---u2---u3
// \________/
//
// u1 & u2 can't communicate
// u1 & u3 can
// u2 & u3 can
//
// so u1 should learn any langs of u2
// or
// u2 should learn any langs of u1
//
// and we should make minimum users to teach
// [2] [3] [1,2]
// 1--4--3
// \ / it is 3 components: 1, 4, 2-3
// 2
// [1,3]
//
// 1 [+3] and 4 [+2]
//
// i don't get the optimal algo, look at hint (21 minute)
//
// so are users should talk each-to-each, event not direct friends?
// why graph then?
I used the hint: just brute force all languages.
Approach
- the main difficulty is to understand the problem
- only consider non-communicating pairs
- find most common language in non-communicated people
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 83ms
fun minimumTeachings(n: Int, ls: Array<IntArray>, fs: Array<IntArray>): Int {
val ls = ls.map { it.toSet() }; val fs = fs.map { it.toList() }
var f = fs.filter { (a, b) -> !ls[b-1].any { it in ls[a-1] }}.flatten().toSet()
return f.size - (f.flatMap { ls[it-1] }.groupBy{it}.maxOfOrNull{it.value.size}?:0)
}
09.09.2025
2327. Number of People Aware of a Secret medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1107
Problem TLDR
People knowing a secret at day n, keeping delay then spread and forget #medium #simulation
Intuition
// time, delay=1, forget = 3
// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// a a a a
// b b b b
// c c c c
// d d d d
// e
// f
// \
// one from a(d), one from b(e), one from c(f)
// 3 active, so +3 passive (+delay day +3 active)
Maintain diff array for
- changing active spreaders
- changing knowers
Another intuition from lee: dp[i] is how many new people at that day. From that angle we know dp[i-forget] is how many people will forget today, dp[i-(forget-delay)] is how many people became active today. Very useful.
Approach
- the main difficulty is to find a good angle to look at this problem
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 4ms
fun peopleAwareOfSecret(n: Int, delay: Int, forget: Int): Int {
val M = 1000000007L
val know = LongArray(n+forget+1); val active = LongArray(n+forget+1)
know[delay] = 1; know[1+forget] = -1; active[delay] = 1; active[1+forget] = -1
for (d in 1+delay..n) {
active[d] = (active[d-1] + active[d] + M) % M
active[d+delay] += active[d]; active[d+forget] -= active[d]
know[d] = (know[d-1] + know[d] + active[d] + M) % M
know[d+forget] -= active[d]
}
return know[n].toInt()
}
08.09.2025
1317. Convert Integer to the Sum of Two No-Zero Integers easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1106
Problem TLDR
Find a+b=n without zeros in digits #easy
Intuition
Brute force a=1..<n, b = n-a
Approach
- any faster solution?
- any shorter solution?
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 55ms
fun getNoZeroIntegers(n: Int) =
(0..n).map { listOf(it, n-it) }.find { '0' !in "$it" }
// 0ms
pub fn get_no_zero_integers(n: i32) -> Vec<i32> {
(0..n).map(|a|vec![a,n-a]).find(|v|!format!("{:?}",v).contains('0')).unwrap()
}
// 0ms
vector<int> getNoZeroIntegers(int n) {
int a=0,b=0,s=1;
while (n) {
int d = n%10; n/=10;
if (n&&d<2) a += s*(8+d), b += s<<1, --n;
else a += s, b += s*(d-1);
s *= 10;
}
return {a,b};
}
07.09.2025
1304. Find N Unique Integers Sum up to Zero easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1105
Problem TLDR
Any n uniq numbers with sum of 0 #easy
Intuition
- fill symmetrical -i,i, then remove 0 if n is even
- derive the law
1-n+i*2(from lee) - fill range
2..nthen add-sumof that
Approach
- careful with even/odd
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 9ms
fun sumZero(n: Int) = (2..n)+-(2..n).sum()
// 0ms
fun sumZero(n: Int) = IntArray(n) {1-n+it*2}
// 0ms
pub fn sum_zero(n: i32) -> Vec<i32> {
(1..n).chain([(n-n*n)/2]).collect()
}
// 0ms
vector<int> sumZero(int n) {
vector<int> r(n); iota(begin(r),end(r),1);
r.back() = (n-n*n)/2; return r;
}
// 0ms
sumZero = lambda _,n:[*range(1-n,n,2)]
06.09.2025
3495. Minimum Operations to Make Array Elements Zero hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1104
Problem TLDR
Sum query [a..b] of optimal pairwise /4 until range is zero #hard #math
Intuition
Didn’t solve.
// 2, 3, 4, 5, 6
// nums are consequent,
// there can be a fast way to check ops count
// *
// * *
// * * * ------ divide by four
// * * * *
// * * * * *
// * * * * *
// 0 0 1 1 1
// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 3 ....
// 1*3+12*2 +
// 1*(4^1-4^0) + 2*(4^2-4^1) + 3*(4^3-4^2)
//
// optimal way?
// pairs 1 2 3 4 5
// the largest log_4(X) steps
// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// . . 3 4
// . . 0 1
// . . 3 0
// . . 3 0
// . . 3 0
// . . 2 0
// . . 2 0
// . . 2 0
// . . 2 0
// . . 1 0
// . 1 0
// . 1 0
// . 1 0
// . 0 0
// 0 0
// 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 3 3
// a b
// 4^3
// 4^2
// 4^1
// 4^0
// 0
// we have this sequence
//
// 1*(4^1-4^0) + 2*(4^2-4^1) + 3*(4^3-4^2) + k*(4^k-4^(k-1))
// / \
// a b somewhere there
//
// 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 3 3
// a=3 . b=17
// . 3..steps
// . 2....steps
// . 2....steps
// . 2....steps
// . 2....steps
// 2....steps
// 2....steps
// 1...step
// r=1+2*6+3=1+2*(4^2-4^1)/2+3
// how many steps to take pairs from a to b
//
// 1. find which range is b
// ok let's look for hints (44 minute)
// first hint already knew - steps(x) = log_4(x)
// second hint don't understand - pair 2 numbers with max "/4" what?
- each number has uniq growing number of ops
- the sequence of ops is
1*(4^1-4^0) + 2*(4^2-4^1) + 3*(4^3-4^2) + k*(4^k-4^(k-1)) - compute sum of individual ops in range:
ops += (r-l+1)*pow - convert to pairwise and handle edge case of odd numbers:
res += ops/2+ops%2
Approach
- i was close to the solution, just didn’t believe i’m on a right track;
- the tricky part is converting from singles to pairwise ops; have to do big observation for this, or just give up
- not mine bithack:
0x15555555 >> (30 - 2*p)evaluates to1 + 4 + 4² + … + 4^{p-1}. Why?0x15555555is the bit pattern0101...(1s in even positions). Shifting by 30-2p moves exactly p of those 1s into the low end, giving the geometric series above.
Logic behind (x+1)*p-(4^p-1)/3:

For [a,b]=[20,70]:

Complexity
-
Time complexity: \(O(nlog(d))\)
-
Space complexity: \(O(1)\)
Code
// 8ms
fun f(x: Int): Long = ((33 - x.countLeadingZeroBits()) shr 1).let { p ->
1L*(x + 1) * p - (0x15555555 shr (30 - 2 * p)) }
fun minOperations(qs: Array<IntArray>) = qs.sumOf { (f(it[1])-f(it[0]-1)+1)/2 }
// 69ms
fun minOperations(qs: Array<IntArray>) =
qs.sumOf { (a,b) ->
((1..16).sumOf { p ->
max(0, 1L*min(b, (1 shl p*2)-1) - max(a, 1 shl (p-1)*2) + 1) * p
}+1) / 2
}
// 24ms
pub fn min_operations(q: Vec<Vec<i32>>) -> i64 {
q.iter().map(|q| (1+(1..17).map(|p|
0.max(1 + q[1].min((1<<p*2)-1) - q[0].max(1<<(p-1)*2)) as i64*p
).sum::<i64>())/2 ).sum::<i64>()
}
// 30ms
long long minOperations(vector<vector<int>>& q) {
long long r = 0, o = 1;
for (auto& q: q) {
for (int p = 1; p < 17; ++p)
o += p * max(0LL, 1LL + min(1LL*q[1], (1LL<<p*2)-1) - max(1LL*q[0], 1LL<<(p-1)*2));
r += o / 2, o = 1;
}
return r;
}
05.09.2025
2749. Minimum Operations to Make the Integer Zero medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1103
Problem TLDR
Min ops to subtract n2+2^(0..60) from n1 and make n1=0 #medium
Intuition
Didn’t solve.
// n1 = a*n2 + b*2^i, i=0..60
// count of (2^i) == a
// n1 = c*2^0+d*2^1+..x*2^32
// bits
// 2^0 = 1
// 2^1 = 2
// 2^i always positive
//
// n1=4 n2=0 2^2
// n1=3 n2=0 2^1,2^0
// n1=3 n2=1 2^1+1
// n1=3 n2=2 2^0+2
// n1=3 n2=3 -1
// n1=7 n2=1 2^2+1,2^0+1
// n1=7 n2=-1 2^3-1
// 7-n2=8 2^3
// n1=8 n2=-1
// 8-n2=9 9-2^3=1
// 1-n2=2 2-2^1=0
// try just subtract the highest bit
// n1=3 n2=-2
// 3-n2=5 5-2^2=1
// 1-n2=3 3-2^1=1 didn't work that way
//
// 1 2 4 8 16 32
// look for hints (23 minute)
// hint one if n2==0, we need just countOneBits operations
// hint two if n1 can be 0, we need at most 60 ops (why?)
//
// n1 = a*n2 + b*2^i, i=0..60
// n1-a*n2 = sum_a(2^i) (i up to a)
// 0b01000
- do arithmetics:
n1-a*n2 = sum(2^x) = Y - a_max is
x=0 for all 2^x = Y - a_min is
countOneBits- optimal exponentiation
Approach
- the hardest step is the grasping of
min..maxforaand understanding that we can split number if theain that range
Complexity
-
Time complexity: \(O(60log(n))\)
-
Space complexity: \(O(1)\)
Code
// 4ms
fun makeTheIntegerZero(n1: Int, n2: Int) = (1..32)
.firstOrNull { it in (n1-1L*it*n2).countOneBits()..n1-1L*it*n2 } ?: -1
// 0ms
pub fn make_the_integer_zero(n1: i32, n2: i32) -> i32 {
let (mut x, mut r) = (n1 as i64, 0);
for k in 1..33 {
x -= n2 as i64;
if x < k { return -1 }
if k >= x.count_ones() as i64 { return k as _ }
} -1
}
// 0ms
int makeTheIntegerZero(int n1, int n2) {
for(long long k = 1, x = n1;;++k) {
x -= n2;
if (x < k) return -1;
if (__builtin_popcountll(x) <= k) return k;
}
}
// 3ms
def makeTheIntegerZero(_, n1, n2):
return next((t for t in range(1, 33)
if (n1 - t*n2).bit_count() <= t <= n1 - t*n2), -1)
04.09.2025
3516. Find Closest Person easy blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1102
Problem TLDR
Compare two distances #easy
Intuition
Distance is abs(z - x or y)
Approach
- use
when
Complexity
-
Time complexity: \(O(1)\)
-
Space complexity: \(O(1)\)
Code
// 14ms
fun findClosest(x: Int, y: Int, z: Int) =
listOf(1,0,2)[abs(z - x).compareTo(abs(z - y))+1]
// 0ms
pub fn find_closest(x: i32, y: i32, z: i32) -> i32 {
[1,0,2][1+1.min((z-x).abs()-(z-y).abs()).max(-1) as usize]
}
// 0ms
int findClosest(int x, int y, int z) {
return (abs(z-x)>abs(z-y))*2+(abs(z-x)<abs(z-y));
}
// 0ms
findClosest=lambda _,x,y,z:(abs(z-x)>abs(z-y))<<1|(abs(z-x)<abs(z-y))
03.09.2025
3027. Find the Number of Ways to Place People II hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1101
Problem TLDR
Left-top, bottom-right pairs with empty rectangles #medium #geometry
Intuition
Sort by x then rotate CCW around each point.
Approach
- attention to the numbers range -10^9..10^9
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(1)\)
Code
// 692ms
fun numberOfPairs(p: Array<IntArray>): Int {
p.sortWith(compareBy({it[0]},{-it[1]}))
return p.indices.sumOf { i -> var m = Int.MIN_VALUE
p.drop(i+1).count { (_,y) -> y <= p[i][1] && y > m.also{m=max(m,y)}}
}
}
02.09.2025
3025. Find the Number of Ways to Place People I medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1100
Problem TLDR
Left-top, bottom-right pairs with empty rectangles #medium
Intuition
Brute-force is accepted for n=50.
Another intuition: sort by x then rotate CCW around each point.
Approach
- should we learn quad trees?
Complexity
-
Time complexity: \(O(n^3)\)
-
Space complexity: \(O(1)\)
Code
// 55ms
fun numberOfPairs(p: Array<IntArray>): Int {
var res = 0
for (i in p.indices) for (j in p.indices)
if (i != j && p[i][0] <= p[j][0] && p[i][1] >= p[j][1] &&
p.indices.none { k -> k != i && k != j &&
p[k][0] in p[i][0]..p[j][0] && p[k][1] in p[j][1]..p[i][1] }) ++res
return res
}
// 43ms
fun numberOfPairs(p: Array<IntArray>): Int {
p.sortBy { it[0]*1000-it[1] }
return p.indices.sumOf { i ->
var y = -1
p.drop(i+1).count { (_,d) -> d <= p[i][1] && d > y.also{y=max(y,d)}}
}
}
01.09.2025
1792. Maximum Average Pass Ratio medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1099
Problem TLDR
Max avg ratio after assigning extra to ratios #medium
Intuition
Greedy works: for each extra choose the class that will make the most difference.
//[1,2],[3,5],[2,2]]
// 2/3 vs 3/5
// 10/15 9/15
//
// 2/3 4/6 2/2 vs 3/4 3/5 2/2
// a/b c/d
// a+1/b+1 +c/d vs a/b + c+1/d+1
Approach
- we don’t have to validate in the end; choose only available numbers
- there is a bitmask optimization
- we can prioritize rows, cols or subs with more numbers filled
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(n)\)
Code
// 332ms
fun maxAverageRatio(cls: Array<IntArray>, ext: Int): Double {
val q = PriorityQueue<IntArray>(compareBy { (a,b) -> 1.0*a/b-1.0*(a+1)/(b+1)})
q += cls; for (e in 1..ext) q += q.poll().also { ++it[0]; ++it[1] }
return cls.sumOf { (a,b) -> 1.0*a/b } / cls.size
}
31.08.2025
37. Sudoku Solver hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1098
Problem TLDR
Solve sudoku #hard #backtrack
Intuition
Brute-force DFS with pruning
Approach
- we don’t have to validate in the end; choose only available numbers
- there is a bitmask optimization
- we can prioritize rows, cols or subs with more numbers filled
Complexity
-
Time complexity: \(O(9^81)\), however,
9is smaller with pruning -
Space complexity: \(O(1)\)
Code
// 233ms
fun solveSudoku(b: Array<CharArray>): Unit {
val rows = Array(9) { b[it].toHashSet() }
val cols = Array(9) { x -> (0..8).map { b[it][x] }.toHashSet() }
val subs = Array(9) { i -> (0..8).map { j -> b[i/3*3 + j/3][i%3*3 + j%3] }.toHashSet() }
fun dfs(i: Int): Boolean {
if (i == 81) return true
val y = i / 9; val x = i % 9
if (b[y][x] != '.') return dfs(i + 1)
for (c in '1'..'9') if (c !in rows[y] && c !in cols[x] && c !in subs[y/3*3+x/3]) {
b[y][x] = c; rows[y] += c; cols[x] += c; subs[y/3*3+x/3] +=c
if (dfs(i + 1)) return true
rows[y] -= c; cols[x] -= c; subs[y/3*3+x/3] -=c
}
b[y][x] = '.'; return false
}
dfs(0)
}
// 79ms
fun solveSudoku(b: Array<CharArray>): Unit {
val s = Array(3) { IntArray(9) }
for (y in 0..8) for (x in 0..8) if (b[y][x] != '.') {
val c = 1 shl (b[y][x] - '0')
s[0][y] = s[0][y] or c; s[1][x] = s[1][x] or c; s[2][y/3*3+x/3] = s[2][y/3*3+x/3] or c}
fun dfs(i: Int): Boolean {
if (i == 81) return true
val y = i / 9; val x = i % 9
if (b[y][x] != '.') return dfs(i + 1)
for (n in 1..9) {
val c = 1 shl n
if ((c and s[0][y]) + (c and s[1][x]) + (c and s[2][y/3*3+x/3]) == 0) {
s[0][y] = s[0][y] xor c; s[1][x] = s[1][x] xor c; s[2][y/3*3+x/3] = s[2][y/3*3+x/3] xor c
b[y][x] = '0' + n; if (dfs(i + 1)) return true
s[0][y] = s[0][y] xor c; s[1][x] = s[1][x] xor c; s[2][y/3*3+x/3] = s[2][y/3*3+x/3] xor c
}}
b[y][x] = '.'; return false
}
dfs(0)
}
30.08.2025
36. Valid Sudoku medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1097
Problem TLDR
Validate sudoku has no duplicates #medium
Intuition
Brute-force.
Approach
- small grid is
big * 3 + small - single hashset: use keys as
row + digit,column + digit,box + digit
Complexity
-
Time complexity: \(O(1)\)
-
Space complexity: \(O(1)\)
Code
// 0ms
fun List<Char>.ok() = filter { it != '.' }.let { it.toSet().size == it.size }
fun isValidSudoku(b: Array<CharArray>) =
(0..8).all { y -> b[y].map { it }.ok() } &&
(0..8).all { x -> (0..8).map { b[it][x] }.ok() } &&
(0..8).all { c -> (0..8).map { b[c/3 * 3 + it/3][c%3 * 3 + it%3]}.ok() }
// 0ms
pub fn is_valid_sudoku(b: Vec<Vec<char>>) -> bool {
let (mut cols, mut rows, mut subs) = ([0;9],[0;9],[0;9]);
for y in 0..9 { for x in 0..9 { if b[y][x] != '.' {
let d = 1 << (b[y][x] as u8 - b'1');
if (cols[x] & d) + (rows[y] & d) + (subs[y/3*3+x/3] & d) > 0 { return false }
cols[x] |= d; rows[y] |= d; subs[y/3*3+x/3] |= d;
}}} true
}
// 0ms
bool isValidSudoku(vector<vector<char>>& b) {
int f[244]={};
for (int y = 0; y < 9; ++y) for (int x = 0; x < 9; ++x) if (b[y][x] != '.') {
int d = b[y][x] - '1';
if (f[y*9+d]+f[81+d*9+x]+f[81+81+(y/3*3+x/3)*9+d]) return 0;
f[y*9+d]=1;f[81+d*9+x]=1;f[81+81+(y/3*3+x/3)*9+d]=1;
} return 1;
}
// 5ms
def isValidSudoku(_, b):
a = sum(([(d,y),(x,d),(y//3,x//3,d)]
for y in range(9) for x in range(9)
for d in [b[y][x]] if d != '.'),[])
return len(a) == len(set(a))
29.08.2025
3021. Alice and Bob Playing Flower Game medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1096
Problem TLDR
Pairs x=1..n * y=1..m for Alice to win in take from (x+y) game #medium
Intuition
Count odd x+y. It is sum of first odd+second even or reversed.
The interesting math fact from others (can be proved by considering 4 cases: even-even, even-odd,odd-even, odd-odd):
n/2 * (m+1)/2 + m/2 * (n+1)/2 == n*m/2
Approach
- try to write O(1)
Complexity
-
Time complexity: \(O(1)\)
-
Space complexity: \(O(1)\)
Code
// 0ms
fun flowerGame(n: Int, m: Int) =
1L * (n/2) * ((m+1)/2) + 1L * ((n+1)/2) * (m/2)
// 11ms
fun flowerGame(n: Int, m: Int): Long {
val ne = (2..n).count { it % 2 < 1 }
val me = (2..m).count { it % 2 < 1 }
return 1L * (n-ne) * me + 1L * ne * (m-me)
}
// 0ms
pub fn flower_game(n: i32, m: i32) -> i64 {
n as i64 * m as i64 / 2
}
// 0ms
long long flowerGame(int n, int m) {
return 1LL * n * m / 2;
}
// 0ms
flowerGame = lambda _,n,m: n*m//2
28.08.2025
3446. Sort Matrix by Diagonals medium
blog post
substack
youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1095
Problem TLDR
Sort bottom left and top right diagonals #medium #matrix
Intuition
Problem is small, put them into lists, sort, then put back.
Approach
- iterate over
yfor bottom-left,xfor top-right - priority queue gives a compact code
Complexity
-
Time complexity: \(O(n^2logn)\)
-
Space complexity: \(O(1)\)
Code
// 18ms
fun sortMatrix(g: Array<IntArray>) = g.apply {
val m = HashMap<Int, PriorityQueue<Int>>()
for (y in indices) for (x in g[0].indices) m.getOrPut(y-x)
{ PriorityQueue { a,b -> if (y < x) a - b else b - a }} += g[y][x]
for (y in indices) for (x in g[0].indices) g[y][x] = m[y-x]!!.poll()
}
// 35ms
fun sortMatrix(g: Array<IntArray>) = g.apply {
for (y in indices) {
val ns = (0..<g.size-y).map { g[y+it][it] }.sortedDescending()
for (x in ns.indices) g[y+x][x] = ns[x]
}
for (x in 1..<g[0].size) {
val ns = (0..<g[0].size-x).map { g[it][x+it] }.sorted()
for (y in ns.indices) g[y][x+y] = ns[y]
}
}
// 0ms
pub fn sort_matrix(mut g: Vec<Vec<i32>>) -> Vec<Vec<i32>> {
for (x0, y0) in (0..g.len()).map(|y| (y, 0)).chain((1..g[0].len()).map(|x| (0, x))) {
let (mut x, mut y, mut v) = (x0, y0, vec![]);
while x < g[0].len() && y < g.len() { v.push(g[y][x]); y += 1; x += 1 }
v.sort_unstable(); if y >= x { v.reverse() }; (x, y) = (x0, y0);
for v in v { g[y][x] = v; y += 1; x += 1 }
} g
}
// 3ms
vector<vector<int>> sortMatrix(vector<vector<int>>& g) {
int n = size(g), m = size(g[0]), b = n - 1;
vector<priority_queue<int>> q(n+m-1);
for (int y = 0; y < n; ++y) for (int x = 0; x < m; ++x) q[x-y+b].push(y<x?-g[y][x]:g[y][x]);
for (int y = 0; y < n; ++y) for (int x = 0; x < m; ++x)
{ int d = x - y + b, v = q[d].top(); q[d].pop(); g[y][x]=y<x?-v:v; } return g;
}
// 12ms
def sortMatrix(_, g):
d = {}
[[heappush(d.setdefault(y-x, []), t*(1,-1)[y>=x]) for x,t in enumerate(r)] for y,r in enumerate(g)]
g[:] = [[(heappop(d[y-x])*(1,-1)[y>=x]) for x in range(len(r))] for y,r in enumerate(g)]
return g
27.08.2025
3459. Length of Longest V-Shaped Diagonal Segment hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1094
Problem TLDR
Max length of 1-2-0-2.. diagonal sequence, on cw rotation #hard #dp
Intuition
Do Depth-First Search, add memoization (however accepted without it)
Approach
- enumerate diagonals as 0..3, cw rotation is
(d+1)%4, ccw(d+3)%4 - v is irrelevant to dp key
- dp key can be Int:
(500*y+x)*100 + dir*10 + rot - I think the HashMap is the weakest point of performance
Complexity
-
Time complexity: \(O(mn)\)
-
Space complexity: \(O(n)\)
Code
// 1219ms
fun lenOfVDiagonal(g: Array<IntArray>): Int {
val nxy = arrayOf(-1,-1,1,1,-1); val nv = arrayOf(2,2,0); var res = 0
fun dfs(y: Int, x: Int, dir: Int, rot: Int, v: Int): Int =
if (y !in 0..<g.size || x !in 0..<g[0].size || g[y][x] != v ) 0
else 1 + max(dfs(y+nxy[dir],x+nxy[dir+1],dir,rot,nv[v]),
if (rot > 0) dfs(y,x,(dir+1)%4,0,v)-1 else 0)
for (y in g.indices) for (x in g[0].indices) if (g[y][x] == 1)
res = max(res, (0..3).maxOf {dfs(y,x,it,1,1)})
return res
}
// 981ms
fun lenOfVDiagonal(g: Array<IntArray>): Int {
val nxy = arrayOf(-1,-1,1,1,-1); val nv = arrayOf(2,2,0); var res = 0
val dp = HashMap<Int, Int>()
fun dfs(y: Int, x: Int, dir: Int, rot: Int, v: Int): Int =
if (y < 0 || x < 0 || y == g.size || x == g[0].size || g[y][x] != v ) 0
else 1 + dp.getOrPut((y*500 + x)*100 + dir*10 + rot) { max(
dfs(y+nxy[dir],x+nxy[dir+1],dir,rot,nv[v]),
if (rot > 0) dfs(y,x,(dir+1)%4,0,v)-1 else 0) }
for (y in g.indices) for (x in g[0].indices) if (g[y][x] == 1)
res = max(res, (0..3).maxOf {dfs(y,x,it,1,1)})
return res
}
26.08.2025
3000. Maximum Area of Longest Diagonal Rectangle medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1093
Problem TLDR
Max area of max diagonal rectangles #easy
Intuition
Single iteration:
- update max diagonal, forget max area
- update max area
Approach
- or we can find a max of a single variable
diagonal+area
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 11ms
fun areaOfMaxDiagonal(d: Array<IntArray>) = d
.maxOf { (w,h) -> (w*w+h*h) * 10000 + w*h }%10000
// 0ms
pub fn area_of_max_diagonal(d: Vec<Vec<i32>>) -> i32 {
d.iter().map(|d|(d[0]*d[0]+d[1]*d[1],d[0]*d[1])).max().unwrap().1
}
// 0ms
int areaOfMaxDiagonal(vector<vector<int>>& d) {
int x = 0;
for (auto d: d) x = max(x, (d[0]*d[0]+d[1]*d[1])*10000+d[0]*d[1]);
return x%10000;
}
// 0ms
areaOfMaxDiagonal= lambda _,d:max((w*w+h*h,w*h) for w,h in d)[1]
25.08.2025
498. Diagonal Traverse medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1092
Problem TLDR
Matrix diagonal traversal #medium
Intuition
Use the fact: diagonal x + y = constant
Approach
- use d%2 to check if should go up
Complexity
-
Time complexity: \(O(nm)\)
-
Space complexity: \(O(nm)\)
Code
// 39ms
fun findDiagonalOrder(m: Array<IntArray>) = buildList {
for (d in 0..m.lastIndex+m[0].lastIndex)
for (x in (max(0,d-m.lastIndex)..min(d, m[0].lastIndex))
.let { if (d%2>0) it.reversed() else it}) this += m[d-x][x]
}
// 0ms
pub fn find_diagonal_order(m: Vec<Vec<i32>>) -> Vec<i32> {
(0..=m.len()+m[0].len()-2).flat_map(|d| {
let (a, b) = (d.saturating_sub(m.len()-1), d.min(m[0].len()-1));
let mut n: Vec<_> = (a..=b).map(|x| m[d-x][x]).collect();
if d%2>0 { n.reverse() }; n
}).collect()
}
// 4ms
vector<int> findDiagonalOrder(vector<vector<int>>& m) {
vector<int>r; int w = size(m[0]), h = size(m);
for (int d = 0; d <= w+h-2; ++d) {
int b = min(d, w-1), a = max(0, d-h+1);
for (int x = (d%2)*b+(1-d%2)*a; d%2 && x >= a || d%2<1 && x <= b; d%2?--x:++x)
r.push_back(m[d-x][x]);
} return r;
}
// 27ms
def findDiagonalOrder(_, m):
h,w=len(m),len(m[0]); return [m[d-x][x]
for d in range(h+w-1)
for x in range(max(0,d-h+1),min(d,w-1)+1)[::1-2*(d&1)]]
24.08.2025
1493. Longest Subarray of 1’s After Deleting One Element medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1091
Problem TLDR
Max 1-subarray after removing one elemnt #medium #two_pointers
Intuition
The simple way:
- count
prevones andcurrones, then max(res, prev+curr) - corner cases are: all ones, single one island and zero
The clever way:
- use fact that we only interested in the largest island
- set left border
land move it always while zeros are two and more - all the smaller islands doesn’t matter
Approach
- the two pointers: always move right, move left until condition, compute current min/max result
- for max window sometimes we didn’t have to shrink window, just move
- right border of sliding window will eventually be at
size-1, we only interested in left
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 2ms
fun longestSubarray(n: IntArray): Int {
var l = 0; var z = 0
for (x in n) z -= x - if (z > x) n[l++] else 1
return n.size - l - 1
}
// 4ms
fun longestSubarray(n: IntArray): Int {
var p = 0; var c = 0; var r = 0; var z = 1
for (x in n) if (x > 0) r = max(r, ++c+p)
else { p = c; c = 0; z = 0 }
return r - z
}
// 0ms
pub fn longest_subarray(n: Vec<i32>) -> i32 {
let (mut l, mut zs) = (0, 0);
(0..n.len()).map(|i| {
zs += 1 - n[i];
if zs > 1 { zs -= 1 - n[l]; l += 1 }
i - l
}).max().unwrap() as _
}
// 0ms
int longestSubarray(vector<int>& n) {
int l = 0, z = 0;
for (int x: n) z -= x-(z>x?n[l++]:1);
return size(n) - l - 1;
}
// 43ms
def longestSubarray(_, n):
l=z=0
for x in n: t=z>x; z+=1-x-t+t*n[l]; l += t
return len(n)-l-1
23.08.2025
3197. Find the Minimum Area to Cover All Ones II hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1090
Problem TLDR
Min sum all-1 areas of 3-split #hard
Intuition
Use hint: try every split
Approach
- corner case: consider reverse split and sum
Complexity
-
Time complexity: \(O(nm^4)\)
-
Space complexity: \(O(1)\)
Code
// 51ms
fun minimumSum(g: Array<IntArray>): Int {
val w = g[0].size; val h = g.size
fun sum(x1: Int, y1: Int, x2: Int, y2: Int): Int {
var r = 0; var b = 0; var l = w; var t = h
for (y in y1..y2) for (x in x1..x2) if (g[y][x] > 0)
{ r = max(r, x); l = min(l, x); b = max(b, y); t = min(t, y) }
return (r-l+1)*(b-t+1)
}
fun split(x1: Int, y1: Int, x2: Int, y2: Int): Int {
var res = 30*30
for (y in y1..<y2) res = min(res, sum(x1, y1, x2, y) + sum(x1, y+1, x2, y2))
for (x in x1..<x2) res = min(res, sum(x1, y1, x, y2) + sum(x+1, y1, x2, y2))
return res
}
var res = 30*30
for (y in 0..<h-1) res = min(res, sum(0, 0, w-1, y) + split(0, y+1, w-1, h-1))
for (y in 0..<h-1) res = min(res, split(0, 0, w-1, y) + sum(0, y+1, w-1, h-1))
for (x in 0..<w-1) res = min(res, sum(0, 0, x, h-1) + split(x+1, 0, w-1, h-1))
for (x in 0..<w-1) res = min(res, split(0, 0, x, h-1) + sum(x+1, 0, w-1, h-1))
return res
}
22.08.2025
3195. Find the Minimum Area to Cover All Ones I medium blog post substack youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1089
Problem TLDR
Min all-1 rectangle #medium
Intuition
Compute 4 variables: minX..maxX, minY..maxY
Approach
- or, we can go from the corners
Complexity
-
Time complexity: \(O(nm)\)
-
Space complexity: \(O(1)\)
Code
// 945ms
fun minimumArea(g: Array<IntArray>): Int {
var a = 0; var b = 0; var c = g.size; var d = g[0].size
for (y in 0..<c) for (x in g[0].indices) if (g[y][x] > 0)
{ a = y; b = max(b, x); c = min(c, y); d = min(d, x) }
return (b-d+1)*(a-c+1)
}
// 1019ms
fun minimumArea(g: Array<IntArray>): Int {
var w = g[0].size; var h = g.size
for (y in g.indices) if (1 !in g[y]) --h else break
for (y in g.lastIndex downTo 0) if (1 !in g[y]) --h else break
for (x in g[0].indices) if (g.indices.all { g[it][x] < 1}) --w else break
for (x in g[0].lastIndex downTo 0) if (g.indices.all { g[it][x] < 1}) --w else break
return w * h
}
// 39ms
pub fn minimum_area(g: Vec<Vec<i32>>) -> i32 {
let mut r = [0, 0, g.len(), g[0].len()];
for y in 0..r[2] { for x in 0..g[0].len() { if g[y][x] > 0
{ r = [y, r[1].max(x), r[2].min(y), r[3].min(x)] }
}} ((r[1] - r[3] + 1) * (r[0] - r[2] + 1)) as _
}
// 275ms
int minimumArea(vector<vector<int>>& g) {
int a=0,b=0,c=size(g),d=size(g[0]),n=c,m=d;
for (int y = 0; y < n; ++y) for (int x = 0; x < m; ++x)
g[y][x]&&(a=y,b=b>x?b:x,c=c<y?c:y,d=d<x?d:x);
return (a-c+1)*(b-d+1);
}
// 3144ms
def minimumArea(_, g):
i, j = zip(*((y,x) for y,r in enumerate(g) for x,v in enumerate(r) if v))
return (max(j)-min(j)+1)*(max(i)-min(i)+1)
// 2593ms
def minimumArea(_, g):
n,m = len(g), len(g[0])
t = next(i for i in range(n) if 1 in g[i])
b = next(i for i in range(n-1,-1,-1) if 1 in g[i])
l = next(j for j in range(m) if any(g[i][j] for i in range(n)))
r = next(j for j in range(m-1,-1,-1) if any(g[i][j] for i in range(n)))
return (b-t+1)*(r-l+1)
21.08.2025
1504. Count Submatrices With All Ones medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1088
Problem TLDR
Count islands of 1 #medium #dp
Intuition
//
// 4
// *
// *
// 1 *
// * x
// 1 4
// 3
// 4 4
// * 3 *
// * * *
// 1 * * *
// * * * x
// 1 3 3 4
//
// 3 5
// 4 4 4 *
// * 3 * * *
// * * * * *
// 1 * * * * *
// * * * * * x
// 1 3 3 4 4 5
//
// 4 6
// 5 5 5 *
// * 4 * * *
// * * * * *
// 2 * * * * *
// * * * * * *
// * * * * * x
// 2 4 4 5 5 6
// 1,0,1,1,1,1,1 16
// 1,1,0,0,0,1,1
// 2 1 2 2 26
// 1,1,1,0,0,1,1
// 3 2 1
// 1,0,1,0,1,0,1
// 1,0,1,1,1,0,1
// 1,1,0,1,1,1,1
// 1,0,0,1,1,0,1
Go row by row, store the heights. For each new position
- it is the bottom right corner of all possible rectangles
- it is equal to the sum of decreasing heights
Approach
- reuse the input (not in production or in interview)
- the monotonic stack is not required; idea: it holds only increasing indices, pop while decrease, remove the diff (use the next index in stack or -1)
Complexity
-
Time complexity: \(O(n^2m)\)
-
Space complexity: \(O(1)\)
Code
// 8ms
fun numSubmat(m: Array<IntArray>): Int {
var res = 0; val h = IntArray(m[0].size)
for (r in m) for (x in h.indices) {
var c = r[x] * ++h[x]; h[x] = c
for (j in x downTo 0) { c = min(c, h[j]); res += c }
}
return res
}
// 53ms
fun numSubmat(m: Array<IntArray>) =
m.withIndex().sumOf { (y, h) ->
val st = Stack<Int>(); var c = 0
m[y].indices.sumOf { x ->
h[x] = m[y][x] * (1 + if (y > 0) m[y-1][x] else 0); c += h[x]
while (st.size > 0 && h[st.peek()] > h[x]) {
val j = st.pop()
c -= (h[j] - h[x]) * (j - if (st.size > 0) st.peek() else -1)
}
st += x; c
}
}
// 4ms
pub fn num_submat(m: Vec<Vec<i32>>) -> i32 {
let (mut r, mut h) = (0, vec![0; m[0].len()]);
for y in &m { for x in 0..h.len() {
let mut c = y[x] * (1 + h[x]); h[x] = c;
for j in (0..=x).rev() { c = c.min(h[j]); r += c }
}} r
}
// 5ms
int numSubmat(vector<vector<int>>& m) {
int res = 0; vector<int> h(size(m[0]));
for (auto& r: m) for (int x = 0; x < size(r); ++x) {
int c = r[x] * ++h[x]; h[x] = c;
for (int j = x; j >= 0; --j) res += c = min(c, h[j]);
} return res;
}
// 772ms
def numSubmat(_, m):
r = 0; h = [0] * len(m[0])
for y in m:
for i,x in enumerate(y):
c=x and h[i]+1;h[i]=c
r+=sum((c:=min(c, h[j])) for j in range(i, -1, -1))
return r
20.08.2025
1277. Count Square Submatrices with All Ones medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1087
Problem TLDR
Count square islands of 1 #medium #dp
Intuition
Reuse the previous row calculations:
- look diagonal up-left
- look up
- count left
Approach
- try to write without
ifs - reuse the input (not in production or in interview)
Complexity
-
Time complexity: \(O(nm)\)
-
Space complexity: \(O(1)\)
Code
// 21ms
fun countSquares(m: Array<IntArray>) = with(m) {
for (y in 1..<size) for (x in 1..<m[0].size)
m[y][x] *= 1 + min(m[y][x-1], min(m[y-1][x-1], m[y-1][x]))
sumOf { it.sum() }
}
// 0ms
pub fn count_squares(mut m: Vec<Vec<i32>>) -> i32 {
for y in 1..m.len() { for x in 1..m[0].len() {
m[y][x] *= 1 + m[y][x-1].min(m[y-1][x-1]).min(m[y-1][x])
}} m.iter().flatten().sum()
}
// 0ms
int countSquares(vector<vector<int>>& m) {
int r = 0;
for (int y = 0; y < size(m); ++y) for (int x = 0; x < size(m[0]); ++x)
r += m[y][x] *= 1 + (y&&x ? min(m[y-1][x-1], min(m[y][x-1], m[y-1][x])): 0);
return r;
}
// 85ms
def countSquares(_, m: List[List[int]]):
for y in range(len(m)):
for x in range(len(m[0])):
m[y][x] *= 1 + (y and x and min(m[y-1][x-1], m[y][x-1], m[y-1][x]))
return sum(map(sum, m))
19.08.2025
2348. Number of Zero-Filled Subarrays medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1086
Problem TLDR
Count 0-subarrays #medium #counting
Intuition
Count zero islands, use arithmetic sum: n(n+1)/2
Approach
- instead of arithmetics, just add current count to the result
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 5ms
fun zeroFilledSubarray(n: IntArray) =
n.fold(0L) { r, t ->
if (t == 0) ++n[0] else n[0] = 0; r + n[0]
}
// 3ms
fun zeroFilledSubarray(n: IntArray): Long {
var res = 0L; var curr = 0
for (x in n) {
if (x == 0) ++curr else curr = 0
res += curr
}
return res
}
// 0ms
pub fn zero_filled_subarray(n: Vec<i32>) -> i64 {
let (mut r, mut c) = (0, 0);
for x in n { if (x == 0) { c += 1 } else { c = 0 }; r += c } r
}
// 0ms
long long zeroFilledSubarray(vector<int>& n) {
long long r = 0;
for (int c = 0; int x: n) r += c = x ? 0: ++c;
return r;
}
// 49ms
zeroFilledSubarray = lambda _,n: sum(accumulate(n, lambda c,x: (c+1)*(x==0), initial=0))
18.08.2025
679. 24 Game hard blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1085
Problem TLDR
Can a,b,c,d = 24 with ops */+-() #hard #backtracking #math
Intuition
Solved not optimally.
// 1..9
// ()+-/*
// 12 * 2
// 8 * 3
// 6 * 4
// 2 * 3 * 4
// 2 * 3 * 2 * 2
// 1 - 2/3 = 1/3; 8 / (1 - 2/3)
// 1 - 3/4 = 1/4; 6 / (1 - 3/4)
// 1 - 5/6 = 1/6; 4 / (1 - 5/6)
// 1 - 7/8 = 1/8; 3 / (1 - 7/8)
// 20+4; 5*4+2+2 2+2=1..3 + 3..1
// 5*(2+2)+4
// 21+3; too many to list them all
// implement eval?
// 1 3 4 6
// 6/(1-3/4)
// i don't think my solution is the expected
// 0123456789012
// .x..x...x..x. 13 positions
// ( ( (
// ) ) )
// + + +
// - - -
// * * *
// / / /
// a a a a
// b b b b
// c c c c
// d d d d
My intuition was just to build all possible equations, then parse them and eval.
The optimal intuition (not mine): every equation has the first step than you can do, just compute by picking any two numbers.
Approach
- solve not optimally to appreciate the cleverness of an idea
Complexity
-
Time complexity: \(O(n^(2n))\), n levels deep, n^2 at each level
-
Space complexity: \(O(n^n)\), n levels, n size at each level
Code
// 80ms
fun judgePoint24(cards: IntArray): Boolean {
fun dfs(cs: List<Double>): Boolean {
for (i in cs.indices) for (j in cs.indices) if (i != j) {
val a = cs[i]; val b = cs[j]
val next = arrayListOf(a+b, a-b,b-a, a*b); if(b!=0.0) next += a/b
val rest = (cs.indices - i - j).map {cs[it]}
for (x in next) if (dfs(rest + x)) return true
}
return cs.size == 1 && abs(24.0-cs[0])<0.001
}
return dfs(cards.map { 1.0 * it })
}
17.08.2025
837. New 21 Game medium blog post substack youtube

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1084
Problem TLDR
Probability sum of random(1..m) less than n when stop adding at k #medium #math #probability
Intuition
Didn’t solved without TLE
// each step:
// sum +=
// + random(1..maxpts)
// + random(1..maxpts)
// + random(1..maxpts)
// + random(1..maxpts)
// stop if sum bigger than k
//
// probability sum <= n
// n=10 k=1 m=10
// s +=
// 1..10 (let's be 1)
// s = 1 bigger k -- stop
// s less 10 true
// n=6 k=1 m=10
// s +=
// 1,2,3,4,5,6
// 7,8,9,10
// s is more than k; stop
// only 6/10 is less than n
// n=21 k=17 m=10
// 1..10
// 1..10
// making +1 calls is too heavy 10^4 x 10^4 TLE
// maybe wrong dp dimension?
// no hints; i'll give up
// i didn't get why p20=p16*p4+p15*p5+..p10*p10
The math intuition: (credits https://leetcode.com/problems/new-21-game/solutions/220949/python-3-memorize-dfs-from-o-kw-w-to-o-k-w/)
f(s) = f(s+1)+f(s+2)+...+f(s+m) /m
f(s+1) = f(s+2)+f(s+3)+...+f(s+m)+f(s+1+m) /m
f(s) - f(s+1) = (f(s+1) - f(s+1+m)) /m
The final condition:
k......n......m means we take (n-k)/m
k.............m....n means we always good 1.0
Approach
- try to understand at least one intuition fully
Complexity
-
Time complexity: \(O(k + m)\)
-
Space complexity: \(O(k + m)\)
Code
// 28ms
fun new21Game(n: Int, k: Int, m: Int): Double {
val dp = HashMap<Int, Double>()
fun dfs(s: Int): Double =
if (s == k - 1) 1.0*min(n - k + 1, m) / m
else if (s >= k) { if (s <= n) 1.0 else 0.0 }
else dp.getOrPut(s) {
dfs(s + 1) - (dfs(s + 1 + m) - dfs(s + 1)) / m
}
return dfs(0)
}
16.08.2025
1323. Maximum 69 Number easy
blog post
substack
youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1082
Problem TLDR
Bigger number by replacing 6 to 9 #easy
Intuition
The simpliest way is to convert to char array, replace first, then stop.
Approach
- let’s explore other unusual ways
Complexity
-
Time complexity: \(O(1)\)
-
Space complexity: \(O(1)\)
Code
// 7ms
fun maximum69Number (n: Int) =
"$n".replaceFirst('6', '9').toInt()
// 12ms
fun maximum69Number (n: Int) =
n + 3 * (setOf(1000, 100, 10, 1).firstOrNull { n/it%9>0 }?:0)
// 0ms
pub fn maximum69_number(n: i32) -> i32 {
n + 3 * [1000, 100, 10, 1].iter().find(|&&p| n/p%10==6).unwrap_or(&0)
}
// 0ms
int maximum69Number (int n) {
for (int p = 1000; p; p /= 10)
if (n/p%10 == 6) return n + 3*p;
return n;
}
// 0ms
maximum69Number = lambda _, n: int(str(n).replace('6','9',1))
15.08.2025
342. Power of Four easy
blog post
substack
youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1081
Problem TLDR
Is number power of 4? #easy
Intuition
- count bits, look at trailing zeros count, should be even
- use a bitmask
...1010101010101 - use
(n-1)%3:n-1 = 4^k -1 = (2^k -1)(2^k + 1), fromodd,2^n,oddrow, one of the odds is always%3:123, 345, 789, and so on
Approach
- also fun regex solution
Complexity
-
Time complexity: \(O(1)\)
-
Space complexity: \(O(1)\)
Code
// 16ms
fun isPowerOfFour(n: Int) =
Regex("^1(?:00)*$").matches(n.toString(2))
// 4ms
fun isPowerOfFour(n: Int) =
(0..15).any { n == 1 shl it*2 }
// 1ms
fun isPowerOfFour(n: Int) =
n.countOneBits() == 1 && n and 1431655765 == n
// 1ms
fun isPowerOfFour(n: Int) =
n.countOneBits() == 1 && (n-1)%3 == 0
// 0ms
pub fn is_power_of_four(n: i32) -> bool {
(0..16).any(|p| n == 1 << p * 2)
}
// 0ms
bool isPowerOfFour(int n) {
return n > 0 && (n & n-1) + (n-1)%3 == 0;
}
// 0ms
def isPowerOfFour(self, n: int) -> bool:
return n in [1<<p*2 for p in range(16)]
14.08.2025
2264. Largest 3-Same-Digit Number in String easy
blog post
substack
youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1080
Problem TLDR
Max 3-digit in string #easy
Intuition
Sliding window is accepted and the optimal
Approach
- compare just a single char
- let’s explore the variations: what if we check each digit individually?
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 26ms
fun largestGoodInteger(num: String) = num.windowed(3)
.filter { it.toSet().size < 2 }.maxByOrNull { it[0] } ?: ""
// 15ms
fun largestGoodInteger(n: String) = (9 downTo 0)
.map { "$it$it$it" }.find { it in n } ?: ""
// 0ms
pub fn largest_good_integer(num: String) -> String {
num.as_bytes().windows(3).filter(|w| w[0] == w[1] && w[1] == w[2])
.max_by_key(|w| w[0]).map_or("".into(), |w| from_utf8(w).unwrap().into())
}
// 0ms
string largestGoodInteger(string n) {
int c = 0, p = 0; char m = 0;
for (auto x: n) c = p == x ? ++c : 1, p = x, m = c > 2 ? max(m, x):m;
return m > 0 ? string()+m+m+m : "";
}
// 0ms
def largestGoodInteger(_, n):
return next((d*3 for d in '9876543210' if d*3 in n), '')
13.08.2025
326. Power of Three easy
blog post
substack
youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1079
Problem TLDR
Is n power of 3? #easy #math
Intuition
Almost failed at corner case Int.MAX_VALUE, be aware of Int overflow when *3.
Another interesting facts:
- 3-base representation has only single
1, others0 3^19is max fit into Int, if3^19 % n == 0, n is a power of3
Approach
- try to write all the different ways
- the
/solution is the most robust - some arithmetic fact:
log_3(n) = log_x(n)/log_x(3) for any x
Complexity
-
Time complexity: \(O(log(n))\)
-
Space complexity: \(O(1)\)
Code
// 27ms
fun isPowerOfThree(n: Int) =
n.toString(3).replace("0", "") == "1"
// 10ms
fun isPowerOfThree(n: Int) = n > 0 &&
3.0.pow(1.0*log(1.0*n, 3.0).roundToInt()) == 1.0*n
// 9ms
fun isPowerOfThree(n: Int) =
n > 0 && 3.0.pow(19.0).toInt() % n < 1
// 8ms
fun isPowerOfThree(n: Int): Boolean {
if (n <= 0) return false
var x = 1L; val n = 1L * n
while (x < n) x *= 3
return x == n
}
// 8ms
fun isPowerOfThree(n: Int): Boolean {
var n = n; if (n > 1) while (n % 3 == 0) n /= 3
return n == 1
}
// 0ms
pub fn is_power_of_three(n: i32) -> bool {
n > 0 && 3i32.pow(19) % n < 1
}
// 3ms
bool isPowerOfThree(int n) {
while (n > 1 && n % 3 == 0) n /= 3;
return n == 1;
}
// 6ms
def isPowerOfThree(self, n: int) -> bool:
return n > 0 and 3**19%n<1
12.08.2025
2787. Ways to Express an Integer as Sum of Powers medium blog post substack youtube https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1078
Problem TLDR
Ways to make n by sum of a^x+b^x+… #medium #dp
Intuition
Solved not optimally.
Consider all numbers: p = 1, 2, 3, ... a, b, c ... n and their x-powers: pow = a^x b^x c^x.
Do depth-first search, at each step make a decision:
- take the number:
v + a^x, p++ - or skip it:
v, p++If we arrive atv==nwe have a one good combination, return1. Cache the answer for inputsv, p.
For optimization, rewrite to iterate over the same values v, p, reversing the ranges.
Then do a space optimization, as we always look at p+1 previous row.
Approach
- I guess it is always good to start with simple choice instead of range iteration inside DFS
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n)\)
Code
// 1092ms
fun numberOfWays(n: Int, x: Int): Int {
val m = 1000000007; var maxp = n; val pow = IntArray(n + 1) { 1 }
for (i in pow.indices) for (j in 1..x) {
pow[i] *= i; if (pow[i] > n) maxp = min(maxp, i)
}
val ways = Array(maxp + 2) { IntArray(n + 1) }
for (i in ways.indices) ways[i][0] = 1
for (x in 1..n) for (from in maxp downTo 1)
for (y in from..maxp) {
if (x - pow[y] < 0) break
ways[from][x] = (ways[from][x] + ways[y + 1][x - pow[y]])%m
}
return ways[1][n]
}
// 657ms
fun numberOfWays(n: Int, x: Int): Int {
val m = 1000000007; val dp = HashMap<Pair<Int, Int>, Int>()
fun dfs(v: Int, p: Int): Int = dp.getOrPut(v to p) {
if (v == 0) 1 else if (v < 0 || p > v || Math.pow(1.0*p, 1.0*x).toInt() > v) 0
else (dfs(v - Math.pow(1.0*p, 1.0*x).toInt(), p + 1) + dfs(v, p + 1)) % m
}
return dfs(n, 1)
}
// 15ms
fun numberOfWays(n: Int, x: Int): Int {
val m = 1000000007; val ways = IntArray(n + 1); ways[0] = 1
for (p in 1..n) {
var pow = 1; for (i in 1..x) pow *= p; if (pow > n) break
for (v in n downTo pow) ways[v] = (ways[v] + ways[v - pow]) % m
}
return ways[n]
}
// 0ms
pub fn number_of_ways(n: i32, x: i32) -> i32 {
let mut dp = [0;301]; let n = n as usize; dp[0] = 1;
for p in 1..=n {
let pow = p.pow(x as u32);
for v in (pow..=n).rev() { dp[v] = (dp[v] + dp[v - pow]) % 1000000007 }
} dp[n]
}
// 14ms
int numberOfWays(int n, int x) {
int d[301]={}; d[0] = 1;
for (int p = 1; p <= n && pow(p, x) <= n; ++p)
for (int v = n, pw = pow(p, x); v >= pw; --v)
d[v] = (d[v] + d[v-pw]) % 1000000007;
return d[n];
}
// 363ms
def numberOfWays(self, n: int, x: int) -> int:
d = [1] + [0] * n
for p in range(1, n + 1):
for v in range(n, p ** x - 1, -1):
d[v] = (d[v] + d[v - p ** x]) % 1000000007
return d[n]
11.08.2025
2438. Range Product Queries of Powers medium
blog post
substack
youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1077
Problem TLDR
Range product queries of powers of two from n #medium
Intuition
- Known technique to split number to the powers of two: exponentiation, each set bit is the power of two
- Trick observation: there are at most 30 of them, can brute-force each query ```j // 012345 // 1248 // 1111 // ok how to do modulus subarray? // maybe use the fact they are all powers of two? (not many of them)
Interesting math optimization to O(nlog(30) + 30):
* product is `2^a * 2^b * 2^c = 2^(a+b+c)`
* so, we can use powers prefixes sum
* then product of range is `p_i_j = 2^(bits in i..j)`
* to calc `x^y %m` use math: `x^y = (x * x)^y/2 + x^y%2`
#### Approach
* use long, product can overflow even before `%m`
* optimization: precompute square matrix `30^2` for `result[from][to]`
#### Complexity
- Time complexity:
$$O(n)$$,
- Space complexity:
$$O(1)$$
#### Code
```kotlin [-Kotlin (71ms]
// 71ms
fun productQueries(n: Int, q: Array<IntArray>): IntArray {
val p = ArrayList<Int>(); val M = 1000000007L
for (b in 0..30) if (n shr b and 1 != 0) p += 1 shl b
return IntArray(q.size) {
(q[it][0]..q[it][1]).fold(1L) { r, i -> (r * p[i]) % M }.toInt()
}
}
```kotlin [-19ms)]
// 19ms
fun productQueries(n: Int, q: Array
```rust [-Rust 15ms]
// 15ms
pub fn product_queries(n: i32, q: Vec<Vec<i32>>) -> Vec<i32> {
let mut p = vec![]; let M = 1000000007i64;
for b in 0..31 { if n >> b & 1 > 0 { p.push(1i64 << b) }}
q.iter().map(|q| { let (s, e) = (q[0] as usize, q[1] as usize);
(s..=e).fold(1, |r, i| (r * p[i]) % M) as i32
}).collect()
}
```c++ [-c++ 16ms]
// 16ms
vector
```python [-python 95ms]
// 95ms
def productQueries(self, n: int, q: List[List[int]]) -> List[int]:
m = 1_000_000_007
p = [b for b in range(31) if (n >> b) & 1]
pref = [0]
for e in p:
pref.append(pref[-1] + e)
return [pow(2, pref[r+1] - pref[l], m) for l, r in q]
10.08.2025
869. Reordered Power of 2 medium
blog post
substack
youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1076
Problem TLDR
Rearrange digits to make power of two #medium #dfs #bits
Intuition
The naive brute force of O(log(n)!) is accepted, we only have 9 digits, n is 10^9.
The trick: think from the finish line - we only have 30 powers of two, let’s just check them.
Approach
- compare by frequency
- optimization: for
9digits, each max frequency is9, we can put freqency array into a single10digits number (c++ solution)
Complexity
-
Time complexity: \(O(log^2(n))\),
-
Space complexity: \(O(log(n))\)
Code
```kotlin [-Kotlin (233ms]
// 233ms fun reorderedPowerOf2(n: Int): Boolean { val ds = “$n” fun dfs(curr: Int, m: Int): Boolean { if (m == 0) return curr.countOneBits() == 1 for (i in 0..30) if (m and (1 shl i) != 0) { if (ds[i] == ‘0’ && curr == 0) continue if (dfs(curr * 10 + (ds[i] - ‘0’), m xor (1 shl i))) return true } return false } return dfs(0, (1 shl ds.length) - 1) }
```kotlin [-18ms)]
// 18ms
fun reorderedPowerOf2(n: Int) =
(0..30).any { "$n".groupBy { it } == "${1 shl it}".groupBy { it }}
```rust [-Rust (0ms]
// 0ms pub fn reordered_power_of2(mut n: i32) -> bool { let mut nf = [0; 10]; while n > 0 { nf[(n % 10) as usize] += 1; n /= 10 } (0..30).any(|i| { let mut x = 1 « i; let mut f = [0; 10]; while x > 0 { f[(x % 10) as usize] += 1; x /= 10 } f == nf }) }
```c++ [-c++ (0ms]
// 0ms
bool reorderedPowerOf2(int n) {
long c = 0; while (n) c += pow(10, n % 10), n /= 10;
for (int i = 0, x=0, y=1; i < 30; ++i, x = 0, y = 1<<i) {
while (y) x += pow(10, y % 10), y /= 10;
if (x == c) return 1;
}
return 0;
}
```python [-python 0ms]
// 0ms def reorderedPowerOf2(self, n: int) -> bool: return any(sorted(str(n)) == sorted(str(1 « i)) for i in range(31))
# 9.08.2025
[231. Power of Two](https://leetcode.com/problems/power-of-two/description/) easy
[blog post](https://leetcode.com/problems/power-of-two/solutions/7060229/kotlin-rust-by-samoylenkodmitry-ap99/)
[substack](https://open.substack.com/pub/dmitriisamoilenko/p/9082025-231-power-of-two?r=2bam17&utm_campaign=post&utm_medium=web&showWelcomeOnShare=true)
[youtube](https://youtu.be/dpCsHFQK4pE)

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
#### Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1075
#### Problem TLDR
Is int 32 power of 2? #easy #bits
#### Intuition
Any negative number is not power of 2 by problem description.
#### Approach
* there are built-in functions
#### Complexity
- Time complexity:
$$O(1)$$,
- Space complexity:
$$O(1)$$
#### Code
```kotlin [-Kotlin (0ms]
// 0ms
fun isPowerOfTwo(n: Int) =
n > 0 && n.countOneBits() < 2
```kotlin [-0ms)]
// 0ms fun isPowerOfTwo(n: Int) = n > 0 && n and (n - 1) < 1
```rust [-Rust (0ms]
// 0ms
pub fn is_power_of_two(n: i32) -> bool {
n > 0 && n.count_ones() == 1
}
```rust [-0ms]
// 0ms pub fn is_power_of_two(n: i32) -> bool { n > 0 && (n as u32).is_power_of_two() }
```c++ [-c++ (0ms]
// 0ms
bool isPowerOfTwo(int n) {
return n > 0 && !(n&(n-1));
}
// 0ms
bool isPowerOfTwo(int n) {
return n > 0 && __builtin_popcount(n) < 2;
}
```python [-python 0ms]
// 0ms def isPowerOfTwo(_, n: int) -> bool: return n > 0 and not n & (n-1)
# 8.08.2025
[808. Soup Servings](https://leetcode.com/problems/soup-servings/description/) medium
[blog post](https://leetcode.com/problems/soup-servings/solutions/7057068/kotlin-rust-by-samoylenkodmitry-8a2i/)
[substack](https://open.substack.com/pub/dmitriisamoilenko/p/8082025-808-soup-servings?r=2bam17&utm_campaign=post&utm_medium=web&showWelcomeOnShare=true)
[youtube](https://youtu.be/teBK2YRCO3M)

https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
#### Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1074
#### Problem TLDR
Probability A empty first plus both empty /2 #medium #dp #probability
#### Intuition
The probability is the number of good events divided by the total number of events.
Each layer deep result should be divided by current layer number of events: `p_curr = (p deep) / curr_total_events`
```j
// 50 50
// 1: 100+0 - end A first
// 2: 70+25 - end A first
// 3: 50+50 - end both
// 4: 25+75 - end B first
// P(a first) = 2/4
// P(both) = 1/4
// 2/4 + 1/2 * 1/4 = 1/4 * (2 + 0.5) = 0.625
// 100 100
// 1: 100+0 A first
// 2: 70+25 30 75
// 1: 100+0 A first
// 2: 70+25 A first
// 3: 50+50 A first
// 4: 20+75 B first
// pa = 3/4 pboth = 0 p = 3/4
// 3: 50+50 50 50
// 1: 100+0 A first
// 2: 70+25 A first
// 3: 50+50 both
// 4: 20+75 B first
// pa = 2/4 pboth = 1/4 p = 1/4 * (2+0.5)
// 4: 25+75 75 25
// 1: 100+0 A first
// 2: 70+25 B first
// 3: 50+50 B first
// 4: 20+75 B first
// pa = 1/4 pboth=0 p=1/4
//
// p = 1/4 * (1 + 3/4 + 1/4*(2+0.5) + 1/4)
// = 1/4 * (2 + 1/4 + 2.5/4) = 0.71875
// can't use n directly, too big 10^9 660295675
// maybe after some number the answer is always 1
Approach
- just remember that on big numbers probabilities distribution collapses into the final value
Complexity
-
Time complexity: \(O(min(5000, n))\),
-
Space complexity: \(O(min(5000, n))\)
Code
// 8ms
val dp = HashMap<Pair<Int, Int>, Double>()
fun soupServings(a: Int, b: Int = a): Double = if (a > 5000) 1.0
else 0.25 * dp.getOrPut(a to b) {
if (a <= 0 && b <= 0) 2.0 else if (a <= 0) 4.0 else if (b <= 0) 0.0
else soupServings(a - 100, b) + soupServings(a - 75, b - 25) +
soupServings(a - 50, b - 50) + soupServings(a - 25, b - 75)
}
// 5ms
fun soupServings(n: Int): Double {
if (n > 5000) return 1.0
val N = 4 + (n+24) / 25; val p = Array(N) { DoubleArray(N) }
for (j in 0..4) for (i in j..<N) { p[j][i] = 1.0; p[j][j] = 0.5 }
for (a in 4..<N) for (b in 4..<N) p[a][b] = 0.25 *
(p[a-4][b] + p[a-3][b-1] + p[a-2][b-2] + p[a-1][b-3])
return p[N-1][N-1]
}
// 0ms
pub fn soup_servings(n: i32) -> f64 {
if n > 5000 { return 1.0 }
let n = ((n+124)/25) as usize; let mut p = vec![vec![0.0;n];n];
for j in 0..5 { for i in j..n { p[j][i] = 1.0; p[j][j] = 0.5 }}
for a in 4..n { for b in 4..n { p[a][b] = 0.25 *
(p[a-4][b] + p[a-3][b-1] + p[a-2][b-2] + p[a-1][b-3])}}; p[n-1][n-1]
}
// 0ms
double soupServings(int n) {
if (n > 5000) return 1.0;
int m = (n + 124)/25; double p[201][201]={0};
for (int j = 0; j < 5; ++j) for (int i = j; i < m; ++i) p[j][i]=1.0, p[j][j]=0.5;
for (int a = 4; a < m; ++a) for (int b = 4; b < m; ++b) p[a][b] = 0.25 *
(p[a-4][b] + p[a-3][b-1] + p[a-2][b-2] + p[a-1][b-3]);
return p[m-1][m-1];
}
// 9ms
def soupServings(self, n: int) -> float:
if n > 5000: return 1.0
m = (n + 124) // 25
p = [[0.0]*(m + 1) for _ in range(m + 1)]
for j in range(5):
for i in range(j, m): p[j][i] = 1.0
p[j][j] = 0.5
for a in range(4, m):
for b in range(4, m):
p[a][b] = 0.25*(p[a-4][b] + p[a-3][b-1] + p[a-2][b-2] + p[a-1][b-3])
return p[m-1][m-1]
7.08.2025
3363. Find the Maximum Number of Fruits Collected hard
blog post
substack
youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1073
Problem TLDR
Max 3 paths from corners to bottom end #hard
Intuition
Used the hints.
Two insights:
- middle only goes diagonal
- two other guys are the two separate searches
// dfs or bfs?
// greedy? - i think can be non-optimal
// either full search with bfs or dp with dfs+cache
// 3x3x3 = 27 steps by each bfs layer
// exactly n-1 steps AND reach n,n cell - no non-optimal steps
// i am writing the dfs+dp, the growth factor is n^27
// let's use hints
// nice, child 0 can only move diagonal (as by rules)
// child 1&2 can't cross diagonal
// my solution TLE
// look for other hints, no new information
// are we expected use raw arrays? bottom up?
// expected bottom up
// children b and c can go separate
Approach
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n^2)\)
Code
// 697ms
fun maxCollectedFruits(f: Array<IntArray>, n: Int = f.lastIndex): Int {
data class P(val x: Int, val y: Int) { val i = x < 0 || y < 0 || x > n || y > n }
fun dfs(p: P, d: List<Int>, dp: HashMap<P, Int> = HashMap()): Int = dp.getOrPut(p) {
f[p.y][p.x] + (0..2).maxOf {
val b = P(p.x + d[it*2], p.y + d[it*2 + 1])
if (!b.i && (b.y - b.x).sign == d[2].sign) dfs(b, d, dp) else 0
}}
val b = listOf(1, 1, -1, 1, 0, 1); val c = listOf(1, 0, 1, 1, 1, -1)
return dfs(P(n, 0), b) + dfs(P(0, n), c) + (0..n).sumOf { f[it][it] }
}
6.08.2025
3479. Fruits Into Baskets III medium
blog post
substack
youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1072
Problem TLDR
Place fruits left to right to first available bucket #medium #segment_tree
Intuition
Use a segment tree: range 4length, 2i+1,2i+2, compare max(l, r)
Approach
- try to memorize how segment tree code looks like
- the iterative segment tree: size of 2*next_power_of_two, copy array to the second part
Complexity
-
Time complexity: \(O(nlog(n))\)
-
Space complexity: \(O(n)\)
Code
// 45ms
fun numOfUnplacedFruits(f: IntArray, b: IntArray): Int {
var sz = 1; var i = 1; while (sz < b.size) sz *= 2
val s = IntArray(sz * 2); for (i in b.indices) s[sz + i] = b[i]
for (i in sz - 1 downTo 1) s[i] = max(s[i*2], s[i*2+1])
return f.count { f ->
while (i < sz) { i *= 2; if (s[i] < f) i++ }
(i >= s.size || s[i] < f).also { if (!it) {
s[i] = 0; while (i > 1) { s[i/2] = max(s[i], s[i xor 1]); i /= 2 }
} else i = 1 }
}
}
// 58ms
fun numOfUnplacedFruits(f: IntArray, b: IntArray): Int {
val s = IntArray(b.size * 4)
fun make(i: Int, l: Int, h: Int): Int {
if (l == h) { s[i] = b[l]; return s[i] }
val m = (l + h) / 2
s[i] = max(make(2*i+1, l, m), make(2*i+2, m + 1, h))
return s[i]
}
fun check(v: Int, i: Int, l: Int, h: Int): Boolean =
if (l == h) {
if (s[i] >= v) { s[i] = 0; true } else false
} else if (s[i] < v) false else {
val m = (l + h) / 2
val r = check(v, 2*i+1, l, m) || check (v, 2*i+2, m + 1, h)
s[i] = max(s[2*i+1], s[2*i+2]); r
}
make(0, 0, b.lastIndex)
return f.size - f.count { check(it, 0, 0, b.lastIndex) }
}
// 40ms
pub fn num_of_unplaced_fruits(f: Vec<i32>, b: Vec<i32>) -> i32 {
fn make(i: usize, l: usize, h: usize, s: &mut Vec<i32>, b: &Vec<i32>) {
if l == h { s[i] = b[l] } else {
let m = (l + h) / 2; make(2*i+1, l, m, s, b); make(2*i+2, m+1, h, s, b);
s[i] = s[2*i+1].max(s[2*i+2])
}}
fn c(v: i32, i: usize, l: usize, h: usize, s: &mut Vec<i32>) -> bool {
if l == h {
if s[i] >= v { s[i] = 0; true } else { false }
} else if s[i] < v { false } else {
let m = (l + h) / 2; let r = c(v, 2*i+1, l, m, s) || c(v, 2*i+2, m+1, h, s);
s[i] = s[2*i+1].max(s[2*i+2]); r
}}
let mut s = vec![0; b.len() * 4]; make(0, 0, b.len()-1, &mut s, &b);
(f.len() - (0..f.len()).filter(|&i| c(f[i], 0, 0, b.len()-1, &mut s)).count()) as _
}
// 27ms
pub fn num_of_unplaced_fruits(f: Vec<i32>, b: Vec<i32>) -> i32 {
let sz = b.len().next_power_of_two(); let mut s = vec![0; 2 * sz];
s[sz..sz + b.len()].copy_from_slice(&b); let mut r = 0;
for i in (1..sz).rev() { s[i] = s[2*i].max(s[2*i+1]) }
for f in f {
let mut i = 1; while i < sz { i *= 2; if s[i] < f { i += 1 }}
if i >= sz && s[i] >= f {
s[i] = 0; while i > 1 { i /= 2; s[i] = s[i*2].max(s[i*2+1]) }
} else { r += 1 }
} r
}
// 45ms
int numOfUnplacedFruits(vector<int>& f, vector<int>& b) {
int n = size(b), sz = 1, r = 0; while (sz < n) sz <<= 1;
vector<int> s(2*sz); copy(begin(b), end(b), begin(s) + sz);
for (int i = sz-1; i; --i) s[i] = max(s[i<<1], s[i<<1|1]);
for (int f: f) {
int i = 1; while (i < sz) { i <<= 1; if (s[i] < f) ++i; }
if (i < 2*sz && s[i] >= f) {
s[i] = 0; for (; i; i >>= 1) s[i>>1] = max(s[i], s[i^1]);
} else ++r;
} return r;
}
// 1591ms
def numOfUnplacedFruits(self, f: List[int], b: List[int]) -> int:
n = len(b); sz = 1
while sz < n: sz *= 2
s = [0] * (2 * sz); s[sz:sz + n] = b; r = 0
for i in range(sz - 1, 0, -1): s[i] = max(s[i<<1], s[i<<1|1])
for f in f:
i = 1
while i < sz: i <<= 1; i += s[i] < f
if i < 2 * sz and s[i] >= f:
s[i] = 0;
while i: s[i>>1] = max(s[i], s[i^1]); i >>= 1
else: r += 1
return r
5.08.2025
3477. Fruits Into Baskets II easy
blog post
substack
youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1071
Problem TLDR
Place fruits left to right to first available bucket #easy #simulation
Intuition
Simulate the process, brute-force is accepted.
Approach
- the code is simpler with decreasing result from size
- refresh your memory about segment trees: range 4length, 2i+1,2i+2, compare max(l, r)
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(1)\) or O(n) if not modyfying the inputs
Code
// 24ms
fun numOfUnplacedFruits(f: IntArray, b: IntArray) = f.size -
f.count { f -> b.indices.any { i -> (b[i] >= f).also { if (it) b[i] = 0}}}
// 13ms
fun numOfUnplacedFruits(f: IntArray, b: IntArray): Int {
val s = IntArray(4 * b.size)
fun make(l: Int, h: Int, i: Int): Int {
if (l == h) { s[i] = b[l]; return s[i] }
val m = (l + h) / 2
s[i] = max(make(l, m, 2 * i + 1), make(m + 1, h, 2 * i + 2))
return s[i]
}
fun q(x: Int, l: Int, h: Int, i: Int): Boolean =
if (l == h) if (s[i] >= x) { s[i] = 0; true } else false
else if (s[i] >= x) {
val m = (l + h) / 2
val r = q(x, l, m, 2 * i + 1) || q(x, m + 1, h, 2 * i + 2)
s[i] = max(s[2 * i + 1], s[2 * i + 2]); r
} else false
make(0, b.lastIndex, 0)
return f.size - f.count { q(it, 0, b.lastIndex, 0) }
}
// 3ms
fun numOfUnplacedFruits(f: IntArray, b: IntArray): Int {
var res = f.size
for (f in f) for (i in b.indices)
if (b[i] >= f) { b[i] = 0; res--; break }
return res
}
// 0ms
pub fn num_of_unplaced_fruits(f: Vec<i32>, mut b: Vec<i32>) -> i32 {
let mut r = f.len() as i32;
for f in f { for i in 0..b.len() { if b[i] >= f { b[i] = 0; r -= 1; break }}} r
}
// 0ms
int numOfUnplacedFruits(vector<int>& f, vector<int>& b) {
int c = 0;
for (int f: f) for (int& b: b) if (b >= f) { b = 0, ++c; break; };
return size(b) - c;
}
// 19ms
def numOfUnplacedFruits(self, f: List[int], b: List[int]) -> int:
r = len(b)
for f in f:
for i, v in enumerate(b):
if v >= f: b[i] = 0; r -= 1; break
return r
4.08.2025
904. Fruit Into Baskets medium
blog post
substack
youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1070
Problem TLDR
Max consequent two-types range #medium #counting
Intuition
Scan from left to right. Count current type and previous. On a third type drop the previous.
Approach
- how many extra variables we need?
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 39ms
fun totalFruit(f: IntArray): Int {
var p = -1; var c = 0; var j = 0
return f.withIndex().maxOf { (i, t) ->
if (t != f[j]) {
if (t != p) c = i - j
p = f[j]; j = i
}
++c
}
}
// 0ms
pub fn total_fruit(f: Vec<i32>) -> i32 {
let (mut p, mut k, mut j) = (-1, 0, 0);
f.iter().enumerate().map(|(i, &t)| {
if t != f[j] {
if t != p { k = j }
p = f[j]; j = i
}
i - k + 1
}).max().unwrap() as _
}
// 0ms
int totalFruit(vector<int>& f) {
int r = 0;
for (int i = 0, j = 0, p = -1, k = 0; i < size(f); ++i) {
if (f[i] != f[j]) {
if (f[i] != p) k = j;
p = f[j]; j = i;
}
r = max(r, i - k + 1);
} return r;
}
// 77ms
def totalFruit(self, f: List[int]) -> int:
r = j = k = 0; p = -1
for i, t in enumerate(f):
if t != f[j]:
if t != p: k = j
p,j = f[j],i
r = max(r, i - k + 1)
return r
3.08.2025
2106. Maximum Fruits Harvested After at Most K Steps hard
blog post
substack
youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1069
Problem TLDR
Max values k steps from start point #hard #sliding_window
Intuition
// k = 30
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// [[0,7],[7,4],[9,10],[12,6],[14,8],[16,5],[17,8],[19,4],[20,1],[21,3],[24,3],[25,3],[26,1],[28,10],[30,9],[31,6],[32,1],[37,5],[40,9]]
// sp
Sliding window:
- always move the right border
- move left until condition
- update max
The main hardness is to peek the smaller path between the two: go back then forward, or go forward then back.
Approach
- the queue is not necessary, just a left pointer is enough
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 15ms
fun maxTotalFruits(f: Array<IntArray>, sp: Int, k: Int): Int {
var q = 0; var sum = 0
return f.maxOf { (x, a) ->
while (min(sp + x - 2*f[q][0], 2*x - sp - f[q][0]) > k) sum -= f[q++][1]
if (abs(x - sp) > k) { ++q; 0 } else { sum += a; sum }
}
}
// 3ms
fun maxTotalFruits(f: Array<IntArray>, sp: Int, k: Int): Int {
var q = 0; var sum = 0; var r = 0
for ((x, a) in f) {
if (x - sp > k) break; if (sp - x > k) { ++q; continue }
while (min(sp + x - 2*f[q][0], 2*x - sp - f[q][0]) > k) sum -= f[q++][1]
sum += a; r = max(r, sum)
}
return r
}
// 11ms
pub fn max_total_fruits(f: Vec<Vec<i32>>, sp: i32, k: i32) -> i32 {
let (mut q, mut s) = (0, 0);
f.iter().map(|v| {
while (sp + v[0] - 2*f[q][0]).min(2*v[0] - sp - f[q][0]) > k { s -= f[q][1]; q += 1 }
if (v[0] - sp).abs() > k { q += 1; 0 } else { s += v[1]; s }
}).max().unwrap()
}
// 2ms
int maxTotalFruits(vector<vector<int>>& f, int sp, int k) {
int q = 0, s = 0, r = 0;
for (auto& v: f) {
if (v[0] - sp > k) break; if (sp - v[0] > k) { ++q; continue; }
while (min(sp + v[0] - 2*f[q][0], 2*v[0] - sp - f[q][0]) > k) s -= f[q++][1];
r = max(r, s += v[1]);
} return r;
}
// 104ms
def maxTotalFruits(self, f: List[List[int]], s: int, k: int) -> int:
q = r = t = 0
for x, a in f:
if s - x > k: q += 1; continue
while min(s + x - 2*f[q][0], 2*x - s - f[q][0]) > k: t -= f[q][1]; q += 1
t += a if x - s <= k else 0; r = max(r, t)
return r
2.08.2025
2561. Rearranging Fruits hard
blog post
substack
youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1068
Problem TLDR
Min swaps cost to make a==b #hard #greedy
Intuition
Didn’t solved
// first idea:
// count freq1, freq2
// f1[i] % 2 != 0, f2[j] % 2 != 0
// in f1 and not in f2 (split by half)
// in f2 and not in f1 (split by half)
// f1[x] != f2[x] then move
// 1: 2 0 split, cost = 1 * 2/2 = 1
// 2: 3 1 move, 3 - (3+1)/2, b[i] * (max(f1,f2) - (f1+f2)/2)
// we have array of costs:, count should be % 2
// c1 c2 c3 c4 and have to pick pairs (min,max),
// sort, then two pointers
// wrong answer (14 minute)
// [84,80,43,8,80,88,43,14,100,88]
// [32,32,42,68,68,100,42,84,14,8]
// {84=1, 80=2, 43=2, 8=1, 88=2, 14=1, 100=1}
// {32=2, 42=2, 68=2, 100=1, 84=1, 14=1, 8=1}
// 8, 14, 43, 43, 80, 80, 84, 88, 88, 100 a
// 8, 14, 32, 32, 42, 42, 68, 68, 84, 100 b
// move x=80 a=2 b=0, cost=80
// move x=43 a=2 b=0, cost=43
// move x=88 a=2 b=0, cost=88
// move x=32 a=0 b=2, cost=32
// move x=42 a=0 b=2, cost=42
// move x=68 a=0 b=2, cost=68
// [32, 42, 43, 68, 80, 88]
// b b a b a a
// 43 80 88
// 32 42 68 32,88 + 43,68 + 42,80 = 32+43+42 = 32+85 = 117
// wrong answer how is it 48? where is 48 from?
// took hints (29 minutes)
// the hint in the comments: `use the minimum element 8 to do 6 swaps.` (what??)
// how does indirect swap works?
//
// 2 2 100 100
// 3 3 200 200
//
// 3 2 100 100 2
// 3 2 200 200
//
// 2 200 100 100 2
// 3 3 200 2
//
// 2 200 2 100 2
// 3 3 200 100
//
// 2 200 3 100 2 2x4=8
// 3 2 200 100
//
// or
// 200 2 100 100 2
// 3 3 2 200
//
// 200 2 3 100 3 2+3=5
// 100 3 2 200
// 1 100 100
// 1 200 200
//
// 200 100 100 1
// 1 1 200
//
// 200 1 100 1
// 1 100 200
//
// 4 4 4 4 3
// 3
//
// 4 4 4 3 3 3
// 5 5 5 5 4
//
// 4 4 4 3 5 3
// 5 5 5 3 4
//
// 4 4 4 5 5 3
// 5 5 3 3 4
//
// 4 4 3 5 5 3
// 5 5 3 4 4 4x3=12
//
// another corner case if smallest itself in the wrong position
// 28 wrong positions, ans smallest here, so 27
```j
What went wrong:
* I was trying to cut corners with some complex `algorithm` to make greedy work with entire groups
* however, with greedy, we have to simulate each step individually, hence make a greedy choice for each swapped value, between itself and `2 * min` jump
#### Approach
* the solution from https://leetcode.com/problems/rearranging-fruits/solutions/3143735/ordered-map/ has mind blowing trick: `min(sw, abs(f) / 2)`; we `assume` that the optimal swaps count can't be more than `sw` (swaps from one side to another)
* to make greedy optimization for groups is to make at most `sw` swaps
#### Complexity
- Time complexity:
$$O(nlog(n))$$
- Space complexity:
$$O(n)$$
#### Code
```kotlin
// 101ms
fun minCost(b1: IntArray, b2: IntArray): Long {
val f1 = b1.groupBy { it }; val f2 = b2.groupBy { it }
val min = min(b1.min(), b2.min())
return (f1.keys + f2.keys).flatMap { x ->
val a = f1[x]?.size ?: 0; val b = f2[x]?.size ?: 0;
if ((a + b) % 2 > 0) return -1L
List(abs(a - b) / 2) { x }
}.run { sorted().take(size/2).sumOf { 1L * min(it, 2 * min) }}
}
// 71ms
fun minCost(a: IntArray, b: IntArray): Long {
val m = TreeMap<Int, Int>(); var sw = 0; var r = 0L; val min = min(a.min(), b.min())
for (x in a) m[x] = (m[x] ?: 0) + 1; for (x in b) m[x] = (m[x] ?: 0) - 1
for ((x, f) in m) { if (f % 2 != 0) return -1L; sw += max(0, f / 2) }
for ((x, f) in m) {
val take = min(sw, abs(f) / 2)
r += 1L * take * min(x, min * 2)
sw -= take; if (sw == 0) break
}
return r
}
1.08.2025
118. Pascal’s Triangle easy
blog post
substack
youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1067
Problem TLDR
Pascal’s Triangle #easy
Intuition
Classic problem, reuse the previous row.
Approach
- many ways to write this: fold, scan, recursion, zip
Complexity
-
Time complexity: \(O(2^n)\)
-
Space complexity: \(O(2^n)\)
Code
// 15ms
fun generate(n: Int) = (2..n).runningFold(listOf(1))
{ r, t -> listOf(1) + r.windowed(2) { it.sum() } + 1 }
// 0ms
pub fn generate(n: i32) -> Vec<Vec<i32>> {
(0..n).scan(vec![1], |c, _| { let r = c.clone();
*c = vec![vec![1], c.windows(2).map(|w| w[0] + w[1]).collect(), vec![1]].concat();
Some(r)
}).collect()
}
// 0ms
vector<vector<int>> generate(int n) {
if (n == 1) return 1; auto p = generate(n - 1); vector<int>r{1};
for (int i = 1; i < size(p[n - 2]); ++i)
r.push_back(p[n - 2][i - 1] + p[n - 2][i]);
r.push_back(1); p.push_back(r); return p;
}
// 0ms
def generate(self, n: int) -> List[List[int]]:
r=[]
for _ in[0]*n:r+=[[1]]if not r else[[1]+[a+b for a,b in zip(r[-1],r[-1][1:])]+[1]]
return r
31.07.2025
898. Bitwise ORs of Subarrays medium
blog post
substack
youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1066
Problem TLDR
Uniq OR-subarrays #medium #dp #bits
Intuition
// 101
// 111
// 010
//
// 001
// 010
// 110
// 100 brainteaser, what's the rule?
// 1000
// 1010
// 1001
// 1101 should have some bits that are not filled previosly
// and propagate this bits up to the latest index where this bit was seen
My idea:
- store last visited bits positions
- for each new bit propagate it up to last visited
Other ideas:
- brute-force, but keep intermediate results in a set to reduce space and time
-
same as mine core, but instead of tracking bits, modify array and go up until a[j] a[i] != a[j]
Approach
- clever optimization from https://leetcode.com/problems/bitwise-ors-of-subarrays/solutions/166832/c-simplest-fastest-224-ms/ by using the fact: each new bit increases the number, so numbers are growing, no need for set (but still need at the end, as it is a series of growing parts)
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(r)\)
Code
// 165ms
fun subarrayBitwiseORs(n: IntArray): Int {
val s = ArrayList<Int>(); var a = 0; var b = 0
for (x in n) {
a = b; b = s.size; s += x
for (j in a..<b) if (s.last() != s[j] or x) s += s[j] or x
}
return s.toSet().size
}
// 155ms
fun subarrayBitwiseORs(a: IntArray): Int {
val s = a.toHashSet(); val l = IntArray(30)
for ((i, x) in a.withIndex()) {
var j = i; var c = x
for (b in 0..29) if (x shr b and 1 > 0) {
while (j > l[b]) { c = c or a[--j]; s += c }
l[b] = i
}
}
return s.size
}
// 126ms
fun subarrayBitwiseORs(a: IntArray): Int {
val s = a.toHashSet()
for (i in a.indices) {
var j = i - 1
while (j >= 0 && a[i] or a[j] != a[j]) { a[j] = a[i] or a[j]; s += a[j--] }
}
return s.size
}
// 58ms
pub fn subarray_bitwise_o_rs(a: Vec<i32>) -> i32 {
let (mut s, mut l) = (vec![], [0; 30]);
for i in 0..a.len() {
let x = a[i]; let (mut j, mut c) = (i, x); s.push(x);
for b in 0..30 { if x >> b & 1 > 0 {
while j > l[b] { j -= 1; c |= a[j]; s.push(c); }
l[b] = i
}}
} s.sort_unstable(); s.dedup(); s.len() as _
}
// 42ms
pub fn subarray_bitwise_o_rs(mut a: Vec<i32>) -> i32 {
let mut s = vec![];
for i in 0..a.len() {
let mut j = i - 1; s.push(a[i]);
while j < a.len() && a[i] | a[j] != a[j] { a[j] |= a[i]; s.push(a[j]); j -= 1 }
} s.sort_unstable(); s.dedup(); s.len() as _
}
// 256ms
int subarrayBitwiseORs(vector<int>& n) {
unordered_set<int> s;
for (int i = 0; i < size(n); ++i) {
s.insert(n[i]);
for (int j = i - 1; j >= 0 && ((n[i] | n[j]) != n[j]); --j)
n[j] |= n[i], s.insert(n[j]);
} return size(s);
}
// 499ms
def subarrayBitwiseORs(self, a: List[int]) -> int:
s,o=set(),set();[s.update(o:={x|y for y in o}|{x}) for x in a]; return len(s)
30.07.2025
2419. Longest Subarray With Maximum Bitwise AND medium
blog post
substack
youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1065
Problem TLDR
Longest max OR subarray #medium #counting
Intuition
// 011
// 010
// 111
// 100
Each new element decreases OR, consider only equal values.
Approach
- longest subarray of
maxes - many one-liners possible
- 09/2024 - 13 minutes, 07/2025 - 10 minutes
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 43ms
fun longestSubarray(n: IntArray, m: Int = n.max()) =
n.runningFold(0) { l, x -> if (x == m) l + 1 else 0 }.max()
// 4ms
fun longestSubarray(n: IntArray): Int {
var m = 0; var r = 0; var l = 0
for (x in n) if (x > m) { m = x; r = 1; l = 1 }
else if (x < m) l = 0 else r = max(r, ++l)
return r
}
// 0ms
pub fn longest_subarray(n: Vec<i32>) -> i32 {
n.into_iter().dedup_with_count()
.max_by_key(|&d| (d.1, d.0)).unwrap().0 as _
}
// 1ms
int longestSubarray(vector<int>& n) {
int r = 0;
for (int l = 0, m = 0; int x: n)
x > m ? m = x, l = 1, r = 1 :
x < m ? l = 0 : r = max(r, ++l);
return r;
}
// 36ms
def longestSubarray(self, n: List[int]) -> int:
m=max(n);return max(sum(1for _ in g) for x, g in groupby(n) if x==m)
29.07.2025
2411. Smallest Subarrays With Maximum Bitwise OR medium
blog post
substack
youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1064
Problem TLDR
Shortest max OR i.. subarrays #medium #two_pointers
Intuition
Go backwards solutions:
- Use bits frequency and two pointers: always expand, shrint while frequency is 2
- Use nearest bit occurence map, then total length is the max occurence pointer
Go forwards solution:
-
for each i go back and update answer[j–] while it is doing the update n[j] != n[j] n[i]
Approach
- the bits frequency is the most template-like for two-pointers
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 72ms
fun smallestSubarrays(n: IntArray): IntArray {
val f = IntArray(32); val r = IntArray(n.size); var j = n.lastIndex
for (i in n.lastIndex downTo 0) {
for (b in 0..31) if (n[i] shr b and 1 > 0) ++f[b]
while (i < j && (0..31).all { b -> f[b] > 1 || n[j] shr b and 1 < 1 }) {
for (b in 0..31) if (n[j] shr b and 1 > 0) --f[b]
j--
}
r[i] = j - i + 1
}
return r
}
// 29ms
fun smallestSubarrays(n: IntArray): IntArray {
val j = IntArray(30); val r = IntArray(n.size)
for (i in n.lastIndex downTo 0) {
for (b in 0..29) if (n[i] shr b and 1 > 0) j[b] = i
r[i] = max(1, j.max() - i + 1)
}
return r
}
// 6ms
fun smallestSubarrays(n: IntArray): IntArray {
val r = IntArray(n.size) { 1 }
for (i in n.indices) {
var j = i - 1
while (j >= 0 && n[j] != n[i] or n[j]) {
n[j] = n[j] or n[i]
r[j] = i - j-- + 1
}
}
return r
}
// 13ms
pub fn smallest_subarrays(n: Vec<i32>) -> Vec<i32> {
let (mut j, mut r) = ([0;30], vec![0; n.len()]);
for i in (0..n.len()).rev() {
for b in 0..30 { if n[i] >> b & 1 > 0 { j[b] = i } }
r[i] = 1.max(1 + *j.iter().max().unwrap() as i32 - i as i32)
} r
}
// 11ms
vector<int> smallestSubarrays(vector<int>& n) {
int j[30]={}, m = 0, k; vector<int> r(size(n));
for (int i = size(n) - 1; i >= 0; --i, m = 0) {
for (int b = 0; b < 30; ++b) k = n[i] >> b & 1, m = max(m, j[b] = max(j[b] * (1 - k), i * k));
r[i] = max(1, m - i + 1);
} return r;
}
// 588ms
def smallestSubarrays(self, n: List[int]) -> List[int]:
last = [0] * 30
res = []
for i in range(len(n) - 1, -1, -1):
for b in range(30):
if n[i] >> b & 1:
last[b] = i
res.append(max(1, max(last) - i + 1))
return res[::-1]
28.07.2025
2044. Count Number of Maximum Bitwise-OR Subsets medium
blog post
substack
youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1063
Problem TLDR
Subsequencies with max OR #medium #bits #backtrack
Intuition
Problem size is small - 16, traverse all subsequencies.
| The dp solution: dp[or] - number of subsets, dp[x | or_prev] += dp[or_prev] |
Approach
- 0..2^16 are all possible bitmasks
- the brute-force is slower than backtracking, every time goes from start: n2^n vs 2^n
- calculate max on the go
Complexity
-
Time complexity: \(O(n2^n)\)
-
Space complexity: \(O(1)\)
Code
// 69ms
fun countMaxOrSubsets(n: IntArray, o: Int = n.reduce(Int::or)) =
(0..(1 shl n.size)).count { m ->
o == n.indices.fold(0) { r, t -> r or (n[t] * (m shr t and 1)) }
}
// 53ms
fun countMaxOrSubsets(n: IntArray): Int {
var res = 0; var max = 0
for (m in 0..(1 shl n.size)) {
val v = n.indices.fold(0) { r, t -> r or (n[t] * (m shr t and 1)) }
if (v > max) { max = v; res = 1 } else if (v == max) ++res
}
return res
}
// 14ms
pub fn count_max_or_subsets(n: Vec<i32>) -> i32 {
let (mut r, mut o) = (0, 0);
for m in 0..=1 << n.len() as i32 {
let v = (0..n.len()).fold(0, |r, t| r | n[t] * (m >> t & 1));
if v > o { o = v; r = 0 }; if v == o { r += 1 }
} r
}
// 86ms
int countMaxOrSubsets(vector<int>& n) {
int max = 0, dp[1<<17]={1};
for (int x: n) {
for (int i = max; i >= 0; --i) dp[i | x] += dp[i];
max |= x;
} return dp[max];
}
// 14ms
def countMaxOrSubsets(self, n: List[int]) -> int:
return (f:=cache(lambda i,v,o=reduce(or_,n):n[i:] and f(i+1,v)+f(i+1,v|n[i]) or v==o))(0,0)
27.07.2025
2210. Count Hills and Valleys in an Array easy
blog post
substack
youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1062
Problem TLDR
Count hills and valleys #easy
Intuition
We have to remove duplications.
Clever ways to look at the problem:
- dedup
- count
slopesinstead: up, down, up, down… - compare only hills or valleys values
Approach
- duplicates are the corner case, failed the same way 1 year ago
- each language opens a new angle of implementation, try many
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 16ms
fun countHillValley(n: IntArray) =
(1..<n.lastIndex).count { i ->
val a = n[0]; val b = n[i]; val c = n[i + 1]
(a > b && b < c || a < b && b > c).also { if (it) n[0] = b }
}
// 11ms
fun countHillValley(n: IntArray): Int {
var p = 0
return n.filter { x -> x != p.also { p = x } }
.windowed(3)
.count { (a, b, c) -> (a > b) == (b < c) }
}
// 1ms
fun countHillValley(n: IntArray): Int {
var p = n[0]; var s = 0
return max(0, n.count { x ->
val cs = x.compareTo(p)
cs != 0 && cs != s.also { s = cs; p = x }} - 1)
}
// 0ms
pub fn count_hill_valley(mut n: Vec<i32>) -> i32 {
n.dedup();
n.windows(3).filter(|w| (w[0] > w[1]) == (w[1] < w[2])).count() as _
}
// 0ms
pub fn count_hill_valley(mut n: Vec<i32>) -> i32 {
n.iter().dedup().tuple_windows::<(_,_,_)>()
.filter(|(a, b, c)| (a > b) == (b < c)).count() as _
}
// 0ms
int countHillValley(vector<int>& n) {
int r = 0, p = n[0], s = 0;
for (int x: n) {
int cs = x > p ? 1 : x < p ? -1 : 0;
if (cs) r += cs != s, s = cs; p = x;
} return max(0, r - 1);
}
// 0ms
def countHillValley(self, n: List[int]) -> int:
d = [x for x,_ in groupby(n)]
return sum((a > b) == (b < c) for a, b, c in zip(d, d[1:], d[2:]))
26.07.2025
3480. Maximize Subarrays After Removing One Conflicting Pair hard
blog post
substack
youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1061
Problem TLDR
Max subarrays count without excluded pairs-1 #hard #greedy #line_sweep
Intuition
Didn’t solved.
// 1 2 3 4
// a b
// a b
// 1 2 3 4 5
// a b
// a b
// a b
// subproblem: nuber of subarrays with a and b separated
// 1 2 3 4 5 6 7 8 9
// a b
//
// for a: can't go past b, so it is number subarrays in 1..5 1..b-1
// 1 2 3 4 5, 12 23 34 45, 123 234 345, 1234 2345, 12345
// 5 + 4 + 3 + 2 + 1 = 5*(5 + 1)/2=15
//
// for b: can't go before a, 4..9 a+1..n, 6*7/2=21
//
// overlap: 4 5, 45 = b-a-1 = 2 * 3 /2 = 3
//
// subarrays 15+21-3=33 (b-1)*b/2 + (n-a)*(n-a+1)/2 - (b-a-1)*(b-a)/2
// n^2/2-na+n/2-a+ab
//
// reverse the problem: number of subarrays including a and b
// f(a) + f(n-b)
// all is f(n)
// now what if we have two pairs?
// 1 2 3 4 5 6 7 8 9
// a b
// a b
// . . . . . valid range
// . . . . . valid range
// a b is the pair intersection result (28 minute)
//
// what if pairs are not intersecting
// 1 2 3 4 5 6 7 8 9
// a b
// a b
// . . . valid
// . . . valid
// . . . . . valid
//
// more complex
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
// a b
// a b
// a b
// a b
// a b
// a b
// . . . .
// . . . .
// . . . . . . . . . .
// ..and so on, i use the hint at (36 minute)
// then i gave up and look for solution https://leetcode.com/problems/maximize-subarrays-after-removing-one-conflicting-pair/solutions/6527930/intuitive-solution-with-sorting-visually-explained/
// so, initial idea to sort was right
// then, how to scan and compute?
// we look for intervals between prev_max_a..max_a and tail after current b
// 12345678901234567890123
// a b n
// a b n
// a b n
// . ................
// ..... ............ c += (max1-max2)*tail = (5-1)*(23-8+1)
// ..... .......
// overlapping case:
// a b
// a b
// ..... ................
// .... ............
// total excluded is sum(max(a) * b_tail)
// current excluded is sum_overlaping(a1-a2) * b_tail
// we adding back maximum excluded value (while keeping track of overlaps)
Approach
- the overlapping part is the hardest to understand
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(1)\)
Code
// 450ms
fun maxSubarrays(n: Int, p: Array<IntArray>): Long {
for (p in p) if (p[0] > p[1]) p[0] = p[1].also { p[1] = p[0] }
Arrays.sort(p, compareBy{ it[1] })
var max1 = 0; var max2 = 0; var c = 0L; var maxc = 0L; var exc = 0L
for (i in p.indices) {
val (a, b) = p[i]; var tail = (if (i < p.size - 1) p[i + 1][1] else n + 1) - b
if (a > max1) { max2 = max1; max1 = a; c = 0 } else max2 = max(max2, a)
c += 1L * (max1 - max2) * tail
exc += 1L * max1 * tail
maxc = max(maxc, c)
}
return 1L * n * (n + 1) / 2 - exc + maxc
}
25.07.2025
3487. Maximum Unique Subarray Sum After Deletion easy
blog post
substack
youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1060
Problem TLDR
Max non-empty uniq subsequence sum #easy
Intuition
Remove all negatives, dedup all positives, then sum.
Approach
- careful with
non-empty, should take 1 negative
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 23ms
fun maxSum(n: IntArray) =
n.max().takeIf { it < 0 } ?:
n.filter { it > 0 }.distinct().sum()
// 12ms
fun maxSum(n: IntArray): Int {
val f = IntArray(101)
for (x in n) if (x >= 0) f[x] = x
return n.max().takeIf { it < 0 } ?: f.sum()
}
// 0ms
pub fn max_sum(mut n: Vec<i32>) -> i32 {
n.sort_unstable(); n.dedup();
if n[n.len() - 1] < 0 { n[n.len() - 1] }
else { n.retain(|&x| x > 0); n.into_iter().sum() }
}
// 1ms
int maxSum(vector<int>& n) {
int f[101]={}, m = n[0], s = 0;
for (int x: n) m = max(m, x), s -= x < 0 ? 0 : (f[x] - (f[x] = x));
return m < 0 ? m : s;
}
24.07.2025
2322. Minimum Score After Removals on a Tree hard
blog post
substack
youtube
https://dmitrysamoylenko.com/2023/07/14/leetcode_daily.html

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1059
Problem TLDR
Min(max_group_xor - min_group_xor) by removing 2 edges from tree #hard #uf
Intuition
Didn’t solved.
// xor(all) = X
// xor(B, C) = X xor A
// A = B xor C xor X
// min = max xor C xor X
// score = max - min = max - (max xor C xor X)
// I need max score
// score = A - A^C^X, A is max
// X = A^B^C
// A is max
// B is min
// C is X^max^min
// A - B =
//
// score^X = max^X - max^C
//
// going circles with xor arithmetics
//
// xor can decrease: 1 xor 1 = 0
// xor can increase: 0 xor 1 = 1
// 101^10 - 101^01 = 110 - 100 = 100
// ok forget about math, what about tree walk
// how to disconnect edge?
// 25 minutes, use hint
// first split a single edge
// A vs BC
// then choose the best second split point (how? 32 minute)
// if A is min, then look for max in BC
// if A is max, then look for min in BC
// if A is neutral - then it is irrelevant, we will traverse all possible A anyway
// ...............
// ..........A____B
// _____B.........A
// for each edge we have a pair A-BC
// max(max_A) - min(min_A) ? not that simple
// 50 minute gave up, gosh I even forgot we have to find the MINIMUM (max-min)
My intuition direction was on Union-Find, but I had a hard time computing the xor cases.
Some stolen solution intuition:
- precompute Union-Find results for all single edges: group
roots, and two values for(xorA, xorBC) - then again iterate
i, jand calculate 3 xors based onlogic
The tricky part, logic and I still have a hard time to really get it.
- on value we always take, let it be
c2 = A - we have
4 nodesof2disconnected edges(a-/-b), (c-/-d) - then the part I don’t fully get, look at the source (https://leetcode.com/problems/minimum-score-after-removals-on-a-tree/solutions/2199132/union-find-c-o-n-2-time-o-n-2-space-code-explanation/)
Approach
- don’t spend too much time hitting a head against the wall, but at least read, something will be absorbed anyway
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n^2)\)
Code
// 269ms
fun minimumScore(n: IntArray, es: Array<IntArray>): Int {
val us = Array(n.size) { IntArray(n.size) { it }}; val xs = Array(n.size) { IntArray(2) }
operator fun IntArray.div(x: Int): Int = if (get(x) == x) x else (this/get(x)).also { set(x, it) }
for (a in es.indices) {
val u = us[a]; val r = IntArray(n.size) { n[it] }
for (i in es.indices) if (i != a) {
val a = u/es[i][0]; val b = u/es[i][1]
if (a != b) { u[a] = b; r[b] = r[b] xor r[a]; r[a] = 0 }
}
xs[a][0] = r[u/es[a][0]]; xs[a][1] = r[u/es[a][1]]; us[a] = u
}
var res = Int.MAX_VALUE
for (i in es.indices) for (j in es.indices) if (i != j) {
val (a, b) = es[i]; var (c, d) = es[j]; var c1 = 0; var c2 = 0; var c3 = 0
if (us[i]/a == us[i]/c) {
c1 = if (us[j]/a == us[j]/c) xs[j][1] else xs[j][0]
c2 = xs[i][1]; c3 = c1 xor xs[i][0]
} else {
c1 = if (us[j]/b == us[j]/c) xs[j][1] else xs[j][0]
c2 = xs[i][0]; c3 = c1 xor xs[i][1]
}
res = min(res, maxOf(c1, c2, c3) - minOf(c1, c2, c3))
}
return res
}
23.07.2025
1717. Maximum Score From Removing Substrings medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1058
Problem TLDR
Max removals ab=x, ba=y #medium #stack
Intuition
Problem is symmetric, reverse for x less than y. Scan, put ‘a’ to stack, pop when meet ‘b’, mark removed. Then scan again, but for ‘ba’.
Notice, there are islands of ‘b’’s and ‘a’’s: we can do a single scan, and check ‘ba’ when we finish the curren island.
Now, the crazy part: notice how the patterns of ‘a’s and ‘b’s are always the same in the stack bbbaaa, so we actually don’t have to use stack, just count.
Approach
- the finish line can be
s + '.'or just do one extra calculation at the end
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 75ms
fun maximumGain(s: String, x: Int, y: Int): Int {
var r = 0; val st = Stack<Char>(); val st2 = Stack<Char>()
val (a, b) = if (x < y) 'b' to 'a' else 'a' to 'b'
val (x, y) = max(x, y) to min(x, y)
for (c in s + '.')
if (c == a) st += a
else if (c == b) {
if (st.size > 0 && st.peek() == a) { st.pop(); r += x } else st += b
} else {
for (c in st)
if (c == b) st2 += c
else if (c == a) {
if (st2.size > 0 && st2.peek() == b) { st2.pop(); r += y }
}
st.clear(); st2.clear()
}
return r
}
// 31ms
fun maximumGain(s: String, x: Int, y: Int): Int {
if (x < y) return maximumGain(s.reversed(), y, x)
var a = 0; var b = 0; var r = 0
for (c in s)
if (c == 'a') ++a
else if (c == 'b') if (a > 0) { --a; r += x } else ++b
else { r += y * min(a, b); a = 0; b = 0 }
return r + y * min(a, b)
}
// 4ms
pub fn maximum_gain(mut s: String, mut x: i32, mut y: i32) -> i32 {
let s: Vec<_> = if x < y { s.bytes().rev().collect() } else { s.into_bytes() };
let (mut a, mut b, mut r) = (0, 0, 0); (x, y) = (x.max(y), x.min(y));
for c in s.into_iter() {
if c == b'a' { a += 1 }
else if c == b'b' { if a > 0 { a -= 1; r += x } else { b += 1 } }
else { r += y * a.min(b); a = 0; b = 0 }
} r + y * a.min(b)
}
// 4ms
int maximumGain(string s, int x, int y) {
if (x < y) reverse(begin(s), end(s)), swap(x, y);
int a = 0, b = 0, r = 0;
for (char c : s)
if (c == 'a') a++;
else if (c == 'b') a ? (a--, r += x) : b++;
else r += y * min(a, b), a = b = 0;
return r + y * min(a, b);
}
22.07.2025
1695. Maximum Erasure Value medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1057
Problem TLDR
Max unique subarray sum #medium #sliding_window
Intuition
Sliding window:
- expand every time
- shrink until condition
Approach
- use array for frequency map
- current index is irrelevant, just decrease the frequency
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 33ms
fun maximumUniqueSubarray(n: IntArray): Int {
val f = IntArray(10001); var j = 0; var s = 0
return n.maxOf { x -> ++f[x]; s += x
while (f[x] > 1) { s -= n[j]; --f[n[j++]] }; s
}
}
// 8ms
fun maximumUniqueSubarray(n: IntArray): Int {
val f = IntArray(10001); var j = 0; var r = 0; var s = 0
for (x in n) {
++f[x]; s += x
while (f[x] > 1) { s -= n[j]; --f[n[j++]] }
r = max(r, s)
}
return r
}
// 0ms
pub fn maximum_unique_subarray(n: Vec<i32>) -> i32 {
let (mut f, mut j, mut s) = ([0; 10001], 0, 0);
n.iter().map(|&x| {
f[x as usize] += 1; s += x;
while f[x as usize] > 1 { s -= n[j]; f[n[j] as usize ] -= 1; j += 1 }; s
}).max().unwrap()
}
// 3ms
int maximumUniqueSubarray(vector<int>& n) {
int f[10001] = {}, j = 0, r = 0, s = 0;
for (auto x: n) {
++f[x]; s += x;
while (f[x] > 1) s -= n[j], --f[n[j++]];
r = max(r, s);
} return r;
}
21.07.2025
1957. Delete Characters to Make Fancy String easy
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1056
Problem TLDR
No three chars repeats #easy
Intuition
Scan, count, filter.
Approach
- make separate decisions for counter and for appending
- there are Regex way, chunks way, dedup way
- leetcode has itertools available
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 193ms
fun makeFancyString(s: String) = s
.replace(Regex("(.)\\1{2,}"), "$1$1")
// 24ms
fun makeFancyString(s: String) = s
.filterIndexed { i, c -> i < 2 || s[i - 2] != c || s[i - 1] != c }
// 17ms
fun makeFancyString(s: String) = buildString {
var p = '.'; var pc = 0
for (c in s) {
if (c == p) ++pc else pc = 1
if (pc < 3) append(c)
p = c
}
}
// 53ms
pub fn make_fancy_string(mut s: String) -> String {
s.chars().dedup_with_count().into_iter()
.map(|(cnt, c)| c.to_string().repeat(2.min(cnt))).collect()
}
// 11ms
pub fn make_fancy_string(s: String) -> String {
String::from_utf8_lossy(
&s.bytes().enumerate().filter(|&(i, b)|
i < 2 || s.as_bytes()[i - 2] != b || s.as_bytes()[i - 1] != b)
.map(|(i, b)| b).collect::<Vec<_>>()).into()
}
// 5ms
pub fn make_fancy_string(mut s: String) -> String {
let (mut a, mut b) = ('.', '.');
s.retain(|c| { let r = a != c || b != c; a = b; b = c; r }); s
}
// 2826ms
string makeFancyString(string s) {
return regex_replace(s, regex("(.)\\1\\1+"), "$1$1");
}
20.07.2025
1948. Delete Duplicate Folders in System hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1055
Problem TLDR
Remove duplicate folder trees #hard #trie
Intuition
// a
// c
// d
// a/b
// c/b
// d/a
// go backwards: corner case is collision `a with d/a`
// first avoid parents: a vs a/b, we should skip a, for same startswith, pick longest
// too complex, maybe should go forward with trie
The hardness is the correct implementation:
- build the tree keys
- count them
- remove all with count > 1
Approach
- we can do two DFS or a single DFS but with worse time complexity to merge indices
Complexity
-
Time complexity: \(O(nlogn)\), worst case is n^2 for long graph nodes
-
Space complexity: \(O(n)\)
Code
// 189ms
fun deleteDuplicateFolder(p: List<List<String>>) = buildList<List<String>> {
class T(val i: HashSet<Int> = HashSet()): TreeMap<String, T>()
val r = T(); val m = HashMap<String, T>()
for (j in p.indices) p[j].fold(r) { t, f -> t.getOrPut(f, ::T).also { it.i += j }}
fun dfs(t: T): String = t.map { (f, nt) -> "$f[${ dfs(nt) }]" }.toString().also { k ->
if (t !== r) for (nt in t.values) t.i += nt.i
if (t.size > 0 && k in m) r.i += m[k]!!.i + t.i else m[k] = t
}
dfs(r); for (i in p.indices) if (i !in r.i) add(p[i])
}
19.07.2025
1233. Remove Sub-Folders from the Filesystem hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1054
Problem TLDR
Fold folders #medium
Intuition
Naive way: make set of folders, check each folder sub-paths to be in this set. Clever way: sort folders, naturally the previous would be the parent if match.
Approach
- Trie gives a worse performance (HashMap based) 27ms vs 5ms
Complexity
-
Time complexity: \(O(nlogn)\) or O(nl)
-
Space complexity: \(O(n)\)
Code
// 116ms
fun removeSubfolders(f: Array<String>) = buildList<String> {
val s = f.toSet()
for (f in f) {
var pref = ""; var skip = false
for (x in f.split("/")) {
pref += "$x"
if (pref != f && pref in s) { skip = true; break }
pref += "/"
}
if (!skip) add(f)
}
}
// 78ms
fun removeSubfolders(f: Array<String>) = buildList<String> {
f.sort()
for (f in f) if (size < 1 || !f.startsWith("${last()}/")) this += f
}
// 25ms
pub fn remove_subfolders(mut f: Vec<String>) -> Vec<String> {
#[derive(Default)] struct T(bool, HashMap<u8, T>);
let (mut tr, mut r) = (T::default(), vec![]); f.sort_unstable();
'o: for w in f { let mut t = &mut tr;
for b in w.bytes().chain(once(b'/')) {
t = t.1.entry(b).or_default(); if t.0 { continue 'o }
}
t.0 = true; r.push(w)
} r
}
// 5ms
pub fn remove_subfolders(mut f: Vec<String>) -> Vec<String> {
let mut r: Vec<String> = vec![]; f.sort_unstable();
for f in f {
if r.last().map_or(true, |l| f.len() < l.len() ||
&f[..l.len()] != l || f.as_bytes()[l.len()] != b'/') { r.push(f) }
} r
}
// 59ms
vector<string> removeSubfolders(vector<string>& f) {
sort(begin(f), end(f)); vector<string> r;
for (auto f: f) if (!size(r) || f.find(r.back() + "/")) r.push_back(f);
return r;
}
18.07.2025
2163. Minimum Difference in Sums After Removal of Elements hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1053
Problem TLDR
Min first half - second half after removing n/3 #hard #heap
Intuition
Used the hint:
- consider each index as partition point,
min sum before - max sum after
// 795813
// remove big left, small right
// order inside parts doesn't matter
// left = 795 right = 813
// but if removed parts diff > 2 number migrates
// 5 813
// 8 goes left
// 58 13
// 991199
// 991 199 d =9+9+1 - 1 +9 +9 = 19 - 19 = 0
// 9 91 199 d = 9+1 - 1+9+9 = 10-19 = -9
// 99 1 199 d = 1 - 1+9+9 = -18, but 1 goes left
// 1+1 - 9+9 = -16
//
// 11 99
// ok but how to shift mid if it was removed? (21 minute)
// used hints: find min/max n-sum for prefix/suffix for every i
My own idea was to maintain two heaps and poll elements from them, but I was stuck with how to balance them correctly.
Approach
- carefull with off-by-ones, sums should not overlap
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(n)\), or O(n / 3)
Code
// 109ms
fun minimumDifference(n: IntArray): Long {
val q = PriorityQueue<Int>(); val suf = LongArray(n.size)
var s = 0L; val k = n.size / 3
for (i in n.lastIndex downTo k) {
q += n[i]; s += n[i]; if (q.size > k) s -= q.poll()
suf[i] = s
}
q.clear(); var d = s; s = 0
for (i in 0..<2 * k) {
q += -n[i]; s += n[i]; if (q.size > k) s += q.poll()
if (i >= k - 1) d = min(d, s - suf[i + 1])
}
return d
}
// 47ms
pub fn minimum_difference(n: Vec<i32>) -> i64 {
let (mut q, k) = (BinaryHeap::new(), n.len() / 3);
let (mut suf, mut s, mut j) = (vec![0; k + 1], 0i64, 0);
for i in (k..n.len()).rev() { let n = n[i] as i64;
q.push(-n); s += n; if q.len() > k { s += q.pop().unwrap(); }
if q.len() == k { suf[j] = s; j += 1 }
}
q.clear(); let mut d = s; s = 0;
for i in 0..2 * k { let n = n[i] as i64;
q.push(n); s += n; if q.len() > k { s -= q.pop().unwrap(); }
if i >= k - 1 { j -= 1; d = d.min(s - suf[j]) }
} d
}
// 131ms
long long minimumDifference(const vector<int>& n) {
int k = n.size() / 3, j = 0; long long s = 0;
priority_queue<int> q; vector<long long> suf(k + 1);
for (int i = n.size() - 1; i >= k; --i) {
s += n[i]; q.push(-n[i]);
if (q.size() > k) s += q.top(), q.pop();
if (q.size() == k) suf[j++] = s;
}
q = {}; long long d = s; s = 0;
for (int i = 0; i < 2 * k; ++i) {
s += n[i]; q.push(n[i]);
if (q.size() > k) s -= q.top(), q.pop();
if (i >= k - 1) d = min(d, s - suf[--j]);
}
return d;
}
17.07.2025
3202. Find the Maximum Length of Valid Subsequence II medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1052
Problem TLDR
Longest same-pair-k-parity subsequence #medium #dp
Intuition
Didn’t solved.
What went right:
- arithmetics:
(a+b)%k == (b + c)%k, a%k == c%k
What went wrong:
- spent some brainpower on dfs implementations (frist 15 minutes)
- the way to update length: closes i got is
++len[v][other], should’ve beenmax(len[v][x%k], 1 + len[v][other])(wasn’t able to comprehend how to peek max and update current simulteneously)
Mostly irrelevant chain-of-thoughts:
// abcd
// (a+b)%k == (b+c)%k
// (a%k + b%k)%k == (b%k + c%k)%k
// 1 4 1 4 %3 always ababab pattern, or aaaa ?
// (1+4)%3=2
// 4%3=1, 1%3=1
// meet 4, look for (0..k) - 4%k
// (a + b) % k = c
// a % k = (c - b%k + k) % k
// 1 4 2 3 1 4 k=3
// *
// * 4: 1-4 start sequence parity (1+4)%k=5%3=2
// * for p=2: 2 - 1%k = 1
// 1 2 3 4 5 k=2
// *
Approach
- no difference between iterations:
x in n v in 0..<korv in 0..<k x in n
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(k)\)
Code
// 92ms
fun maximumLength(n: IntArray, k: Int): Int {
val len = Array(k) { IntArray(k) }
for (v in 0..<k) for (x in n)
len[v][x % k] = max(len[v][x % k], 1 + len[v][(k + v - (x % k)) % k])
return len.maxOf { it.max() }
}
// 92ms
fun maximumLength(n: IntArray, k: Int): Int {
val len = Array(k) { IntArray(k) }
for (x in n) for (v in 0..<k)
len[v][x % k] = max(len[v][x % k], 1 + len[v][(k + v - (x % k)) % k])
return len.maxOf { it.max() }
}
// 67ms
pub fn maximum_length(n: Vec<i32>, k: i32) -> i32 {
(0..k as usize).map(|v| {
let k = k as usize; let mut len = vec![0; k];
n.iter().map(|&x| { let x = x as usize;
len[x % k] = len[x % k].max(1 + len[(k + v - x % k) % k]); len[x % k]
}).max().unwrap() }).max().unwrap() as _
}
// 55ms
int maximumLength(vector<int>& n, int k) {
int r = 0;
for (int v = 0; v < k; ++v) for (int l[1000]={}; int x: n)
r = max(r, l[x%k] = max(l[x%k], 1 + l[(v - x%k + k) % k]));
return r;
}
16.07.2025
3201. Find the Maximum Length of Valid Subsequence I medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1051
Problem TLDR
Longest same-pair-parity subsequence #medium #greedy
Intuition
4 cases to consider, take greedily
// 00000 -- valid (0+0=0)
// 1111111 -- valid (1+1=0)
// 010101 -- valid (1+0=1)
// 101010 -- valid (1+0=1)
// 0001010 -- invalid
// 0001111 -- invalid
Approach
- write CPU-branchless with bit tricks
- use a single array for all 4 cases
- two alterating cases 0-1 and 1-0 collapses into single with initial condition of first element
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 14ms
fun maximumLength(n: IntArray): Int {
val c = IntArray(4)
for (x in n) { ++c[x % 2]; c[2 + x % 2] = 1 + c[3 - x % 2] }
return c.max()
}
// 8ms
fun maximumLength(n: IntArray): Int {
var zo = 0; var oz = 0
var zonext = 0; var oznext = 1
var allZeros = 0; var allOnes = 0
for (x in n) {
allZeros += 1 - (x % 2)
allOnes += x % 2
if (x % 2 == zonext) { ++zo; zonext = 1 - zonext }
if (x % 2 == oznext) { ++oz; oznext = 1 - oznext }
}
return maxOf(allZeros, allOnes, zo, oz)
}
// 2ms
fun maximumLength(n: IntArray): Int {
var az = 0; var ao = 0; var c = 0; var e = n[0] and 1
for (x in n) {
val p = x and 1; az += 1 - p; ao += p
c += 1 - p xor e; e = e xor (1 - p xor e)
}
return max(max(az, ao), c)
}
// 0ms
pub fn maximum_length(n: Vec<i32>) -> i32 {
let (mut a, mut b, mut c, mut e) = (0, 0, 0, n[0] & 1);
for x in n {
let p = x & 1; a += 1 - p; b += p;
c += 1 - p ^ e; e = e ^ (1 - p ^ e);
} a.max(b).max(c)
}
// 0ms
int maximumLength(vector<int>& n) {
int a = 0, b = 0, c = 0, e = n[0] & 1;
for (int x: n) a += 1 - x&1, b += x&1, c += (x&1) == e, e = e ^ ((x&1) == e);
return max(max(a, b), c);
}
14.07.2025
1290. Convert Binary Number in a Linked List to Integer easy blog post substack youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1049
Problem TLDR
Binary linked list to decimal #easy #linkedlist
Intuition
x = x * 2 + value
- use recursion
- use loop
- use values to hold some data
Approach
- try to write it in all difference ways
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 128ms
fun ListNode?.str(): String = if (this == null) ""
else "" + `val` + next.str()
fun getDecimalValue(head: ListNode?) = head.str().toInt(2)
// 0ms
fun getDecimalValue(head: ListNode?): Int =
if (head?.next == null) head!!.`val` else
getDecimalValue(head.next!!.apply { `val` += 2 * head.`val`})
// 0ms
fun getDecimalValue(head: ListNode?, r: Int = 0): Int =
head?.run { getDecimalValue(next, r * 2 + `val`) } ?: r
// 0ms
fun getDecimalValue(head: ListNode?): Int {
var x = head; var y = 0
while (x != null) { y = y * 2 + x.`val`; x = x.next }
return y
}
// 0ms
var max = 1
fun getDecimalValue(head: ListNode?): Int = head?.run {
val curr = max++
getDecimalValue(next) + `val` * (1 shl (max - curr - 1))
} ?: 0
// 0ms
fun getDecimalValue(head: ListNode?): Int = head?.run {
val curr = `val` / 2
next?.`val` += (curr + 1) * 2
val tail = getDecimalValue(next)
val max = max(curr, (next?.`val` ?: 0) / 2)
`val` = `val` % 2 + max * 2
(`val` % 2) * (1 shl (max - curr)) + tail
} ?: 0
// 0ms
pub fn get_decimal_value(mut head: Option<Box<ListNode>>) -> i32 {
let mut r = 0;
while let Some(b) = head {
r = r * 2 + b.val;
head = b.next
} r
}
// 0ms
int getDecimalValue(ListNode* head) {
for (;; head = head->next)
if (!head->next) return head->val;
else head->next->val += head->val * 2;
}
13.07.2025
2410. Maximum Matching of Players With Trainers medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1048
Problem TLDR
Count trainers for players #medium #sort
Intuition
Skip not able trainers, always take smallest player and trainer.
Approach
- we can iterate over trainers or over players
- Rust
into_iteris slower thaniter7ms vs 3ms - Rust
iteris slower thanfor3ms vs 0ms - have to sort both, 10^9 range not suitable for counting sort linear solution
- players counter and result counter is the same variable
Complexity
-
Time complexity: \(O(nlog(n))\)
-
Space complexity: \(O(1)\)
Code
// 49ms
fun matchPlayersAndTrainers(ps: IntArray, ts: IntArray): Int {
ps.sort(); ts.sort(); var t = 0; var cnt = 0
return ps.count { p ->
while (t < ts.size && ts[t] < p) ++t
t++ < ts.size
}
}
// 44ms
fun matchPlayersAndTrainers(ps: IntArray, ts: IntArray): Int {
ps.sort(); ts.sort(); var p = 0
for (t in ts) {
if (t < ps[p]) continue
if (++p == ps.size) break
}
return p
}
// 3ms
pub fn match_players_and_trainers(mut ps: Vec<i32>, mut ts: Vec<i32>) -> i32 {
ps.sort_unstable(); ts.sort_unstable(); let mut t = 0;
ps.iter().take_while(|&&p| {
while t < ts.len() && ts[t] < p { t += 1 }
t += 1; t <= ts.len()
}).count() as _
}
// 0ms
pub fn match_players_and_trainers(mut ps: Vec<i32>, mut ts: Vec<i32>) -> i32 {
ps.sort_unstable(); ts.sort_unstable(); let mut p = 0;
for t in ts {
if t < ps[p] { continue }; p += 1;
if p == ps.len() { break }
} p as _
}
// 32ms
int matchPlayersAndTrainers(vector<int>& ps, vector<int>& ts) {
sort(begin(ps), end(ps)); sort(begin(ts), end(ts));
int p = 0;
for (int t = 0; t < size(ts) && p < size(ps); ++t) p += ts[t] >= ps[p];
return p;
}
12.07.2025
1900. The Earliest and Latest Rounds Where Players Compete hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1047
Problem TLDR
First and last round Alice fight Bob #hard #simulation
Intuition
Didn’t solved (have a hard time to understand the simulation rules)
// 7 minutes read description, didn't understood
// let's try simulation
// round 1
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
// * s w choose 11win, 6middle go 2nd rnd
// 2, 3, 4, 5, 7, 8, 9, 10
// w * 2 always win
// 2, 3, 4, 5, 7, 8, 9
// w s * 2 always win, 5 middle go 2nd rnd
// 2, 3, 4, 7, 8
// w s * 2 win, 4 go 2nd
// 2 3 7
// w s * 2 win, 3 go 2nd
// 2 2 go 2nd
// round 2
// 6 11 2 5 4 3
// 2 3 4 5 6 11
// let's start with simulation 28^28
// how to choose the best?
// maybe BFS (idea on 51 minute)
// 1:38 wrong answer for case
// 1 2 3 4 (2,3) 3,3 vs 1,1
// w -
// 2 3
// w
// 2 3 wrong simulation code
// is winnder goes fight again? (question at 1:43 :) )
// 1, 2, 3, 4, 5, 6 7, 8, 9, 10, 11
// - s w
// 2, 3, 4, 5, 7, 8, 9, 10
// w -
// 3, 4, 5, 7, 8, 9
// w -
// 4, 5, 7, 8
// w -
// 5, 7
// w
// 5, 7
// 1 2 3 4 (2,3)
// w -
```
What went wrong: the description comprehension. We stop when first fight with second. The winners are irrelevant. My mistake was leaving the winner.
#### Approach
* sometimes the description is the hardest part
#### Complexity
- Time complexity:
$$O(2^n)$$
- Space complexity:
$$O(n)$$
#### Code
```kotlin
// 343ms
fun earliestAndLatest(n: Int, fp: Int, sp: Int): IntArray {
var min = Int.MAX_VALUE; var max = 1; val fp = fp - 1; val sp = sp - 1
fun dfs(mask: Int, round: Int, i: Int, j: Int) {
if (i >= j) dfs(mask, round + 1, 0, 27) else
if ((mask and (1 shl i)) == 0) dfs(mask, round, i + 1, j) else
if ((mask and (1 shl j)) == 0) dfs(mask, round, i, j - 1) else
if (i == fp && j == sp) { min = min(min, round); max = max(max, round) } else {
if (i != fp && i != sp) dfs(mask xor (1 shl i), round, i + 1, j - 1)
if (j != fp && j != sp) dfs(mask xor (1 shl j), round, i + 1, j - 1)
}
}
dfs((1 shl n) - 1, 1, 0, 27)
return intArrayOf(min, max)
}
11.07.2025
2402. Meeting Rooms III hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1046
Problem TLDR
Most frequent meeting room #hard #heap
Intuition
The corner case is int overflow.
Write the simulation:
- peek free room, or shift time to the first ending meeting
- purge all meetings until the time
Approach
- to remove the
timevariable, sort by theroomnumber - to use just a single queue, do the
rotation: poll, shift time, push back; first free room is a queue size (interesting fact) - to do without a queue: track ending times for each [100] room, peek the lowest in a linear time
Complexity
-
Time complexity: \(O(nlog(n))\) or mnlog(n)
-
Space complexity: \(O(n)\)
Code
// 235ms
fun mostBooked(n: Int, ms: Array<IntArray>): Int {
ms.sortBy { it[0] }
val freeRooms = PriorityQueue<Int>()
val busyRooms = PriorityQueue<Pair<Long, Int>>(compareBy({it.first},{it.second}))
for (r in 0..<n) freeRooms += r
val freq = IntArray(n)
for ((s, e) in ms) {
while (busyRooms.size > 0 && busyRooms.peek().first <= s)
freeRooms += busyRooms.poll().second
if (freeRooms.size > 0) {
val room = freeRooms.poll()
++freq[room]
busyRooms += 1L * e to room
} else {
val (t, room) = busyRooms.poll()
++freq[room]
busyRooms += (t + e - s) to room
}
}
return freq.indexOf(freq.max())
}
// 182ms
fun mostBooked(n: Int, ms: Array<IntArray>): Int {
ms.sortBy { it[0] }
val q = PriorityQueue<Pair<Long, Int>>(compareBy({it.first},{it.second}))
val freq = IntArray(n)
for ((s, e) in ms)
if (q.size > 0 && q.peek().first <= s || q.size >= n) {
while (q.peek().first < s) q += 1L * s to q.poll().second
val (end, room) = q.poll()
++freq[room]
q += (1L * e + max(0, end - s)) to room
} else {
++freq[q.size]
q += 1L * e to q.size
}
return freq.indexOf(freq.max())
}
// 181ms
fun mostBooked(n: Int, ms: Array<IntArray>): Int {
ms.sortBy { it[0] }; val freq = IntArray(n); val t = LongArray(n)
for ((s, e) in ms) {
val room = (0..<n).firstOrNull { t[it] <= s } ?: t.indexOf(t.min())
t[room] = 1L * e + max(0, t[room] - s)
++freq[room]
}
return freq.indexOf(freq.max())
}
// 173ms
fun mostBooked(n: Int, ms: Array<IntArray>): Int {
ms.sortBy { it[0] }
val freeRooms = PriorityQueue<Int>()
val busyRooms = PriorityQueue<Pair<Long, Int>>(compareBy{it.first})
for (r in 0..<n) freeRooms += r
val freq = IntArray(n); var t = 0L
for ((s, e) in ms) {
t = max(t, 1L * s)
while (busyRooms.size > 0 && busyRooms.peek().first <= t)
freeRooms += busyRooms.poll().second
if (freeRooms.size < 1) {
t = busyRooms.peek().first
while (busyRooms.size > 0 && busyRooms.peek().first <= t)
freeRooms += busyRooms.poll().second
}
val room = freeRooms.poll()
++freq[room]
busyRooms += (1L*e + (t - s)) to room
}
return freq.indexOf(freq.max())
}
// 132ms
fun mostBooked(n: Int, ms: Array<IntArray>): Int {
ms.sortBy { it[0] }; val freq = IntArray(n); val t = LongArray(n)
for ((s, e) in ms) {
var min = Long.MAX_VALUE; var rmin = -1; var rs = -1
for (r in 0..<n) {
if (t[r] <= s) { rs = r; break }
if (t[r] < min) { min = t[r]; rmin = r }
}
val room = max(rs, rmin)
t[room] = 1L * e + max(0, t[room] - s)
++freq[room]
}
return freq.indexOf(freq.max())
}
// 24ms
pub fn most_booked(n: i32, mut ms: Vec<Vec<i32>>) -> i32 {
ms.sort_unstable(); let n = n as usize;
let (mut f, mut t, mut res) = (vec![0; n], vec![0; n], 0);
for m in ms { let (s, e) = (m[0] as i64, m[1] as i64);
let (mut rmin, mut rs, mut m) = (-1, -1, i64::MAX);
for r in 0..n { if t[r] <= s { rs = r as i32; break }; if t[r] < m { rmin = r as i32; m = t[r] }}
let room = rmin.max(rs) as usize; t[room] = e + 0.max(t[room] - s); f[room] += 1;
if f[room] > f[res] { res = room } else if f[room] == f[res] { res = res.min(room) }
}
res as _
}
// 63ms
int mostBooked(int n, std::vector<std::vector<int>>& ms) {
sort(begin(ms), end(ms));
long long t[100] = {}; int f[100] = {}, res = 0;
for (auto& m : ms) {
long long s = m[0], e = m[1], rs = -1, rmin = -1, mint = LONG_MAX;
for (int r = 0; r < n; ++r)
if (t[r] <= s) { rs = r; break; }
else if (t[r] < mint) rmin = r, mint = t[r];
int room = max(rs, rmin);
t[room] = 1LL * e + max(0LL, t[room] - s);
if (++f[room] > f[res] || (f[room] == f[res] && room < res)) res = room;
}
return res;
}
10.07.2025
3440. Reschedule Meetings for Maximum Free Time II medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1045
Problem TLDR
Max free time after moving 1 event #medium #sorting
Intuition
// 0 17..19 24..25 41
// 17 5 16
// 2 1
* look for all free windows
* look around each event
* look if each event can fit into another window
* sort free windows
* track windows indices
Space optimization: do forward and backward pass to track the largest seen gap.
Approach
- we can do forward & backward pass in a single loop
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\) or O(1)
Code
// 91ms
fun maxFreeTime(evt: Int, st: IntArray, et: IntArray): Int {
val free = IntArray(st.size)
val gaps = Array(3) { 0 to 0 }; gaps[0] = st[0] to 0
for (i in 0..<st.size) {
val s = st[i]; val e = et[i]
val prev = if (i == 0) 0 else et[i - 1]
val before = s - prev
val next = if (i < st.size - 1) st[i + 1] else evt
val after = next - e
free[i] = before + after
val g = (0..2).minBy { gaps[it].first }
if (gaps[g].first < after) gaps[g] = after to (i + 1)
}
var res = 0
for (i in free.indices) {
var fit = 0
val curr = et[i] - st[i]
for (g in 0..2) if (gaps[g].first >= curr && gaps[g].second !in i..i+1)
fit = curr
res = max(res, free[i] + fit)
}
return res
}
// 7ms
fun maxFreeTime(evt: Int, st: IntArray, et: IntArray): Int {
var left = 0; var right = 0; var res = 0; var j = st.size - 1
for (i in st.indices) {
var before = st[i] - if (i == 0) 0 else et[i - 1]
var after = (if (i < st.size - 1) st[i + 1] else evt) - et[i]
res = max(res, before + after + if (et[i] - st[i] <= left) et[i] - st[i] else 0)
left = max(left, before)
before = (if (j == st.size - 1) evt else st[j + 1]) - et[j]
after = st[j] - if (j > 0) et[j - 1] else 0
res = max(res, before + after + if (et[j] - st[j] <= right) et[j] - st[j] else 0)
right = max(right, before); j--
}
return res
}
// 4ms
pub fn max_free_time(evt: i32, st: Vec<i32>, et: Vec<i32>) -> i32 {
let (mut left, mut right, mut res, mut j) = (0, 0, 0, st.len() - 1);
for i in 0..st.len() {
let before = st[i] - if i == 0 { 0 } else { et[i - 1] };
let after = (if i < st.len() - 1 { st[i + 1] } else { evt }) - et[i];
res = res.max(before + after + if et[i] - st[i] <= left { et[i] - st[i] } else { 0 });
left = left.max(before);
let before = (if j == st.len() - 1 { evt } else { st[j + 1] }) - et[j];
let after = st[j] - if j > 0 { et[j - 1] } else { 0 };
res = res.max(before + after + if et[j] - st[j] <= right { et[j] - st[j] } else { 0 });
right = right.max(before); j -= 1
} res
}
// 0ms
int maxFreeTime(int evt, vector<int>& st, vector<int>& et) {
int left = 0, right = 0, res = 0, j = st.size() - 1;
for (int i = 0; i < st.size(); ++i) {
int before = st[i] - (i == 0 ? 0 : et[i - 1]);
int after = (i < st.size() - 1 ? st[i + 1] : evt) - et[i];
int dur = et[i] - st[i];
res = max(res, before + after + (dur <= left ? dur : 0));
left = max(left, before);
before = (j == st.size() - 1 ? evt : st[j + 1]) - et[j];
after = st[j] - (j > 0 ? et[j - 1] : 0);
dur = et[j] - st[j];
res = max(res, before + after + (dur <= right ? dur : 0));
right = max(right, before);
j--;
}
return res;
}
9.07.2025
3439. Reschedule Meetings for Maximum Free Time I medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1044
Problem TLDR
Max free time after moving k events together #medium #sliding_window
Intuition
// .. ... .... ....
// .. ... .... .... ......
// a b c d
// a+b b+c c+d k=1
// a+b+c b+c+d k=2
// a+b+c+d k=3
Only the free intervals matter. Move k+1 intervals together with sliding window.
Approach
- try to write O(1) memory solution
- corner cases are
startand theend
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(k)\) or O(1)
Code
// 16ms
fun maxFreeTime(evt: Int, k: Int, st: IntArray, et: IntArray): Int {
val free = LinkedList<Int>(); var sum = 0
return (0..st.size).maxOf { i ->
val t = (if (i < st.size) st[i] else evt) - (if (i > 0) et[i - 1] else 0)
sum += t; free += t; if (free.size > k + 1) sum -= free.removeFirst()
sum
}
}
// 10ms
fun maxFreeTime(evt: Int, k: Int, st: IntArray, et: IntArray): Int {
var sum = 0
return (0..st.size).maxOf { i ->
sum += (if (i < st.size) st[i] else evt) - (if (i > 0) et[i - 1] else 0) -
(if (i > k) st[i - k - 1] else 0) + if (i - k - 2 >= 0) et[i - k - 2] else 0
sum
}
}
// 3ms
pub fn max_free_time(evt: i32, k: i32, st: Vec<i32>, et: Vec<i32>) -> i32 {
let (mut sum, k) = (0, k as usize);
(0..=st.len()).map(|i| {
sum += if i < st.len() { st[i] } else { evt } - if i > 0 { et[i - 1] } else { 0 } -
if i > k { st[i - k - 1] } else { 0 } + if i >= k + 2 { et[i - k - 2] } else { 0 };
sum
}).max().unwrap_or(0)
}
// 4ms
int maxFreeTime(int evt, int k, vector<int>& st, vector<int>& et) {
int sum = 0, res = 0, n = st.size();
for (int i = 0; i <= n; ++i) res = max(res, sum +=
(i < n ? st[i] : evt) -
(i > 0 ? et[i - 1] : 0) -
(i > k ? st[i - k - 1] : 0) +
(i >= k + 2 ? et[i - k - 2] : 0));
return res;
}
8.07.2025
1751. Maximum Number of Events That Can Be Attended II hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1043
Problem TLDR
Max top k valued intervals #hard #binary_search #dp
Intuition
Used a hint: dp + binary search for the next item. The interesting part is bottom up dp:
- for every interval look up the largest previous result before
start - append if
prev + value > curr - the dp row is increased pairs
end, sum - meaning max value at the
endtime - the longest chain of events is
k
Approach
- sort by start or end, both works
Complexity
-
Time complexity: \(O(nklog(n))\)
-
Space complexity: \(O(nk)\)
Code
// 226ms
fun maxValue(es: Array<IntArray>, k: Int): Int {
es.sortBy { it[0] }; val dp = HashMap<Pair<Int, Int>, Int>()
fun dfs(i: Int, k: Int): Int = if (i == es.size || k == 0) 0 else dp.getOrPut(i to k) {
val (s, e, v) = es[i]; var lo = i + 1; var hi = es.lastIndex; var j = es.size
while (lo <= hi) {
val m = (lo + hi) / 2
if (es[m][0] > e) { j = min(j, m); hi = m - 1 } else lo = m + 1
}
max(dfs(i + 1, k), v + dfs(j, k - 1))
}
return dfs(0, k)
}
// 208ms
fun maxValue(es: Array<IntArray>, k: Int): Int {
es.sortBy { it[1] }
var dp1 = arrayListOf(listOf(0, 0))
var dp2 = arrayListOf(listOf(0, 0))
repeat(k) {
for ((s, e, v) in es) {
var lo = 0; var hi = dp1.size - 1; var i = -1
while (lo <= hi) {
val m = (lo + hi) / 2
if (dp1[m][0] < s) { lo = m + 1; i = max(i, m) } else { hi = m - 1 }
}
if (i >= 0 && dp1[i][1] + v > dp2.last()[1]) dp2 += listOf(e, dp1[i][1] + v)
}
dp1 = dp2; dp2 = arrayListOf(listOf(0, 0))
}
return dp1.last()[1]
}
// 43ms
pub fn max_value(mut es: Vec<Vec<i32>>, k: i32) -> i32 {
es.sort_unstable_by_key(|e| e[1]); let mut dp1 = vec![[0, 0]];
for x in 0..k { let mut dp2 = vec![[0, 0]];
for e in &es {
let mut lo = 0; let mut hi = dp1.len() - 1;
while lo <= hi {
let m = (lo + hi) / 2;
if dp1[m][0] < e[0] { lo = m + 1 } else { hi = m - 1 }
}
if dp1[hi][1] + e[2] > dp2[dp2.len() - 1][1] { dp2.push([e[1], e[2] + dp1[hi][1]]) }
} dp1 = dp2
} dp1[dp1.len() - 1][1]
}
// 502ms
int maxValue(vector<vector<int>>& es, int k) {
sort(es.begin(), es.end()); unordered_map<long long, int> dp;
auto dfs = [&](this const auto& dfs, int i, int k) -> int {
if (i == es.size() || k == 0) return 0;
long long key = ((long long)i << 32) | k;
if (dp.count(key)) return dp[key];
int s = es[i][0], e = es[i][1], v = es[i][2],
lo = i + 1, hi = es.size() - 1;
while (lo <= hi) {
int m = (lo + hi) / 2;
if (es[m][0] > e) hi = m - 1; else lo = m + 1;
}
return dp[key] = max(dfs(i + 1, k), v + dfs(lo, k - 1));
};
return dfs(0, k);
}
7.07.2025
1353. Maximum Number of Events That Can Be Attended medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1042
Problem TLDR
Max attended events #medium #heap
Intuition
// 1 2 3 4
// ****
// ****
// ****
// ****
//
// 1 2 3 4
// **********
// *
// *
// ****
// *
//
// 1 2 3 4 5
// 1************
// *********4***
// ************5
// 2***
// ***3
// 3 5 5 3 3
// 2 4 4 2 2 take 1
// 3 3 2 2 take 1 (until it's end)
// 2 2 2 take 1 (until it's end)
// 1 1 take 1 (until it's end, search for end)
// 0 take 1
//
// 1 2 3 4 5 6 7
// *
// ***
// *****
// *******
// *********
// ***********
// *************
The greedy strategy is to never waste a day and prioritize those that ends soon.
- iterate over days
- close already ended
- add all started in that day
- take one that ends sooner (maintain a heap to take min)
Approach
- iteration over days range is almost as fast as manual day adjusting
Complexity
-
Time complexity: \(O(nlog(n))\)
-
Space complexity: \(O(n)\)
Code
// 97ms
fun maxEvents(es: Array<IntArray>): Int {
val days = Array(100002) { ArrayList<Int>() }
for ((s, e) in es) days[s] += e
var cnt = 0; val pq = PriorityQueue<Int>()
for (d in 0..100000) {
while (pq.size > 0 && pq.peek() < d) pq.poll()
pq += days[d]
if (pq.size > 0) { pq.poll(); cnt++ }
}
return cnt
}
// 96ms
fun maxEvents(es: Array<IntArray>): Int {
es.sortWith(compareBy({ it[0] }, { it[1] }))
val pq = PriorityQueue<Int>()
var d = 0; var i = 0; var cnt = 0
for (d in 1..100000) {
while (pq.size > 0 && pq.peek() < d) pq.poll()
while (i < es.size && es[i][0] == d) pq += es[i++][1]
if (pq.size > 0) { pq.poll(); ++cnt }
}
return cnt
}
// 94ms
fun maxEvents(es: Array<IntArray>): Int {
es.sortWith(compareBy({ it[0] }, { it[1] }))
val pq = PriorityQueue<Int>()
var d = 0; var i = 0; var cnt = 0
while (pq.size > 0 || i < es.size) {
if (pq.size < 1) d = es[i][0]
while (i < es.size && es[i][0] == d) pq += es[i++][1]
pq.poll(); ++cnt; ++d
while (pq.size > 0 && pq.peek() < d) pq.poll()
}
return cnt
}
// 24ms
pub fn max_events(mut es: Vec<Vec<i32>>) -> i32 {
es.sort_unstable();
let (mut pq, mut i, mut cnt) = (BinaryHeap::new(), 0, 0);
for d in 1..=100000 {
while pq.len() > 0 && -pq.peek().unwrap() < d { pq.pop(); }
while i < es.len() && es[i][0] == d { pq.push(-es[i][1]); i += 1 }
if let Some(_) = pq.pop() { cnt += 1 }
} cnt
}
// 69ms
int maxEvents(vector<vector<int>>& es) {
sort(begin(es), end(es));
priority_queue<int, vector<int>, greater<int>> pq;
int i = 0, cnt = 0;
for (int d = 1; d <= 100000; ++d) {
while (size(pq) && pq.top() < d) pq.pop();
while (i < size(es) && es[i][0] == d) pq.push(es[i++][1]);
if (size(pq)) { pq.pop(); ++cnt; }
} return cnt;
}
6.07.2025
1865. Finding Pairs With a Certain Sum medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1041
Problem TLDR
Design pairs counter; two lists, one changes #medium #hashmap
Intuition
The brute-force is accepted: maintain two frequencies map, iterate over the first.
Approach
- sort first and exit early
- remove 0 frequency elements
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n)\)
Code
// 231ms
class FindSumPairs(vararg val n: IntArray): HashMap<Int, Int>() {
init { for (x in n[1]) merge(x, 1, Int::plus) }
fun add(i: Int, v: Int) {
merge(n[1][i].also { n[1][i] += v }, -1, Int::plus)
merge(n[1][i], 1, Int::plus)
}
fun count(t: Int) = n[0].sumOf { get(t - it) ?: 0 }
}
// 186ms
class FindSumPairs(vararg val n: IntArray): HashMap<Int, Int>() {
val f1 by lazy {
val f1 = HashMap<Int, Int>()
for (x in n[0]) f1.merge(x, 1, Int::plus)
val af = Array(f1.size) { IntArray(2) }
var i = 0
for ((a, f) in f1) { af[i][0] = a; af[i++][1] = f }
Arrays.sort(af, compareBy { it[0] })
af
}
init { for (x in n[1]) merge(x, 1, Int::plus) }
fun add(i: Int, v: Int) {
merge(n[1][i].also { n[1][i] += v }, -1, Int::plus)
merge(n[1][i], 1, Int::plus)
}
fun count(t: Int): Int {
var r = 0
for ((a, f) in f1)
if (a > t) break
else r += f * (get(t - a) ?: 0)
return r
}
}
// 41ms
#[derive(Default)] struct FindSumPairs(Vec<i32>, HashMap<i32, i32>, Vec<i32>);
impl FindSumPairs {
fn new(mut n1: Vec<i32>, n2: Vec<i32>) -> Self {
n1.sort_unstable(); let mut m = HashMap::new();
for &x in &n2 { *m.entry(x).or_insert(0) += 1 }
Self(n1, m, n2)
}
fn add(&mut self, i: i32, v: i32) {
let x = self.2[i as usize]; self.2[i as usize] = x + v;
*self.1.entry(x).or_insert(0) -= 1;
*self.1.entry(x + v).or_insert(0) += 1
}
fn count(&self, t: i32) -> i32 {
self.0.iter().map(|x| self.1.get(&(t - x)).unwrap_or(&0)).sum()
}
}
// 19ms https://leetcode.com/problems/finding-pairs-with-a-certain-sum/submissions/1688214588
#[derive(Default)] struct FindSumPairs(Vec<(i32, i32)>, HashMap<i32, i32>, Vec<i32>);
impl FindSumPairs {
fn new(mut n1: Vec<i32>, n2: Vec<i32>) -> Self {
n1.sort_unstable(); let mut m = HashMap::new();
for &x in &n2 { *m.entry(x).or_insert(0) += 1 }
Self(n1.chunk_by(|a, b| a == b).map(|c| (c[0], c.len() as i32)).collect(), m, n2)
}
fn add(&mut self, i: i32, v: i32) {
let x = self.2[i as usize]; self.2[i as usize] = x + v;
*self.1.entry(x).or_insert(0) -= 1;
if self.1[&x] == 0 { self.1.remove(&x); }
*self.1.entry(x + v).or_insert(0) += 1
}
fn count(&self, t: i32) -> i32 {
let mut r = 0;
for &(x, c) in &self.0 {
if x > t { break }
r += c * self.1.get(&(t - x)).unwrap_or(&0)
} r
}
}
// 147ms
class FindSumPairs {
public:
vector<int> n1, n2; unordered_map<int, int> m;
FindSumPairs(vector<int>& ns1, vector<int>& ns2) {
n1 = ns1; n2 = ns2; sort(begin(n1), end(n1));
for (int x: n2) ++m[x];
}
void add(int i, int v) { --m[n2[i]]; n2[i] += v; ++m[n2[i]]; }
int count(int t) {
int r = 0;
for (int x: n1) if (x > t) break; else r += m[t - x];
return r;
}
};
// 49ms
class FindSumPairs {
public:
vector<int> n1, n2; unordered_map<int, int> m;
FindSumPairs(vector<int>& ns1, vector<int>& ns2) {
swap(n1, ns1); swap(n2, ns2); sort(begin(n1), end(n1));
for (int x: n2) ++m[x];
}
void add(int i, int v) { --m[n2[i]]; n2[i] += v; ++m[n2[i]]; }
int count(int t) {
int r = 0;
for (int x: n1) if (x > t) break; else {
auto it = m.find(t - x);
if (it != end(m)) r += it->second;
} return r;
}
};
5.07.2025
1394. Find Lucky Integer in an Array easy
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1040
Problem TLDR
Max x == freq(x) #easy
Intuition
The most brute-force is O(n^2), the fastest is O(n) and O(1) memory.
Approach
- how many ways to write this code?
- skip all numbers bigger than size
- sort, group, chunk, build a table, bit shift
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 14ms
fun findLucky(arr: IntArray): Int {
arr.sortDescending(); var c = 0; var p = -1
for (x in arr) if (x == p) ++c else { if (c == p) return p; c = 1; p = x }
return if (c == p) p else -1
}
// 13ms
fun findLucky(arr: IntArray) =
(500 downTo 1).firstOrNull { x -> x == arr.count { it == x } } ?: -1
// 6ms
fun findLucky(arr: IntArray) =
arr.groupBy { it }.maxOf { (k, v) -> if (v.size == k) k else -1 }
// 2ms
fun findLucky(a: IntArray): Int {
for (x in a) if ((x and 0xfff) <= a.size) a[(x and 0xfff) - 1] += 1 shl 12
for (x in a.size downTo 1) if (x == a[x - 1] shr 12) return x
return -1
}
// 1ms
fun findLucky(arr: IntArray): Int {
val f = IntArray(501); for (x in arr) ++f[x]
for (x in arr.size downTo 1) if (x == f[x]) return x
return -1
}
// 0ms
pub fn find_lucky(mut a: Vec<i32>) -> i32 {
a.sort_unstable(); a.chunk_by(|a, b| a == b)
.filter(|c| c.len() as i32 == c[0]).map(|c| c[0] as i32).max().unwrap_or(-1)
}
// 0ms
int findLucky(vector<int>& a) {
int f[501]={}, r = -1; f[0] = 1;
for (int x: a) ++f[x];
for (int x: f) if (x == f[x]) r = max(r, x);
return r;
}
4.07.2025
3307. Find the K-th Character in String Game II hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1039
Problem TLDR
kth char in double+shift by ops[i] string #hard #bit_manipulation
Intuition
Took me too long to spot the reversive order of operations.
// a
// ab
// 1234
// abab
// 12345678910
// *
// *
// *
// *
// 0123456789
// abbcbccdbc
// 0112122312
// . . *+1 op = 1 single conversion
// . *+0 op=0
// *+0 op=1
// *+1 op=0
// *0
// 0123456789
// abbcbccdbc k=3 op=[1,0]
// 0112122312
// *+0 op=0
// *+1 op=1
// *0
// a - ab op=1
// ab - abab op=0 notice the reversive order of `op`
// 0123
// abab
// *
- each time string doubles
- the
leftpart is always skips shift - the
rightpart do shift ifoperations[op] == 1 - given position
xcan be from the left ifx % 2 == 0or from the right ifx % 2 == 1 - as we go from child to parent, operations[] are inversed
Approach
- this time overflow of
zis actually possible, don’t forget %26
Complexity
-
Time complexity: \(O(o)\)
-
Space complexity: \(O(1)\)
Code
// 1ms
fun kthCharacter(k: Long, operations: IntArray): Char {
var x = 0L; var p = 1L
for (o in operations) { x += p * o; p *= 2 }
return 'a' + (x and (k - 1)).countOneBits() % 26
}
// 1ms
fun kthCharacter(k: Long, operations: IntArray, i: Int = 0, l: Long = 1L): Char =
if (k == l) 'a' else 'a' + (kthCharacter((k - l) / 2, operations, i + 1, 0) + ((k - l) % 2).toInt() * operations[i] - 'a') % 26
// 0ms
pub fn kth_character(k: i64, operations: Vec<i32>) -> char {
let (mut x, mut p) = (0, 1); for o in operations { x += p * o as i64; p *= 2 }
"abcdefghijklmnopqrstuvwxyz".as_bytes()[((x & (k - 1)).count_ones() % 26) as usize] as char
}
// 0ms
char kthCharacter(long long k, vector<int>& o) {
--k; char c = 'a';
for (int o: o) c = 'a' + (c + ((k & 1) & o) - 'a') % 26, k /= 2;
return c;
}
3.07.2025
3304. Find the K-th Character in String Game I easy
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1038
Problem TLDR
kth char after appending rotated self #easy
Intuition
Simulation is accepted.
Some patterns:
// 01 23 4567 8910 16 32
// 01 12 1223 13
// ab bc bccd bccd.... bccd............ bccd........
// cdde
// 12
- the
bis always at pos power of two - each time we double into the
left partandright part - left is untouched, right is shifted once against previous
- left is at POS%2 == 0, right is at POS%2 > 0
Approach
- do shift at each set bit
- ‘a’ will never overflow ‘z’, the first ‘z’ is at
(1 << 25) - 1position
Complexity
-
Time complexity: \(O(k^2)\)
-
Space complexity: \(O(k)\)
Code
// 13ms
fun kthCharacter(k: Int): Char {
var s = listOf('a')
while (s.lastIndex < k - 1) s += s.map { it + 1 }
return s[k - 1]
}
// 1ms
fun kthCharacter(k: Int): Char {
var k = k - 1; var c = 'a'
while (k > 0) { c += k % 2; k /= 2 }
return c
}
// 0ms
fun kthCharacter(k: Int): Char {
fun x(k: Int): Char = if (k == 0) 'a' else x(k / 2) + k % 2
return x(k - 1)
}
// 0ms
fun kthCharacter(k: Int, l: Int = 1): Char =
if (k == l) 'a' else kthCharacter((k - l) / 2, 0) + (k - l) % 2
// 0ms
fun kthCharacter(k: Int) = 'a' + (k - 1).countOneBits()
// 0ms
pub fn kth_character(k: i32) -> char {
"abcdefghi".as_bytes()[(k - 1).count_ones() as usize] as char
}
// 0ms
char kthCharacter(int k) {
return 'a' + __builtin_popcount(k - 1);
}
2.07.2025
3333. Find the Original Typed String II hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1037
Problem TLDR
ways to remove duplicates, preserve length at least k #hard #dp
Intuition
Didn’t solved.
// aaabbb k=3 len=6
// aaabbb
//
// aaabb b=3, 3-1=2, 6-2=4
// aaab
// aabbb a:2, 6-2=4
// abbb
//
// aabb combinatorics? a_variants * b_variants - bad_comb
// aab
// abb
//
// bad:
// ab
// dp? it is 10^5 * 2000 will give TLE, use hint(14 minute)
// at most k - 1
// bad combination length is at most k - 1
// ab - single bad
// if k=5
// ab, abb, abbb, aab, aabb, aaab - bad
// how to count them?
// aaabbbcccbbb k=7
// a b c b min=4, can take +2 on each or +1 +1 on any pair
// aa
// aaa
// aa bb
// aa cc
// aa bb
// bb
// bbb
//(aa bb)
// bb cc
// bb bb
// cc
// ccc
//(aa cc)
// (bb cc)
// cc bb
// bb
// bbb
//(aa bb)
// (bb bb)
// (cc bb) (15 bad), total=1*3a*3b*3c*3b = 9*9=81
// ans = 81-15 = 66
// choose up to 2 from aa|bb|cc|bb = choose 1 + choose 2
// C(1, 4) + C(2, 4) ??? how to choose from: a|bbbb|cc
// choose (k - 1 - min) from islands a|bbb|cc|b|aa
// only non-singles
// bb|c|a
// 43 minute, look for solution
- the main hardness is how to choose
badvariants from a non-equal buckets (after we remove all the minimal required chars) n- size of minimum non-repeating bucketsg- groups, with filtered out minimal required valuesaabecomesa,bbecomes `` and filtered out; we only interested in therepeating_count - 1values to choose from- use
DP[curr_bucket] = sum_{kk-g(i)}(DP[prev_bucket]) = PS[curr]-PS[kk-g(i)]
Approach
- good solution from /u/votrubac/ https://leetcode.com/problems/find-the-original-typed-string-ii/solutions/5982440/optimized-tabulation/
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 416ms
fun possibleStringCount(w: String, k: Int): Int {
val M = 1_000_000_007L; val g = ArrayList<Int>()
var c = 1; var all = 1L; var n = k
for (i in 1..w.length) if (i < w.length && w[i] == w[i - 1]) ++c
else { --n; if (c - 1 > 0) g += c - 1; all = (all * c) % M; c = 1 }
if (n <= 0) return all.toInt()
val dp = Array(2) { LongArray(n) }; dp[0][0] = 1L; val ps = LongArray(n + 1)
for (i in 0..<g.size) for (kk in 0..<n) {
ps[kk + 1] = (ps[kk] + dp[i % 2][kk]) % M
dp[1 - (i % 2)][kk] = (ps[kk + 1] - ps[max(0, kk - g[i])]) % M
}
var bad = 0L; for (i in 0..<n) bad = (bad + dp[g.size % 2][i]) % M
return ((all + M - bad) % M).toInt()
}
// 49ms
pub fn possible_string_count(w: String, k: i32) -> i32 {
let g = w.as_bytes().chunk_by(|a, b| a == b).map(|c| c.len() as i64).collect::<Vec<_>>();
let M = 1_000_000_007; let mut all = 1; for &c in &g { all = (all * c) % M };
if k as usize <= g.len() { return all as i32 }; let n = k as usize - g.len();
let g = g.iter().filter(|&&c| c > 1).map(|&c| c - 1).collect::<Vec<_>>();
let mut dp = vec![vec![0; n]; 2]; dp[0][0] = 1i64; let mut ps = vec![0; n + 1];
for i in 0..g.len() { for kk in 0..n {
ps[kk + 1] = (ps[kk] + dp[i % 2][kk]) % M;
dp[1 - (i % 2)][kk] = (ps[kk + 1] - ps[(0.max(kk as i64 - g[i])) as usize]) % M;
}}
let mut bad = 0; for i in 0..n { bad = (bad + dp[g.len() % 2][i]) % M }
((all + M - bad) % M) as i32
}
1.07.2025
3330. Find the Original Typed String I easy
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1036
Problem TLDR
ways to remove duplicates #easy #counting
Intuition
Count duplicates, answer is sum of count - 1.
Corner case: duplicates must be adjacent.
Approach
- count
same chars islands - or just count equal adjacent pairs
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 136ms
fun possibleStringCount(w: String) = 1 +
w.windowed(2).count { it[0] == it[1] }
// 108ms
fun possibleStringCount(w: String): Int {
var cnt = 1; var p = '.'
for (c in w) if (c == p) ++cnt else p = c
return cnt
}
// 98ms
fun possibleStringCount(w: String): Int {
var cnt = 1; var r = 0; var p = '.'
for (c in w) if (c == p) ++r else { cnt += r; r = 0; p = c }
return cnt + r
}
// 2ms
pub fn possible_string_count(w: String) -> i32 {
w.as_bytes().chunk_by(|a, b| a == b).collect::<Vec<_>>()
.iter().map(|w| 0.max(w.len() as i32 - 1)).sum::<i32>() + 1
}
// 0ms
pub fn possible_string_count(w: String) -> i32 {
1 + w.as_bytes().windows(2).filter(|w| w[0] == w[1]).count() as i32
}
// 0ms
int possibleStringCount(string w) {
int cnt = 1; char p = '.';
for (char c: w) c == p ? ++cnt : p = c;
return cnt;
}
30.06.2025
594. Longest Harmonious Subsequence easy
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1035
Problem TLDR
Longest subsequence with max-min=1 #easy #counting #sort #two_pointers
Intuition
Calculate the frequencies. For each value x find count x-1 and x+1.
Another was: sort, then linear scan.
Approach
- should be
exactly 1, notat most - we can check only the
x + 1(because wex - 1would still be checked)
Complexity
-
Time complexity: \(O(n\)
-
Space complexity: \(O(n)\)
Code
// 25ms
fun findLHS(n: IntArray): Int {
val f = n.groupBy { it }
return f.maxOf { (k, v) -> v.size + (f[k + 1]?.size ?: -v.size) }
}
// 0ms
pub fn find_lhs(mut n: Vec<i32>) -> i32 {
n.sort_unstable(); n.chunk_by(|a, b| b - a < 1)
.collect::<Vec<_>>().windows(2)
.map(|w| if w[1][0] - w[0][0] == 1 { w[0].len() + w[1].len() } else { 0 })
.max().unwrap_or(0) as _
}
// 6ms
int findLHS(vector<int>& n) {
sort(begin(n), end(n)); int r = 0;
for (int i = 1, j = 0; i < size(n); ++i) {
while (j < i && n[i] - n[j] > 1) j++;
if (n[i] - n[j] == 1) r = max(r, i - j + 1);
} return r;
}
29.06.2025
1498. Number of Subsequences That Satisfy the Given Sum Condition medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1034
Problem TLDR
Subsequencies target in 0..min+max #medium #binary_search #two_pointers
Intuition
Observe the problem:
// 2,3,3,4,6,7 target = 10
// * * *
// 7 2 7 72 27 2 727 -77 -7 -7
// 2 7 7 27 27 2 277 -77 -7 -7
// order doesn't matter, can sort
// binary search target / 2 right border
// for each value x find with bs t=(target - x)
// 0 1 2 3 4 5
// 2 3 3 4 6 7 t=12
// j i 6+2 =8 6+6=12
// j i 7+2 =9 7+7=14, 7+6=13, 7+4=11
// f t t=4
// 4 + 3 + 2 + 1 = 10 = 4 * 5 / 2
- order doesn’t matter -> can sort (subsequencies are different, but count is the same; for every min,max pair we can take any subset of others)
- now min..max is a subarray (not subsequence)
- at every position we count subarrays
endingon that position - count
goodorbad - naive: binary search
target - n[i], bad isi - j - clever: the right border only goes from the right to the left, no need for binary search
Approach
- optimize memory to O(1) using
2^x%mexponentiation technique:a^x = (a^2^x/2 + a^x%2) - write a short joke solution with
BigInteger - precompute
2^xin one go countingbadsubarrays
Complexity
-
Time complexity: \(O(nlog(n))\)
-
Space complexity: \(O(n)\)
Code
// 177ms
fun numSubseq(n: IntArray, t: Int): Int {
var i = 0; var j = n.size - 1; n.sort(); var c = 0.toBigInteger(); val one = 1.toBigInteger()
while (i <= j) if (n[i] + n[j] > t) j-- else c = c.add(one.shiftLeft(j - i++))
return c.mod(1_000_000_007.toBigInteger()).intValueExact()
}
// 75ms
fun numSubseq(n: IntArray, t: Int): Int {
val M = 1_000_000_007; n.sort(); var cnt = 0
val f = IntArray(n.size + 2); f[1] = 1
for ((i, x) in n.withIndex()) {
f[i + 2] = (f[i + 1] * 2) % M
var lo = 0; var hi = i; var j = -1
while (lo <= hi) {
val m = (lo + hi) / 2
if (x + n[m] <= t) { j = max(j, m); lo = m + 1 }
else hi = m - 1
}
cnt = (cnt + f[i - j]) % M
}
return (f[n.size + 1] - cnt - 1 + M) % M
}
// 57ms
fun numSubseq(n: IntArray, t: Int): Int {
val M = 1_000_000_007; n.sort(); var cnt = 0
val f = IntArray(n.size + 2); f[1] = 1; var j = n.size - 1
for ((i, x) in n.withIndex()) {
f[i + 2] = (f[i + 1] * 2) % M
while (j >= 0 && x + n[j] > t) j--
if (j <= i) cnt = (cnt + f[i - j]) % M
}
return (f[n.size + 1] - cnt - 1 + M) % M
}
// 55ms
fun numSubseq(n: IntArray, t: Int): Int {
val M = 1_000_000_007; var c = 0; var i = 0; var j = n.size - 1; n.sort()
fun f(a: Long, x: Int): Long = if (a == 2L && x < 63) (1L shl x) % M else
if (x == 0) 1L else (f((a * a) % M, x / 2) * if (x % 2 > 0) a else 1) % M
while (i <= j) if (n[i] + n[j] > t) j--
else c = (c + f(2L, j - i++).toInt()) % M
return c
}
// 47ms
fun numSubseq(n: IntArray, t: Int): Int {
val M = 1_000_000_007; val f = IntArray(n.size); f[0] = 1
var c = 0; var i = 0; var j = n.size - 1; n.sort()
for (i in 1..<n.size) f[i] = (2 * f[i - 1]) % M
while (i <= j) if (n[i] + n[j] > t) j--
else c = (c + f[j - i++]) % M
return c
}
// 45ms
fun numSubseq(n: IntArray, t: Int): Int {
val M = 1_000_000_007; n.sort(); var cnt = 0
val f = IntArray(n.size); f[0] = 1; var j = n.size - 1
for (i in 1..<n.size) f[i] = (2 * f[i - 1]) % M
for ((i, x) in n.withIndex()) {
while (j >= 0 && x + n[j] > t) j--
if (j < i) break
cnt = (cnt + f[j - i]) % M
}
return cnt
}
// 5ms
pub fn num_subseq(mut n: Vec<i32>, t: i32) -> i32 {
let (M, mut c, mut j) = (1_000_000_007, 0, n.len());
n.sort_unstable(); let mut f = vec![0; n.len() + 2]; f[1] = 1;
for (i, x) in n.iter().enumerate() {
f[i + 2] = (f[i + 1] * 2) % M;
while j > 0 && x + n[j - 1] > t { j -= 1 }
if i + 1 >= j { c = (c + f[i + 1 - j]) % M }
} (f[n.len() + 1] - c - 1 + M) % M
}
// 0ms
int numSubseq(vector<int>& a, int t) {
int n = a.size(), m = 1e9+7; vector<int> p(n,1);
sort(a.begin(), a.end());
for(int i = 1; i < n; ++i) p[i] = (p[i-1]*2) % m;
int i = 0, j = n-1, r = 0;
while(i <= j) if(a[i] + a[j] > t) --j;
else r = (r + p[j-i++]) % m;
return r;
}
28.06.2025
2099. Find Subsequence of Length K With the Largest Sum easy
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1033
Problem TLDR
Subsequence of k largest #easy #sort
Intuition
Sort, take k, restore original order.
Approach
- use sort or heap
- try to write quickselect (Hoare is the fastest)
- corner case is the duplicate numbers, count how many included in largest k
Complexity
-
Time complexity: \(O(nlog(n))\)
-
Space complexity: \(O(n)\)
Code
// 36ms
fun maxSubsequence(n: IntArray, k: Int) = n
.withIndex().sortedBy { -it.value }.take(k)
.sortedBy { it.index }.map { it.value }
// 31ms
fun maxSubsequence(n: IntArray, k: Int) =
n.toMutableList().apply {
while (size > k) remove(min())
}
// 26ms
fun maxSubsequence(n: IntArray, k: Int): List<Int> {
val q = PriorityQueue<Pair<Int, Int>>(compareBy { it.first })
for ((i, x) in n.withIndex()) {
q += x to i
if (q.size > k) q.poll()
}
return q.sortedBy { it.second }.map { it.first }
}
// 17ms
fun maxSubsequence(n: IntArray, k: Int): IntArray {
val src = n.clone(); var i = 0
var lo = 0; var hi = n.lastIndex
while (lo < hi) {
var l = lo; var h = hi
val t = (n[lo] + n[hi]) / 2
while (l <= h) {
while (n[l] < t) ++l
while (n[h] > t) --h
if (l <= h) n[l] = n[h].also { n[h--] = n[l++] }
}
if (n.size - k > h) lo = l else hi = h
}
val min = n[n.size - k]
var cnt = (n.size - k..<n.size).count { n[it] == min }
return IntArray(k) { while (src[i] < min || src[i] == min && --cnt < 0) ++i; src[i++] }
}
// 0ms
pub fn max_subsequence(mut n: Vec<i32>, k: i32) -> Vec<i32> {
for i in 0..n.len() { n[i] = (n[i] << 11) | i as i32 }
n.sort_unstable(); let l = n.len() - k as usize;
(&mut n[l..]).sort_unstable_by_key(|x| x & ((1 << 11) - 1));
for x in &mut n { *x >>= 11 } n[l..].to_vec()
}
// 0ms
vector<int> maxSubsequence(vector<int>& a, int k) {
auto b = a; sort(begin(b), end(b), greater<>());
int m = b[k-1], c = count(begin(b), begin(b) + k, m);
vector<int> r;
for (int x: a) if (x > m || (x == m && c-- > 0)) r.push_back(x);
return r;
}
27.06.2025
2014. Longest Subsequence Repeated k Times hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1032
Problem TLDR
Longest k-repeating subsequence #hard #backtracking
Intuition
Used the hints.
- find all
goodcharacters (at leastkfrequent) - do DFS with backtracking
- prune by only taking at most
n/kchars, each frequency at mostf[c] / k
Approach
- great speed up:
don't build subsequence further if current is not k-repeating(300ms to 90ms) - another way is BFS, explore new length layer by layer (Rust code, no pruning optimizations)
Complexity
-
Time complexity: \(O(n^r)\)
r = max_freq[a..z] / k -
Space complexity: \(O(r)\) recursion depth
Code
// 91ms
fun longestSubsequenceRepeatedK(s: String, k: Int): String {
var res = ""; val f = IntArray(26); for (c in s) ++f[c - 'a']
val cnt = IntArray(26); val seq = CharArray(s.length / k); var sz = 0
fun check() {
var i = 0; var fr = if (sz > 0) 0 else k
if (sz > 0) for (c in s) if (c == seq[i % sz]) if (++i % sz == 0) fr++
if (fr < k) return
if (sz > res.length) res = String(seq, 0, sz)
for (c in 25 downTo 0) if (f[c] >= k && cnt[c] < f[c] / k) {
++cnt[c]; seq[sz++] = 'a' + c
check()
--cnt[c]; --sz
}
}
check()
return res
}
// 416ms
pub fn longest_subsequence_repeated_k(s: String, k: i32) -> String {
let (mut q, mut q1, mut res) = (vec![String::from("")], vec![], "".into());
while q.len() > 0 {
for sub in &q {
for c in 'a'..='z' {
let next = format!("{}{}", sub.clone(), c);
let mut i = 0; let mut r = next.len() * (k as usize);
for c in s.bytes() {
if c == next.as_bytes()[i % next.len()] {
i += 1; if i == r { break }}}
if i == r { res = next.clone(); q1.push(next) }
}}
(q, q1) = (q1, q); q1.clear()
} res
}
// 92ms
string longestSubsequenceRepeatedK(string s, int k) {
int f[26] = {}, c[26] = {}; for (char x : s) f[x - 'a']++;
string res, seq;
auto dfs = [&](this const auto& dfs) {
int sz = seq.size(), i = 0, cnt = sz ? 0 : k;
if (sz)
for (char x : s)
if (x == seq[i % sz] && ++i % sz == 0)
if (++cnt == k) break;
if (cnt < k) return;
if (sz > (int)res.size()) res = seq;
for (int x = 25; x >= 0; x--) {
if (f[x] >= k && c[x] < f[x] / k) {
c[x]++; seq.push_back('a' + x);
dfs();
seq.pop_back(); c[x]--;
}
}
};
dfs();
return res;
}
26.06.2025
2311. Longest Binary Subsequence Less Than or Equal to K medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1031
Problem TLDR
Longest binary subsequence less than K #medium
Intuition
// take all zeros
// 1001010 k=5
// ** * *
// 1 take rightmost 1 while no more than k
//
// 1000001110 k=8
//
// 1001010 k=5
// . * l=1
// . * x=4 l=2
// . * l=3
// .-
// * l=4
// * l=5
// 101001010111100001111110110010011 k=522399436
Greedily take from the tail if condition is ok. Spent too much time trying to build the number, then gave up and just used strings. (what was missing: check bitshift less than 31)
Approach
- sometimes more hacky solution is the only one that can be written without off-by-ones
- to not overflow, check number is not negative, and check the bitshift is less than 31
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n)\)
Code
// 30ms
fun longestSubsequence(s: String, k: Int) = s.reversed()
.fold("") { r, c ->
if ("$c$r".toIntOrNull(2) ?: k + 1 <= k) "$c$r" else r
}.length
// 7ms
fun longestSubsequence(s: String, k: Int): Int {
var x = 0; var l = 0
for (i in s.lastIndex downTo 0)
if (s[i] == '0') ++l else if (l < 31) {
val y = x + (1 shl l)
if (y in 0..k) { x = y; ++l }
}
return l
}
// 0ms
pub fn longest_subsequence(s: String, k: i32) -> i32 {
let (mut x, mut l, s) = (0, 0, s.as_bytes());
for i in (0..s.len()).rev() {
if s[i] == b'0' { l += 1 }
else if l < 31 {
let y = x + (1 << l);
if y <= k { x = y; l += 1 }
}
} l
}
// 0ms
int longestSubsequence(string s, int k) {
int x = 0, l = 0;
for (int i = size(s) - 1; i >= 0; --i)
if (s[i] == '0') ++l; else if (l < 31) {
int y = x + (1 << l);
if (y <= k) { x = y; ++l; }
}
return l;
}
25.06.2025
2040. Kth Smallest Product of Two Sorted Arrays hard blog post substack youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1030
Problem TLDR
K-th increasing product from two arrays #hard #binary_search
Intuition
The intuition is simple (i used the hints though):
- search result with binary search
- count by iterating over one array and finding how many to take using the binary search in the other.
The implementation is scary.
// 1 2 3 1x1 1x2 2x1 1x3 3x1 2x2 2x3 3x2 3x3
// 1 2 3
// 2 5 2x3 2x4 5x3 5x4
// 3 4 6 8 15 20
// ----++++ ----+++
//
// inverted for ----- + classic for +++++
Approach
- we only need one
classicbinary search and oneinverted - for the negative
currentarray use theinvertedsearch; divide array into negative and positive part - search for the
maximum index you can take - for inverted, subtract inverted result from all possible pairs
Complexity
-
Time complexity: \(O(nlog^2(n))\)
-
Space complexity: \(O(1)\)
Code
// 1022ms
fun kthSmallestProduct(n1: IntArray, n2: IntArray, k: Long): Long {
fun bs(n1: IntArray, n2: IntArray, from: Int, to: Int, cmp: (Long) -> Boolean): Long {
var cnt = 0L
for (i in from..to) {
var l = 0; var h = n2.lastIndex; var jmax = -1
while (l <= h) {
val j = (l + h) / 2
if (cmp(1L * n1[i] * n2[j])) { jmax = max(jmax, j); l = j + 1 } else h = j - 1
}
cnt += jmax + 1
}
return cnt
}
fun classic(n1: IntArray, n2: IntArray, m: Long, from: Int, to: Int): Long =
bs(n1, n2, from, to) { it <= m }
fun inverted(n1: IntArray, n2: IntArray, m: Long, from: Int, to: Int): Long =
1L * n2.size * (to - from + 1) - bs(n1, n2, from, to) { it > m }
val div = (0..<n1.size - 1).firstOrNull { (n1[it] < 0) != (n1[it + 1] < 0) } ?: -1
fun count(m: Long): Long = if (div >= 0)
classic(n1, n2, m, div + 1, n1.lastIndex) + inverted(n1, n2, m, 0, div)
else if (n1[0] < 0) inverted(n1, n2, m, 0, n1.lastIndex) else classic(n1, n2, m, 0, n1.lastIndex)
val peaks = listOf(1L * n1[0] * n2[0], 1L * n1[0] * n2.last(), 1L * n1.last() * n2[0], 1L * n1.last() * n2.last())
var lo = peaks.min(); var hi = peaks.max(); var res = Long.MAX_VALUE
while (lo <= hi) {
val m = lo + (hi - lo) / 2
if (count(m) < k) lo = m + 1 else { hi = m - 1; res = min(res, m) }
}
return res
}
24.06.2025
2200. Find All K-Distant Indices in an Array easy
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1029
Problem TLDR
Indices k-distant to key #easy
Intuition
The brute force: scan -k..k at each index. More optimal: build suffix array to predict where is the next key, scan and save the last key position.
Approach
- use brute-force for easy problems
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n)\)
Code
// 32ms
fun findKDistantIndices(n: IntArray, key: Int, k: Int) =
n.indices.filter { (max(0, it - k)..min(n.size - 1, it + k)).any { n[it] == key} }
// 1ms
pub fn find_k_distant_indices(n: Vec<i32>, key: i32, k: i32) -> Vec<i32> {
(0..n.len() as i32).filter(|i|
(0.max(i - k)..(i + k + 1).min(n.len() as i32)).any(|j| n[j as usize] == key)).collect()
}
// 0ms
vector<int> findKDistantIndices(vector<int>& n, int key, int k) {
int last = -2 * size(n); vector<int> res{}, next(size(n));
for (int i = size(n) - 1; i >= 0; --i)
next[i] = n[i] == key ? i : (i + 1 < size(n) ? next[i + 1] : 2 * size(n));
for (int i = 0; i < size(n); ++i) {
if (n[i] == key) last = i;
if (next[i] - i <= k || i - last <= k) res.push_back(i);
}
return res;
}
23.06.2025
2081. Sum of k-Mirror Numbers hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1028
Problem TLDR
n palindromes in both 10 and k-base #hard #math
Intuition
The simple intuition: brute-force all palindromes. The trick is how to build palindromes in increasing order.
- subproblem: Closest Palindrome, hard (https://leetcode.com/problems/find-the-closest-palindrome/description/)
My own solution was accepted:
- iterate
halves1..some_max_value - build two possible tails, with doubled or not center value
- collect those values and then sort
The trick is how to find the max_value to be sure we got all first n values. I just brute-forced it and hardcoded, the function is max(n) = f(2^x) with some constants.
More optimal approach: generate palindromes in increasing order.
- iterate over
lengthof the palindrome - and iterate
halves = start..end, where start is10^half, end is10^(half+1)-1 - then build a tail, and check
Approach
- even non optimal solution feels good if its your own
- however, let’s try to understand and remember how to build the palindromes in order
Complexity
-
Time complexity: \(O(2^n)\)
-
Space complexity: \(O(n)\)
Code
// 1265ms
fun kMirror(k: Int, n: Int): Long {
val k = k.toLong(); val res = ArrayList<Long>()
fun check(v: Long) {
var x = v; var vk = 0L
while (x > 0) { vk = vk * k + x % k; x /= k }
if (vk == v) res += v
}
for (vd in 1..(1 shl ((7 * n + 166) / 18))) {
val vd = vd.toLong(); var x = vd
var v = vd; var v2 = vd
while (x > 0) {
v = v * 10L + x % 10L; x /= 10L
if (x > 0) v2 = v2 * 10L + x % 10L
}
check(v); check(v2)
}
res.sort()
return (0..<n).sumOf { res[it] }
}
// 87ms
fun kMirror(k: Int, n: Int): Long {
var ans = 0L; var cnt = 0; var len = 0; val k = 1L * k
while (cnt < n && ++len > 0) {
val half = (len + 1) / 2
var start = 1; for (i in 1..<half) start *= 10
val end = start * 10 - 1;
for (pref in start..end) {
var pal = 1L * pref; var tail = 1L * pref
if (len % 2 > 0) tail /= 10
while (tail > 0) { pal = pal * 10 + (tail % 10); tail /= 10 }
var t = pal; var rev = 0L
while (t > 0) { rev = rev * k + (t % k); t /= k }
if (rev == pal) { ans += pal; if (++cnt == n) break }
}
}
return ans
}
// 69ms
pub fn k_mirror(k: i32, mut n: i32) -> i64 {
let (mut ans, mut len, k) = (0i64, 0, k as i64);
while n > 0 {
len += 1; let half = (len + 1) / 2;
let mut start = 1i64; for _ in 1..half { start *= 10; }
let end = start * 10 - 1;
for pref in start..=end {
let mut pal = pref;
let mut tail = if len % 2 == 0 { pref } else { pref / 10 };
while tail > 0 { pal = pal * 10 + (tail % 10); tail /= 10; }
let mut t = pal; let mut rev = 0i64;
while t > 0 { rev = rev * k + (t % k); t /= k; }
if rev == pal { ans += pal; n -= 1; if n == 0 { break } }
}
} ans
}
// 107ms
long long kMirror(int k, int n) {
long long ans = 0;
for (int len = 1; n; ++len) {
int halfLen = (len + 1) / 2;
long long start = 1; for (int i = 1; i < halfLen; ++i) start *= 10;
long long end = start * 10 - 1;
for (long long prefix = start; prefix <= end && n; ++prefix) {
long long pal = prefix; long long tail = prefix;
if (len & 1) tail /= 10;
while (tail) pal = pal * 10 + (tail % 10), tail /= 10;
long long t = pal, rev = 0;
while (t) rev = rev * k + (t % k), t /= k;
if (rev == pal) ans += pal, --n;
}
}
return ans;
}
22.06.2025
2138. Divide a String Into Groups of Size k easy
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1027
Problem TLDR
k-chunked string, filled tail #easy
Intuition
Pad then chunk, or chunk then pad. Prefill everything, or write a precise filling code. Great task to learn the language built-ins.
Approach
- if you know Kotlin
padEnd&chunkedyou don’t have to think - Rust doesn’t allow
fmtwith dynamic fill character 1 + (size - 1) / kor(k + size - 1) / kwill pad to% k- Kotln / Java
StringhasCharArrayconstructor arguments - Rust has
resizeto pad-fill aVec
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 14ms
fun divideString(s: String, k: Int, fill: Char) =
s.chunked(k).map { it.padEnd(k, fill) }
// 9ms
fun divideString(s: String, k: Int, fill: Char) =
Array(1 + (s.length - 1) / k) { s.drop(it * k).take(k).padEnd(k, fill) }
// 8ms
fun divideString(s: String, k: Int, fill: Char) =
s.padEnd((1 + (s.length - 1) / k) * k, fill).chunked(k)
// 1ms
fun divideString(s: String, k: Int, fill: Char): Array<String> {
val s = s.toCharArray()
return Array(1 + (s.size - 1) / k) { i ->
val sz = min(s.size - i * k, k)
if (sz == k) String(s, i * k, k)
else {
val tmp = CharArray(k) { fill };
System.arraycopy(s, i * k, tmp, 0, sz)
String(tmp)
}
}
}
// 0ms
pub fn divide_string(s: String, k: i32, fill: char) -> Vec<String> {
let mut s = s.chars().collect::<Vec<_>>(); let k = k as usize;
s.resize((1 + (s.len() - 1) / k) * k, fill);
s.chunks(k).map(|c| c.iter().collect()).collect()
}
// 0ms
vector<string> divideString(string s, int k, char fill) {
vector<string> r(1 + (size(s) - 1) / k, string(k, fill));
for (int i = 0; i < size(s); ++i) r[i / k][i % k] = s[i];
return r;
}
21.06.2025
3085. Minimum Deletions to Make String K-Special medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1026
Problem TLDR
Min remove to make frequencies k-narrow #medium
Intuition
(spent too much time thinking about optimizing 26^2 brute force to 26log(26))
// calc freq
// 13579 k=4
// *** remove 1 and 3, 4 chars
// ***55 remove 2 and 4, 6 chars
// aabcaba
// a=4 b=2 c=1
// 1 2 4 k=0
// * 1 1 remove 1+3=4
// * 2 remove 1+2=3
// * remove 1+2=3
// optimal way to peek the baseline?
// prefix sum
// 1 2 4
// 4
// 6
// 7
// baseline:
// 1 total_right = 6, new_total_right = 2 * 1 = 2, diff=6-2=4
// 2 left `1` is removed, right=4, new_right=1*2=2, diff=4-2=2,
// 4 right=0, left sum=3 is removed
// actually we only have 26 chars, can brute-force
- only the frequencies matters
Approach
- pay attention to the intermediate gathered
data size
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 19ms
fun minimumDeletions(w: String, k: Int): Int {
val f = IntArray(26); for (c in w) ++f[c - 'a']
return f.minOf { x -> f.sumOf { if (it < x) it else max(0, it - x - k) }}
}
// 5ms
fun minimumDeletions(w: String, k: Int): Int {
val f = IntArray(26); for (c in w) ++f[c - 'a']
var res = w.length
for (x in f) if (x > 0) {
var remove = 0
for (f in f) if (f > 0) remove += if (f < x) f else max(0, f - x - k)
res = min(res, remove)
}
return res
}
// 0ms
pub fn minimum_deletions(w: String, k: i32) -> i32 {
let mut f = [0; 26]; for c in w.bytes() { f[(c - b'a') as usize] += 1 }
(0..26).map(|x| (0..26).map(|c| if f[c] < f[x] { f[c] } else { 0.max(f[c] - f[x] - k)}).sum()).min().unwrap()
}
// 6ms
int minimumDeletions(string w, int k) {
int f[26]={}, r = size(w); for (auto& c: w) ++f[c - 'a'];
for (int x: f) {
int remove = 0;
for (int c: f) remove += c < x ? c: max(0, c - x - k);
r = min(r, remove);
} return r;
}
20.06.2025
3443. Maximum Manhattan Distance After K Changes medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1025
Problem TLDR
Max distance after k flips #medium
Intuition
Used the hints.
// find final vector dx dy
// change k negative parts
// SWWEW k=1
// . dy=-1
// ... dx=-2
// order doesn't matter
// NWSE . N E NWNE
// . W N
// . . .
// i solved the wrong problem, the MAX is ON the path, not final
// the order MATTER
- we have to check each step
- at each step remove the opposite to the maximum direction
Another clever intuition is min(total, dist + 2k):
- each flip do +2
- max flips we can do is
total
Approach
- pay attention to the description, don’t solve the wrong problem
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 86ms
fun maxDistance(str: String, k: Int): Int {
var n = 0; var e = 0; var w = 0; var s = 0
return str.withIndex().maxOf { (i, c) ->
when (c) { 'N' -> ++n; 'S' -> ++s; 'W' -> ++w; 'E' -> ++e }
i + 1 - 2 * max(0, minOf(w + s, e + n, w + n, e + s) - k)
}
}
// 58ms
fun maxDistance(str: String, k: Int): Int {
var res = 0; var n = 0; var e = 0; var w = 0; var s = 0
for (c in str) {
when (c) { 'N' -> ++n; 'S' -> ++s; 'W' -> ++w; 'E' -> ++e }
if (e >= w && n >= s) {
val bad = max(0, w + s - k)
val good = w + s - bad
res = max(res, e + n - bad + good)
} else if (e < w && n < s) {
val bad = max(0, e + n - k)
val good = e + n - bad
res = max(res, w + s - bad + good)
} else if (e >= w && n < s) {
val bad = max(0, w + n - k)
val good = w + n - bad
res = max(res, e + s - bad + good)
} else {
val bad = max(0, e + s - k)
val good = e + s - bad
res = max(res, w + n - bad + good)
}
}
return res
}
// 90ms
pub fn max_distance(st: String, k: i32) -> i32 {
let (mut n, mut e, mut w, mut s) = (0, 0, 0, 0);
st.bytes().enumerate().map(|(i, c)| {
match (c) { b'N' => n += 1, b'S' => s += 1, b'E' => e += 1, _ => w += 1 }
i as i32 + 1 - 2 * 0.max((w + s).min(e + n).min(w + n).min(e + s) - k)
}).max().unwrap()
}
// 32ms
pub fn max_distance(st: String, k: i32) -> i32 {
let (mut n, mut e, mut w, mut s, mut r) = (0, 0, 0, 0, 0);
for (i, b) in st.bytes().enumerate() {
match (b) { b'N' => n += 1, b'S' => s += 1, b'E' => e += 1, _ => w += 1 }
r = r.max(i as i32 + 1 - 2 * 0.max((w + s).min(e + n).min(w + n).min(e + s) - k))
} r
}
// 31ms
pub fn max_distance(st: String, k: i32) -> i32 {
let (mut x, mut y, mut r) = (0i32, 0i32, 0);
for (i, b) in st.bytes().enumerate() {
match (b) { b'N' => y += 1, b'S' => y -= 1, b'E' => x += 1, _ => x -= 1 }
r = r.max((i as i32 + 1).min(x.abs() + y.abs() + 2 * k))
} r
}
// 22ms
int maxDistance(string s, int k) {
int x = 0, y = 0, r = 0, total = 1;
for (char c: s) {
y += (c == 'N') - (c == 'S'); x += (c == 'E') - (c == 'W');
r = max(r, min(total++, abs(x) + abs(y) + 2 * k));
} return r;
}
19.06.2025
2294. Partition Array Such That Maximum Difference Is K medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1024
Problem TLDR
k-narrow subsequences #medium #sort
Intuition
Sort, then expand each subsequence as much as possible, the tail with thank you.
Approach
- we can use bucket sort or a bitset
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(n)\)
Code
// 61ms
fun partitionArray(n: IntArray, k: Int): Int {
n.sort(); var l = -k - 1
return n.count { r -> (r - l > k).also { if (it) l = r } }
}
// 9ms
fun partitionArray(n: IntArray, k: Int): Int {
val f = java.util.BitSet(100001); for (x in n) f.set(x)
var cnt = 0; var l = -k-1; var r = f.nextSetBit(0)
while (r >= 0) {
if (r - l > k) { l = r; ++cnt }
r = f.nextSetBit(r + 1)
}
return cnt
}
// 8ms
fun partitionArray(n: IntArray, k: Int): Int {
val f = IntArray(100001); for (x in n) f[x] = x + 1
var cnt = 0; var l = -k
for (r in f) if (r - l > k) { l = r; ++cnt }
return cnt
}
// 1ms
pub fn partition_array(n: Vec<i32>, k: i32) -> i32 {
let (mut f, mut l) = ([0; 100001], -k);
for x in n { f[x as usize] = x + 1 }
f.iter().filter(|&&r| { let w = r - l > k; if w { l = r }; w }).count() as _
}
// 4ms
int partitionArray(vector<int>& n, int k) {
bitset<100001>f; int l = -k-1, c = 0;
for (int x: n) f[x] = 1;
for (int r = 0; r < 100001; ++r) if (f[r] && r - l > k) ++c, l = r;
return c;
}
18.06.2025
2966. Divide Array Into Arrays With Max Difference medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1023
Problem TLDR
List of k-narrow tripplets #medium
Intuition
Sort to minimize distance betwee siblings
Approach
- Kotlin has a
chunked
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(n)\)
Code
// 200ms
fun divideArray(n: IntArray, k: Int) = n.sorted().chunked(3)
.takeIf { it.all { it[2] - it[0] <= k }} ?: listOf()
// 23ms
fun divideArray(n: IntArray, k: Int): Array<IntArray> {
val f = IntArray(100001); for (x in n) ++f[x]; var x = 0
val r = Array(n.size / 3) { IntArray(3) }
for (r in r) {
while (f[x] < 1) ++x; --f[x]; r[0] = x; val m = k + x
while (x < m && f[x] < 1) ++x; --f[x]; r[1] = x
while (x < m && f[x] < 1) ++x; --f[x]; r[2] = x
if (f[x] < 0) return emptyArray()
}
return r
}
// 3ms
pub fn divide_array(mut n: Vec<i32>, k: i32) -> Vec<Vec<i32>> {
n.sort_unstable(); n.chunks(3)
.map(|c| if c[2] - c[0] > k { None } else { Some(c.to_vec()) })
.collect::<Option<_>>().unwrap_or_default()
}
// 0ms
vector<vector<int>> divideArray(vector<int>& n, int k) {
vector<vector<int>> r; sort(begin(n), end(n));
for (int i = 0; i < size(n); i += 3)
if (n[i + 2] - n[i] > k) return {};
else r.push_back({n[i], n[i + 1], n[i + 2]});
return r;
}
17.06.2025
3405. Count the Number of Arrays with K Matching Adjacent Elements hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1022
Problem TLDR
Combinations k equal siblings 1..m in [n] array #hard #combinatorics #math
Intuition
Didn’t solve. Some thougths:
// n = 4, m = 2, k = 2
// [1, 1, 1, 2], [1, 1, 2, 2], [1, 2, 2, 2], [2, 1, 1, 1], [2, 2, 1, 1] [2, 2, 2, 1]
// dp[i] = (1..m).sum { a (1..m).sum { b (a == b) + dp[i + 2] } }
// 10^5 x 10^5 will give TLE/MLE
// combinatorics? all perimutations excluding the banned
// 1 1 2 1 2 2 2 1 1 2 2 1 k = 1
// 1 2 1 2 1 2 k = 0 ban
// 1 1 1 2 2 2 k = 2 ban
// k max = n - 1
// (0..kMax) = all perm "111".toString(2)
// stil don't know how to count perm for each `k`
// hints are pointing to the DP, but how it is not TLE?
// (26 minute, give up, its combinatorics)
// m * C(n - 1, k) * (m - 1) ** (n - 1 - k)
If I understood it right:
- stars and bars: the bars are equal parts, we have
kof them onn-1positions:C(n-1,k) - first is
1..m - the stars can be
1..m - 1(prev)at(n-1) - kpositions (after bars are placed):(m-1)^(n-1-k)
Approach
- this time I recognized my inability to solve combinatorics much faster than 1 hour (26 minute gave up)
- memoize
a^b % m: it is derived from matha ^ b = (a^2)^(b/2) * a^(b%2), b /= 2, a = a * a - memoize combinations nCr (n choose r):
n!/(n-r)!r!=(1..n)/(1..r)(1..n-r) = (1..n)/(1..n-r) / (1..r) = (n-r+1)..n/1..r - memoize how to calculate this with
% M:Fermattheoremx^(m-1)=1 %m is eq x^(m-2)=x^-1 %m, so1/1..r % m is eq (1..r)^m-2 % morden^-1 % m = den^(m-2) %mhttps://en.wikipedia.org/wiki/Fermat%27s_little_theorem - of course it is impossible for me to solve without some huge investment into combinatorics theory, but some tricks are worth to learn
Complexity
-
Time complexity: \(O(nlogn)\)
-
Space complexity: \(O(1)\)
Code
// 28ms
fun countGoodArrays(n: Int, m: Int, k: Int): Int {
val M = 1_000_000_007; val m = 1L * m; var nCr = 1L; var den = 1L
fun pow(a: Long, b: Int): Long =
if (b == 0) 1L else (pow((a * a) % M, b / 2) * if (b % 2 > 0) a else 1) % M
for (i in 1..k) { nCr = (nCr * (n - i)) % M; den = (den * i) % M }
nCr = (nCr * pow(den, M - 2)) % M
return ((((m * nCr) % M) * pow(m - 1, n - k - 1)) % M).toInt()
}
// 28ms
pub fn count_good_arrays(n: i32, m: i32, k: i32) -> i32 {
let (M, n, m, k, mut nCr, mut den) = (1_000_000_007, n as i64, m as i64, k as i64, 1, 1);
fn pow(a: i64, b: i64, M: i64) -> i64 {
if b == 0 { 1 } else { (pow((a * a) % M, b / 2, M) * if (b % 2 > 0) { a } else { 1 }) % M }
}
for i in 1..=k { nCr = (nCr * (n - i)) % M; den = (den * i) % M }
nCr = (nCr * pow(den, M - 2, M)) % M;
((((m * nCr) % M) * pow(m - 1, n - k - 1, M)) % M) as i32
}
// 25ms
#define M 1000000007
int countGoodArrays(int n, int m, int k) {
auto p = [](long a, long b) {
long r = 1;
while (b) { if (b & 1) r = r * a % M; a = a * a % M; b >>= 1; }
return r;
};
long x = 1, y = 1;
for (int i = 1; i <= k; ++i) { x = x * (n - i) % M; y = y * i % M; }
return x * p(y, M - 2) % M * m % M * p(m - 1, n - k - 1) % M;
}
16.06.2025
2016. Maximum Difference Between Increasing Elements easy
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1021
Problem TLDR
Max increasing pair diff #easy
Intuition
Brute-force works. Or, compute running min and search max(current - min).
Approach
- shortest code can be the optimal too
Complexity
-
Time complexity: \(O(n^2)\), or O(n)
-
Space complexity: \(O(1)\)
Code
// 78ms
fun maximumDifference(n: IntArray) =
(0..<n.lastIndex).maxOf { i -> n.drop(i + 1).maxOf { it - n[i] }}
.takeIf { it > 0 } ?: -1
// 37ms
fun maximumDifference(n: IntArray) =
(0..<n.lastIndex).maxOf { i ->
(i + 1..<n.size).maxOf { j -> n[j] - n[i] }}
.takeIf { it > 0 } ?: -1
// 3ms
fun maximumDifference(n: IntArray) =
n.fold(n[0] to 0) { (m, r), t -> min(t, m) to max(r, t - m) }
.second.takeIf { it > 0 } ?: -1
// 1ms
fun maximumDifference(n: IntArray): Int {
var min = n[0]; var r = 0
for (x in n) {
r = max(r, x - min)
min = min(min, x)
}
return if (r > 0) r else -1
}
// 0ms
pub fn maximum_difference(n: Vec<i32>) -> i32 {
let x = n.iter().fold((0, n[0]), |(r, m), &x| (r.max(x - m), m.min(x))).0;
if x > 0 { x } else { -1 }
}
// 0ms
int maximumDifference(vector<int>& n) {
int r = 0, m = n[0];
for (int x: n) r = max(r, x - m), m = min(m, x);
return r > 0 ? r : -1;
}
15.06.2025
1432. Max Difference You Can Get From Changing an Integer medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1020
Problem TLDR
Max - min, replacing any digit, no leading zeros #medium
Intuition
The brute force is fast enough. More optimized:
- max is first non-nine replaced by 9
- min is if first is non-one, replace by 1
- else first non-zero replaced by 0 BUT
Approach
- also can be solved without convertion to strings
Complexity
-
Time complexity: \(O(1)\), 10 digits, 10x10 runs, total is 1000 operations; 10 ops for optimized
-
Space complexity: \(O(1)\)
Code
// 12ms
fun maxDiff(n: Int): Int {
var max = n; var min = n
for (a in "$n") for (b in "0123456789") {
val x = "$n".replace(a, b)
if (x == "0" || x[0] == '0') continue
max = max(max, x.toInt())
min = min(min, x.toInt())
}
return max - min
}
// 8ms
fun maxDiff(n: Int) =
"$n".replace("$n".find { it != '9' } ?: '.', '9').toInt() -
if ("$n"[0] > '1') "$n".replace("$n"[0], '1').toInt()
else "$n".replace("$n".find { it != "$n"[0] && it > '0' } ?: '.', '0').toInt()
// 0ms
pub fn max_diff(n: i32) -> i32 {
let (s, mut a, mut b) = (n.to_string(), n, n);
for c in s.chars() {
for d in '0'..='9' {
let x: String = s.chars().map(|x| if x == c { d } else { x }).collect();
if x == "0" || x.starts_with("0") { continue }
let x = x.parse().unwrap();
a = a.max(x); b = b.min(x)
}
} a - b
}
// 0ms
int maxDiff(int n) {
string s = to_string(n);
int a = n, b = n;
for (char c: s) for (char d = '0'; d <= '9'; ++d) {
string t = s;
for (char& x: t) if (x == c) x = d;
if (t == "0" || t[0] == '0') continue;
int x = stoi(t); a = max(a, x); b = min(b, x);
} return a - b;
}
14.06.2025
2566. Maximum Difference by Remapping a Digit easy
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1019
Problem TLDR
Max - min, replacing any digit #easy
Intuition
Brute-force: replace any digit to any other digit, no thinking. Brute-force2: replace any digit to ‘9’ for max, and to ‘0’ for min, small thinking. Galaxy brain: replace first non-nine to nine for max, first non-zero to zero for min.
Approach
- we can do this in one forward pass by dividing 10^8 / 10
- instead of min and max compute diff
- we can use two arraya of transformations or just to variables to check
Complexity
-
Time complexity: \(O(1)\), 10 digits, 10x10 runs, total is 1000 operations; 10 ops for optimized
-
Space complexity: \(O(1)\)
Code
// 12ms
fun minMaxDifference(n: Int) =
('0'..'8').maxOf { "$n".replace(it, '9').toInt() } -
"$n".replace("$n"[0], '0').toInt()
// 8ms
fun minMaxDifference(n: Int) =
"$n".replace("$n".find { it != '9'} ?: '9', '9').toInt() -
"$n".replace("$n"[0], '0').toInt()
// 0ms
fun minMaxDifference(num: Int): Int {
var n = num; var pow = 100000000; var diff = 0
while (n > 0 && n / pow == 0) pow /= 10
var nine = 9; val zero = n / pow
while (pow > 0) {
val d = n / pow
if (nine == 9 && d != 9) nine = d
diff = diff * 10 + (if (d == nine) 9 else d) - (if (d == zero) 0 else d)
n -= d * pow; pow /= 10
}
return diff
}
// 0ms
pub fn min_max_difference(mut n: i32) -> i32 {
let mut p = 100000000; while n > 0 && n / p == 0 { p /= 10 }
let (mut nine, zero, mut diff) = (9, n / p, 0);
while p > 0 {
let d = n / p; n -= d * p; p /= 10; diff *= 10;
if nine == 9 && d != 9 { nine = d }
diff += (if d == nine { 9 } else { d }) -
if d == zero { 0 } else { d }
} diff
}
// 0ms
int minMaxDifference(int n) {
auto s = to_string(n), t = s; int m = 0;
for (char c = '0'; c <= '9'; ++c) {
t = s; for (char& x: t) if (x == c) x = '9';
m = max(m, stoi(t));
}
t = s; for (char& x: t) if (x == s[0]) x = '0';
return m - stoi(t);
}
13.06.2025
2616. Minimize the Maximum Difference of Pairs medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1018
Problem TLDR
Min max diffs non-overlapped pairs #medium #binary_search
Intuition
Didn’t solve.
// 1 1 2 3 7 10 10
// a a b b
// * x * x b b
// a a
// * x
// take `p` min diffs
// 1 1 1 2
// * .
// *
// *
// how to deal with overlaps? maybe gredily skip
// 18 minute 1, 2, 2, 2, 3, 3, 4 wrong result
// a a b b
// hint1 use DP
// 36 minute: all hints+TLE
// 43 minute MLE the hint was misleading
// hint: binarysearch (again overlapping pairs?)
// 54 minute, giveup (ok, missing idea was to solve overlaps by greedily take)
The working hint:
- binary search of the max allowed diff
- take diffs greedily from a sorted order
Approach
- we can skip
abs - exit early on
cnt >= p - there is an actual DP solution without MLE
Complexity
-
Time complexity: \(O(nlog(n))\)
-
Space complexity: \(O(1)\)
Code
// 31ms
fun minimizeMax(n: IntArray, p: Int): Int {
n.sort(); var lo = 0; var hi = n[n.size - 1] - n[0]
while (lo <= hi) {
val m = (lo + hi) / 2; var cnt = if (n[n.size - 1] - n[0] <= m) 1 else 0; var i = 1
while (i < n.size)
if (n[i] - n[i - 1] > m) i++ else if (++cnt >= p) break else i += 2
if (cnt >= p) hi = m - 1 else lo = m + 1
}
return lo
}
// 7ms
pub fn minimize_max(mut n: Vec<i32>, p: i32) -> i32 {
n.sort_unstable(); let (mut lo, mut hi, l) = (0, n[n.len() - 1] - n[0], n.len());
while lo <= hi {
let m = (lo + hi) / 2; let (mut cnt, mut i) = ((m >= n[l - 1] - n[0]) as i32, 1);
while i < l {
if m >= n[i] - n[i - 1]
{ cnt += 1; i += 2; if cnt >= p { break }} else { i += 1 }}
if cnt >= p { hi = m - 1 } else { lo = m + 1 }
} lo
}
// 22ms
int minimizeMax(vector<int>& n, int p) {
sort(begin(n), end(n));
int l = size(n), lo = 0, ld = n.back() - n[0]; int hi = ld;
while (lo <= hi) {
int m = (lo + hi) / 2; int c = ld <= m, i = 1;
while (i < l) if (n[i] - n[i - 1] > m) i++;
else if (++c >= p) break; else i += 2;
if (c >= p) hi = m - 1; else lo = m + 1;
} return lo;
}
12.06.2025
3423. Maximum Difference Between Adjacent Elements in a Circular Array easy
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1017
Problem TLDR
Max abs sibling diff #easy
Intuition
There are many surprising ways to write that code, try all of them.
Approach
- kotlin’s
last()makes runtime worse 12ms vs 1ms ofn[n.size - 1] - we can
windowed - we can
zip - we can zip with 0..100
- we can minimize the array reading
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 24ms
fun maxAdjacentDistance(n: IntArray) =
n.zip(n.drop(1) + n[0]).maxOf { (a, b) -> abs(a - b) }
// 22ms
fun maxAdjacentDistance(n: IntArray) =
(n + n[0]).asList().windowed(2).maxOf { abs(it[0] - it[1]) }
// 17ms
fun maxAdjacentDistance(n: IntArray) =
n.indices.maxOf { abs(n[(it + 1) % n.size] - n[it]) }
// 15ms
fun maxAdjacentDistance(n: IntArray) =
n.zip(intArrayOf(n.last()) + n).maxOf { (a, b) -> abs(a - b) }
// 11ms
fun maxAdjacentDistance(n: IntArray): Int {
var r = abs(n[0] - n.last())
for (i in 1..<n.size) r = max(r, abs(n[i] - n[i - 1]))
return r
}
// 1ms
fun maxAdjacentDistance(n: IntArray): Int {
var r = abs(n[0] - n[n.size - 1])
for (i in 1..<n.size) r = max(r, abs(n[i] - n[i - 1]))
return r
}
// 0ms
pub fn max_adjacent_distance(n: Vec<i32>) -> i32 {
(0..n.len()).map(|i| (n[(i + 1) % n.len()] - n[i]).abs()).max().unwrap()
}
// 0ms
pub fn max_adjacent_distance(n: Vec<i32>) -> i32 {
(0..100).zip([&n[1..], &n[..1]].concat())
.map(|(a, b)| (n[a] - b).abs()).max().unwrap()
}
// 0ms
int maxAdjacentDistance(vector<int>& n) {
int r = 0, p = n[size(n) - 1];
for (int x: n) r = max(r, abs(p - x)), p = x;
return r;
}
11.06.2025
3445. Maximum Difference Between Even and Odd Frequency II hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1016
Problem TLDR
Max odd - min even frequency, window at least k #hard
Intuition
Didn’t solve.
Irrelevant chain-of-thoughts:
// 0 1 2 3 4 odd-even
//
// 1111122 at least k
// 3-2 k=6
// small number of digits, maybe solve for each pair
// even should be the smallest = 2
// odd should be the largest BUT substring length >= k (so can't shrink less than k to make odd)
// for every two numbers ..a...a... find the best start..end for odds
// this is O(n^2) algo, as the window size k up to n
// can we do it in a one go?
// 112211221122
// eeo for example consider those even positions
// oee odds with different lengths
// ooeeo
// oeeoo
// ooeeooeeo adds two more evens, no gaps allowed
// oeeooeeoo adds two more evens, no gaps allowed
// (17 minute)
// eooeo
// can optimal evens be more than 2?
// 111112222111111 5-2=3 vs 11-4=5 yes
// 5 2 2 6
// ok, maybe FIX the window size and binary search it? - will not work, no criteria for binary search
// (26 minute, 0 lines of code)
// idea: the only reason to shrink window is to make odd from even (29 minute)
// or, maybe to decrease even frequency (33 minute)
// ok, look for hints, no working ideas yet
// hint1: fix 2 chars (kind of was close)
// hint2: prefix sum
//
// 111111222211111 5-2=3 vs 11-4=5 yes
// 6 2 2 5
// but how to use the prefix sum? (56 minute)
// (60 minute, give up look for solution)
// a odd b odd complementary to a odd b even, a even b odd
// a odd b even complementary to a even b even, a odd b odd
// a even b odd complementary to a even b even, a odd b odd
// a even b even complementary to a odd b even, a even b odd (but what about k?, 75 minute)
The missing part for me even after hints was how to shrink the window. Basically, we moving until last a or b, shrinking to size of 2: aa or bb but preserving at least k.
The working solution:
- for every pair of digits a and b
- compute prefix sum of frequencies fa, fb
- and maintain sliding window with left pointer j
-
move j while window at least k and until fa[j] == fa fb[j] == fb (until last a or b) - compute diff and put to seen[key]=diff, key is a mask of parity (a%2, b%2)
- then the current complementary key is inversion of parity (1 - fa%2)
- and diff = diff - complementary_diff
Approach
- felt close, but not enough
- the rule for shrinking window is crucial here; why shrink to size of 2 gives optimal, and don’t make worse other pointer expansion?
- the initial condition to prefixes array is tricky, use sentinel 0 at start
- rotate a b and b a to simplify complementary state matching
- store the
diff=fa[j]-fb[j]in seen instead of indices, and we have to subtract it as complementary - or we can skip the prefix array entirely, as we only interested in the latest count
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 54ms
fun maxDifference(s: String, k: Int): Int {
var res = -s.length
for (a in "01234") for (b in "01234") if (a != b) {
val fa = IntArray(s.length + 1); val fb = IntArray(s.length + 1)
val seen = IntArray(4) { s.length }; var j = 0
for ((i, c) in s.withIndex()) {
val l = i + 1; fa[l] = fa[i]; fb[l] = fb[i]
if (c == a) ++fa[l]; if (c == b) ++fb[l]
while (j <= i - k + 1 && fb[j] < fb[l]) {
val key = (fa[j] % 2) * 2 + (fb[j] % 2)
seen[key] = min(fa[j] - fb[j], seen[key])
j++
}
res = max(res, fa[l] - fb[l] - seen[(1 - fa[l] % 2) * 2 + (fb[l] % 2)])
}
}
return res
}
// 26ms
pub fn max_difference(s: String, k: i32) -> i32 {
let (k, s, n, mut r) = (k as usize, s.as_bytes(), s.len(), -(s.len() as i32));
for &a in b"01234" { for &b in b"01234" { if a == b { continue; }
let (mut fa, mut pa, mut fb, mut pb, mut seen, mut j) =
(0, 0, 0, 0, vec![n as i32; 4], 0);
for (i, &c) in s.iter().enumerate() {
fa += (c == a) as i32; fb += (c == b) as i32;
while j + k <= i + 1 && fb >= 2 + pb {
let key = ((pa % 2) * 2 + (pb % 2)) as usize;
seen[key] = seen[key].min(pa - pb);
pa += (s[j] == a) as i32; pb += (s[j] == b) as i32;
j += 1;
}
r = r.max(fa - fb - seen[((1 - fa % 2) * 2 + (fb % 2)) as usize]);
}}} r
}
// 39ms
int maxDifference(string s, int k) {
int n = s.size(), r = -n;
for (char a : {'0','1','2','3','4'})
for (char b : {'0','1','2','3','4'}) if (a != b) {
int fa = 0, fb = 0, pa = 0, pb = 0, j = 0, seen[4] = {n,n,n,n};
for (int i = 0; i < n; ++i) {
fa += s[i] == a; fb += s[i] == b;
while (j + k <= i + 1 && fb >= pb + 2) {
int key = pa % 2 * 2 + pb % 2;
seen[key] = min(seen[key], pa - pb);
pa += s[j] == a; pb += s[j] == b; ++j;
}
int key = (1 - fa % 2) * 2 + fb % 2;
r = max(r, fa - fb - seen[key]);
}
} return r;
}
10.06.2025
3442. Maximum Difference Between Even and Odd Frequency I easy
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1015
Problem TLDR
Max odd - min even frequency #easy
Intuition
Find all frequencies, then do the search.
Approach
- use built-in methods like
groupBy - compare with hand-crafted iterative code performance
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 24ms
fun maxDifference(s: String) = s.groupingBy { it }
.eachCount().values.groupBy { it % 2 }
.let { it[1]!!.max() - it[0]!!.min() }
// 23ms
fun maxDifference(s: String) = s.groupingBy { it }
.eachCount().values.partition { it % 2 > 0 }
.let { (a, b) -> a.max() - b.min() }
// 8ms
fun maxDifference(s: String) = s.groupBy { it }.values
.groupBy { it.size % 2 }
.let { it[1]!!.maxOf { it.size } - it[0]!!.minOf { it.size } }
// 7ms
fun maxDifference(s: String) = with(s.groupBy { it }.values) {
filter { it.size % 2 > 0 }.maxOf { it.size } -
filter { it.size % 2 < 1 }.minOf { it.size }
}
// 6ms
fun maxDifference(s: String) = with(s.groupBy { it }.values) {
maxOf { (it.size % 2) * it.size } -
minOf { it.size + (it.size % 2) * (99 - it.size) }
}
// 1ms
fun maxDifference(s: String): Int {
val f = IntArray(26); for (c in s) ++f[c - 'a']
var a = 0; var b = s.length
for (f in f) if (f > 0)
if (f % 2 > 0) a = max(f, a) else b = min(f, b)
return a - b
}
// 0ms
pub fn max_difference(mut s: String) -> i32 {
let (mut a, mut b, mut f) = (0, 99, [0; 26]);
for b in s.bytes() { f[(b - b'a') as usize] += 1 }
for f in f { if (f > 0 && f % 2 < 1) { b = b.min(f) } else { a = a.max(f) }}
a - b
}
// 0ms
pub fn max_difference(mut s: String) -> i32 {
let mut s = unsafe { s.as_bytes_mut() }; s.sort_unstable();
let (a, b): (Vec<_>, Vec<_>) = s[..].chunk_by(|a, b| a == b)
.map(|c| c.len()).partition(|l| l % 2 > 0);
(a.iter().max().unwrap() - b.iter().min().unwrap()) as _
}
// 0ms
int maxDifference(string s) {
int f[26]={}, a = 0, b = 99;
for (auto c: s) ++f[c - 'a'];
for (int c: f) if (c > 0 && !(c & 1)) b = min(b, c); else a = max(a, c);
return a - b;
}
09.06.2025
440. K-th Smallest in Lexicographical Order hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1014
Problem TLDR
k-th lexicographical number of 1..n #hard
Intuition
Didn’t solve. (previous attempt were passed but not optimal https://leetcode.com/problems/k-th-smallest-in-lexicographical-order/solutions/5819960/kotlin-rust/)
// generate all - will give TLE, 10^9 range
// [1, 10,
// 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
// 11,
// 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
// 12,
// 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
// 13,
// 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
// 14,
// 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
// 15,
// 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
// 16,
// 160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
// 17,
// 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
// 18,
// 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
// 19,
// 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
// 2, 20,
// 200,
// 21, 22, 23, 24, 25, 26, 27, 28, 29,
// 3, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
// 4, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
// 5, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
// 6, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
// 7, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
// 8, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
// 9, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
// (8 minute) no ideas
// ok, let's try brute-force maybe it will be fast enough
// (15 minute) TLE n = 957747794 k = 424238336
// from hints: look for digits in n to form a subtree
// 1 - subtree of 1 has size of sz1 (110)
// 2 - subtree of 2 has size of sz2 (10 + 1), 200=200, 1 extra child
// 3 - subtree of 3 has size of sz3 (10) 300 bigger than 200, no extra
// 4 - subtree of 4 has size of sz4 (10)
// ...
// 9 - subtree of 9 has size of sz9 (10)
//
// then remove first digit and go deeper at 1 (the first digit of solution k = 3,n=200)
// 10 - (10)
// 11 - (10)
// ...
// 19 - (10)
// then go deeper at 10 (the second digit of solution k = 3-1=2, n=20)
// 100 - (0) the third digit of solution, k = 2-1=1, n= 2? (how to adjust n?)
// 101 - (0)
// ...
// 109 - (0)
// (50 minute) still didn't know how to adjust n
// 54 look for solution
The solution:
- start with root of the tree x = 1
- calculate subtree size from..to by doing from *= 10, to = to * 10 + 9
- if i + count > k, we found the digit, go deeper subtree x *= 10
- if i + count <= k, skip the node x++, i += count
Approach
- the previous approach of just stealing the solution didn’t give good results as I am unable to solve it again; better spend more time to understand the logic
Complexity
-
Time complexity: \(O(lg(n)lg(k))\)
-
Space complexity: \(O(1)\)
Code
// 0ms
fun findKthNumber(n: Int, k: Int): Int {
var x = 1L; var i = 1; var n = n.toLong(); var k = k.toLong()
while (i < k) {
var cnt = 0L; var from = x; var to = x
while (from <= n) {
cnt += min(to, n) - from + 1
from *= 10; to = to * 10 + 9
}
if (i + cnt <= k) { i += cnt.toInt(); x++ } else { i++; x *= 10 }
}
return x.toInt()
}
// 0ms
pub fn find_kth_number(n: i32, k: i32) -> i32 {
let (mut x, n, mut k) = (1i64, n as i64, k as i64);
while k > 1 {
let (mut skip, mut from, mut to) = (0, x, x);
while from <= n {
skip += to.min(n) - from + 1;
from *= 10; to = to * 10 + 9
}
if k - skip < 1 { k -= 1; x *= 10 } else { k -= skip; x += 1 }
} x as _
}
// 0ms
int findKthNumber(int n, int k) {
long long x = 1; k--;
while (k) {
long long skip = 0, from = x, to = x;
while (from <= n)
skip += min(to, 1LL * n) - from + 1,
from *= 10, to = to * 10 + 9;
if (k - skip < 0) --k, x *= 10; else ++x, k -= skip;
} return (int) x;
}
08.06.2025
386. Lexicographical Numbers medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1013
Problem TLDR
Generate lexicographical numbers 1..n #medium
Intuition
// 1 10 100 1000 11 12 120 2 20 200 21
There is a DFS pattern in the order: 1, 2, 3 are the headers, with fillers in-between.
Approach
- the iterative variant is clever: go deep by *10, then increment, then remove all zeros
- by rewriting the order, some interesting implementations are possible, like runningFold/scan
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 22ms
fun lexicalOrder(n: Int) = buildList<Int> {
var x = 1
repeat(n) {
add(x)
if (x * 10 <= n) x *= 10
else {
if (x == n) x /= 10
x++
while (x % 10 == 0) x /= 10
}
}
}
// 19ms
fun lexicalOrder(n: Int) = buildList<Int> {
fun dfs(p: Int) {
if (p > n) return@dfs
add(p); for (d in 0..9) dfs(p * 10 + d)
}
for (d in 1..9) dfs(d)
}
// 18ms
fun lexicalOrder(n: Int) =
(1..<n).runningFold(1) { r, t -> var x = r
if (x * 10 <= n) x *= 10
else {
if (x == n) x /= 10
x++
while (x % 10 == 0) x /= 10
}
x
}
// 6ms
fun lexicalOrder(n: Int): List<Int> {
var x = 0
return List<Int>(n) {
if (x > 0 && x * 10 <= n) x *= 10
else {
if (x == n) x /= 10
x++
while (x % 10 == 0) x /= 10
}
x
}
}
// 0ms
pub fn lexical_order(n: i32) -> Vec<i32> {
(0..n).scan(0, |x, t| {
if *x > 0 && *x * 10 <= n { *x *= 10 }
else {
if *x == n { *x /= 10 }
*x += 1;
while *x % 10 == 0 { *x /= 10 }
}; Some(*x)
}).collect()
}
// 1ms
vector<int> lexicalOrder(int n) {
int x = 1; vector<int>r(n);
for (int i = 0; i < n; ++i) {
r[i] = x;
if (x * 10 <= n) x *= 10;
else {
if (x == n) x /= 10;
++x;
while (x % 10 == 0) x /= 10;
}
} return r;
}
07.06.2025
3170. Lexicographically Minimum String After Removing Stars medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1012
Problem TLDR
Smallest string by remove min to the left of * #medium
Intuition
// aab*b*c*c*
// . * should go left to right
// . *
// . *
// . *
We have to remove rightmost of the smallest.
Approach
- track indices
- can use a heap
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 381ms
fun clearStars(s: String): String {
val a = s.toCharArray()
val q = PriorityQueue<Int>(compareBy({ s[it] }, { -it }))
for (i in s.indices) if (a[i] == '*') a[q.poll()] = '*' else q += i
return a.filter { it != '*' }.joinToString("")
}
// 60ms https://leetcode.com/problems/lexicographically-minimum-string-after-removing-stars/submissions/1656351997
fun clearStars(s: String): String {
val a = s.toCharArray(); var j = 0; var k = 26
val f = Array(26) { ArrayList<Int>() }
for (i in s.indices) if (a[i] == '*') {
a[f[k].removeLast()] = '*'
while (k < 26 && f[k].size == 0) k++
} else { f[a[i] - 'a'] += i; k = min(k, a[i] - 'a') }
for (i in a.indices) if (a[i] != '*') a[j++] = a[i]
return String(a, 0, j)
}
// 19ms
pub fn clear_stars(mut s: String) -> String {
let (mut b, mut k, mut f) = (unsafe { s.as_bytes_mut() }, 26, vec![vec![]; 26]);
for i in 0..b.len() {
if b[i] == b'*' {
b[f[k].pop().unwrap()] = b'*';
while k < 26 && f[k].len() == 0 { k += 1 }
} else { let b = (b[i] - b'a') as usize; f[b].push(i); k = k.min(b) }}
s.retain(|c| c != '*'); s
}
// 29ms
string clearStars(string s) {
array<vector<int>, 26> f; int k = 26;
for (int i = 0; i < size(s); ++i)
if (s[i] != '*') f[s[i] - 'a'].push_back(i), k = min(k, s[i] - 'a');
else { s[f[k].back()] = '*'; f[k].pop_back(); while (k < 26 && !size(f[k])) ++k; }
erase(s, '*'); return s;
}
06.06.2025
2434. Using a Robot to Print the Lexicographically Smallest String medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1011
Problem TLDR
Smallest string by writing to stack #medium #string
Intuition
Kind of solved myself.
Chain-of-thougths:
// bac
// b
// ba
// ab
// c
// abc
// bddac -> ac ddb
// bd
// db
// da
// dbad
// dbadc
// db ad c so, we can rotate any part of the string
// but only once, non-intersecting
// and can swap intervals
// how to do it in O(n) and optimally?
// (11 minute)
// bdda
// a
// bddc
// ac
// acddb
// bddacab
// * -> abcaddb (wrong), aabcddb is correct, hot to get it?
// bdd a
// bddc aa
// bddc aab
// ok, so it looks like we can skip any chars
// and skipped chars would be the prefix (reversed)
// (19 minute)
// abcabcbcadac
// what the strategy for skipping?
// let's take all 'a''s
// bcbcbcdc aaaa -> aaaa cdcbcbcb looks like it works
// (21 minute)
// ok, it is not working for "bac" -> abc
// we can leave all the suffix
// bacaaccccbbb
// bc aaa ccccbbb, after the last 'a' we do the same for suffix
// cb cccc bbb
// bbb cccc
// aaa bbb cccc cb
// bacaabccbeb -> aaa bbb e ccc b
// bc aaa bccbeb
// cce bbb
// bc cce
// aaa bbb ecc cb (32 minute)
// ok, 40 minute, "bac" wrong (acb instead of abc)
// the strategy was wrong, after 'a' better to take 'b' then 'c'
// 45 minute, another corner case "vzhofnpo"
// look for hints
// hint1: knew
// hint2: knew
// hint3: knew, so it is all about the implementation details
// vzhofnpo abcdefghijklmnopqrstuvwxyz
// *. . * .. vzho f
// * . . * ..
// * . *. vzho fn
// * * vzh fno
// vzhp fnoo > fnoh (57 minute)
// * * vzh fno
// (62 minute) TLE (and I'm happy)
Observations:
- take the
smallestchars first - take all the
currentchars, skip others adding them to stack, stop at the rightmost - increment the
currentchar - before going to the right, get all the
smallerchars from the stack
Another solutions from u/votrubac/ is counting:
- build the frequencies
- put
everychar to stack as you go - if all
current charsare taken, drain all thesmallerchars from the stack
Approach
- strictly synchronize variables, current char and its index
- attention to the order of operations:
before increment,increment current,after increment - we can write
for c in sorfor c in 'a'..'z'for the same algorithm
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 68ms
fun robotWithString(s: String) = buildString {
val ix = IntArray(26) { -1 }; val t = Stack<Char>()
var c = 'a'; for (i in s.indices) ix[s[i] - 'a'] = i
for (i in 0..s.length) {
while (ix[c - 'a'] < i && ++c <= 'z')
while (t.size > 0 && t.last() <= c) append(t.pop())
if (i < s.length) if (s[i] == c) append(c) else t += s[i]
}
}
// 63ms
fun robotWithString(s: String) = buildString {
val idx = IntArray(26) { -1 }; val t = ArrayList<Char>()
var i = 0; for (i in s.indices) idx[s[i] - 'a'] = i
for (c in 'a'..'z') {
while (t.size > 0 && t.last() <= c) append(t.removeLast())
while (i <= idx[c - 'a']) {
if (s[i] == c) append(c) else t += s[i]
i++
}
}
while (i < s.length) t += s[i++]
for (i in t.lastIndex downTo 0) append(t[i])
}
// 50ms
fun robotWithString(s: String) = buildString {
val f = IntArray(26); for (c in s) ++f[c - 'a']
var j = 0; val t = ArrayList<Char>()
for (c in s) {
t += c; --f[c - 'a']
while (j < 25 && f[j] < 1) ++j
while (t.size > 0 && t.last() <= 'a' + j) append(t.removeLast())
}
}
// 44ms
fun robotWithString(s: String) = buildString {
val ix = IntArray(27) { -1 }; val t = ArrayList<Char>()
var c = 'a' - 1; for (i in s.indices) ix[s[i] - 'a'] = i
var j = -1; ix[26] = s.length
for ((i, si) in s.withIndex()) {
while (j < i) {
c++; j = ix[c - 'a']
while (t.size > 0 && t.last() <= c) append(t.removeLast())
}
if (si == c) append(c) else t += si
}
for (i in t.lastIndex downTo 0) append(t[i])
}
// 9ms
pub fn robot_with_string(s: String) -> String {
let mut f = [0; 26]; for b in s.bytes() { f[(b - b'a') as usize] += 1 }
let (mut j, mut t, mut r) = (0, vec![], String::new());
for b in s.bytes() {
t.push(b); f[(b - b'a') as usize] -= 1;
while j < 25 && f[j] < 1 { j += 1 }
while t.len() > 0 && t[t.len() - 1] <= b'a' + j as u8 { r.push(t.pop().unwrap() as char) }
} r
}
// 48ms
string robotWithString(string s) {
int f[26]={}, j = 0; string r, t;for (auto& c: s) ++f[c - 'a'];
for (auto& c: s) {
t += c; --f[c - 'a']; while (j < 25 && f[j] < 1) ++j;
while (size(t) > 0 && t.back() <= 'a' + j) r += t.back(), t.pop_back();
} return r;
}
05.06.2025
1061. Lexicographically Smallest Equivalent String medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1010
Problem TLDR
Map by smallest in group from associate s1 with s2 #medium
Intuition
We can do DFS or use a Union-Find to track groups.
Approach
- we can find minimum in-place by always picking it as root
- no reason to optimize (compression, ranking) Union-Find of just 26 elements
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\), for the result
Code
// 30ms
fun smallestEquivalentString(s1: String, s2: String, bs: String): String {
val u = HashMap(('a'..'z').associateBy { it })
fun f(x: Char): Char = if (x == u[x]) x else f(u[x]!!)
for ((a, b) in s1.zip(s2)) if (f(a) < f(b)) u[f(b)] = f(a) else u[f(a)] = f(b)
return bs.map(::f).joinToString("")
}
// 2ms
fun smallestEquivalentString(s1: String, s2: String, bs: String): String {
val u = IntArray(26) { it }; val a = bs.toCharArray()
fun f(a: Int): Int { var x = a; while (x != u[x]) x = u[x]; u[a] = x; return x }
for (i in s1.indices) {
val a = f(s1[i] - 'a'); val b = f(s2[i] - 'a')
if (a < b) u[b] = a else u[a] = b
}
for (i in a.indices) a[i] = 'a' + f(a[i] - 'a'); return String(a)
}
// 0ms
pub fn smallest_equivalent_string(s1: String, s2: String, bs: String) -> String {
let mut u: Vec<_> = (0..26).collect();
fn f(x: u8, u: &mut Vec<usize>) -> usize { let x = x as usize; while u[x] != u[u[x]] { u[x] = u[u[x]] }; u[x] }
for (a, b) in s1.bytes().zip(s2.bytes()) {
let (a, b) = (f(a - b'a', &mut u), f(b - b'a', &mut u)); if a < b { u[b] = a } else { u[a] = b }
}
bs.bytes().map(|b| (b'a' + f(b - b'a', &mut u) as u8) as char).collect()
}
// 0ms
string smallestEquivalentString(string s1, string s2, string bs) {
int u[26] = {}; iota(u, u + 26, 0);
auto f = [&](int x) { while (x != u[x]) x = u[x]; return x; };
for (int i = 0; i < size(s1); ++i) {
int a = f(s1[i] - 'a'), b = f(s2[i] - 'a');
u[max(a, b)] = min(a, b);
}
for (char& c: bs) c = 'a' + f(c - 'a'); return bs;
}
04.06.2025
3403. Find the Lexicographically Largest String From the Box I medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1009
Problem TLDR
Max string of every split by n #medium
Intuition
Observe an example, find a way to iterate over all possible strings.
// abcdefgh n=3
// a b cdefgh
// a bc defgh
// a bcd efgh
// a bcde fgh
// a bcdef gh
// a bcdefg h
// ab c defgh
// ab cd efgh
// ab cde fgh
// ab cdef gh
// ab cdefg h
// abc d efgh
// abc de fgh
// abc def gh
// abc defg h
// abcd e fgh
// abcd ef gh
// abcd efg h
// abcde f gh
// abcde fg h
// abcdef g h
// a, ab, abc, abcd, abcde, abcdef (length - (n-1))
// b bc bcd bcde bcdef bcdefg (length - (n-2) - i)
- for every position
i - the first
before = min(i, n - 1)goes to friends - and the last
after = n - 1 - beforegoes to friends, then trim
Approach
- there is also O(1) memory solution, just don’t do substring, save positions and compare
- there is also O(n) time solution,
1163. Last Substring in Lexicographical Order(hard) - take the last substring, then trim; the trick is to jump to the next ofi or jpointers by largests[i] or s[j]
Complexity
-
Time complexity: \(O(n^2)\), O(n) c++
-
Space complexity: \(O(n)\), O(result) c++
Code
// 28ms
fun answerString(w: String, n: Int) =
if (n == 1) w else w.indices.maxOf { i ->
w.slice(i..w.length - n + min(n - 1, i))
}
// 3ms
pub fn answer_string(w: String, n: i32) -> String {
if n == 1 { w } else { let n = n as usize; (0..w.len())
.map(|i| w[i..=w.len() - n + i.min(n - 1)].to_string()).max().unwrap() }
}
// 79ms
string answerString(string w, int n) {
if (n == 1) return w; string res = "";
for (int i = 0; i < size(w); ++i) {
int before = min(i, n - 1);
int after = n - 1 - before;
string s = w.substr(i, size(w) - i - after);
if (s > res) res = s;
} return res;
}
// 0ms
string answerString(string w, int n) {
if (n == 1) return w; string res = "";
int i = 0, j = 1;
while (j < size(w)) {
int k = 0; while (j + k < size(w) && w[j + k] == w[i + k]) ++k;
if (k == size(w)) break;
if (w[j + k] > w[i + k]) i += k + 1, j = i + 1; else j += k + 1;
}
int sz = size(w) - n + 1; int sz1 = size(w) - i;
return w.substr(i, min(sz, sz1));
}
03.06.2025
1298. Maximum Candies You Can Get from Boxes hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1008
Problem TLDR
Open boxes graph with keys simulation #hard
Intuition
Just the simulation steps in a BFS
Approach
- make sure
keysdidn’t add unvisited box
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 5ms https://leetcode.com/problems/maximum-candies-you-can-get-from-boxes/submissions/1652437683
fun maxCandies(st: IntArray, cs: IntArray, ks: Array<IntArray>, cb: Array<IntArray>, ib: IntArray): Int {
val q = LinkedList<Int>(); var res = 0; for (b in ib) if (st[b] > 0) { st[b] = -1; q += b } else st[b] = 2
while (q.size > 0) {
val b = q.removeFirst(); res += cs[b]
for (c in cb[b]) if (st[c] > 0) { st[b] = -1; q += c } else st[c] = 2
for (k in ks[b]) if (st[k] > 1) { st[k] = -1; q += k } else if (st[k] == 0) st[k] = 1
}
return res
}
// 0ms
pub fn max_candies(mut st: Vec<i32>, cs: Vec<i32>, ks: Vec<Vec<i32>>, cb: Vec<Vec<i32>>, ib: Vec<i32>) -> i32 {
let (mut q, mut r) = (VecDeque::from_iter(ib), 0);
while let Some(b) = q.pop_front() { let b = b as usize;
if st[b] > 0 {
st[b] = -1; r += cs[b]; q.extend(&cb[b]);
for &k in &ks[b] { let k = k as usize; if st[k] > 1 { q.push_back(k as i32) } else if st[k] == 0 { st[k] = 1 }}
} else if st[b] == 0 { st[b] = 2 }
} r
}
// 0ms
int maxCandies(vector<int>& st, vector<int>& cs, vector<vector<int>>& ks, vector<vector<int>>& cb, vector<int>& ib) {
queue<int> q; int r = 0;
for (int b: ib) if (st[b]) { st[b] = -1; q.push(b); } else st[b] = 2;
while (size(q)) {
int b = q.front(); q.pop(); r += cs[b];
for (int c: cb[b]) if (st[c] > 0) { st[c] = -1; q.push(c); } else st[c] = 2;
for (int k: ks[b]) if (st[k] > 1) { st[k] = -1; q.push(k); } else if (!st[k]) st[k] = 1;
} return r;
}
02.06.2025
135. Candy hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1007
Problem TLDR
Min candies, fair siblings by ratings #hard #greedy
Intuition
I was busy to find a single-pass solution, trying to sum the monotonic lengths sums, but it didn’t worked. So, looked for hints.
The hint: two passes works.
Chain-of-thoughts:
// 1 2 2
// a a+1 1
// 1 2 1 2 1 2 3 4 5
//
// 5 4 3 2 1 2 3 4 5 4 3
// 6 5 4 3 2 3 4 5 6 5 4 -1 to all
// 1 0 2 +1 to all
// 2 1 2
// 1 2 2 2 3
// 1 1
// 1 2 1 1 2
// 2 2 1 1 1 2 2 2 3 3 2 2 12
// 1 1 1 1 +4
// 1 2 3 5 4 3 6
// 1 1 1 1
// 1 2 3 4 2 1
//
// 1 2 5 3 4 1 2
// 1 2 3 1 2 1 2
// ^ if (next is bigger && prev is bigger) give 1
//
// 1 2 5 3 2 1
// ^ if (next is smaller && prev is bigger) give prev - 1
// 1 2 3 4 5 4 5 6 7
// 1 2 3 4 5 1 2 3 4
//
// ok what if we are decreasing
// 7 6 3 4 3 2 1
// a b c 3*4/2=6
// 1
// 2
// 3 a b c d 4*5/2=10
// 1
// 2
// 3
// 4
// 1 2 3 4 7 6 3 4 3 2 1
// 1 2 4 3 2 1
// * *
// * * * *
// vs
// * * *
// * * * two passes works
// 1 2 3 0 0 0
// 0 0 4 3 2 1
// 1 0 2
// * *
// *
// 1 2 3 4 7 6 3 4 3 2 1
// 1 2 3 4 5 1 1 2 1 1 1
// 2 1 4 3 2 1
Here is the correct single pass intuition:
// 5*3 3*5 3 and 5 is in conflict
// 4*.*2 2*.*4 choose max(3,5) = 5, so subtract min(3, 5)=-3
// 3* . *1 1* . *3 or just shorten the smallest length by 1
// 2* . . . . *2
//1* . . . . *1
// i j k i j k
Approach
- single pass solution can be more trickier to find, start with several passes (forward, back)
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\) or O(1)
Code
// 16ms
fun candy(r: IntArray): Int {
val c = IntArray(r.size) { 1 }
for (i in 1..<r.size) if (r[i] > r[i - 1]) c[i] = c[i - 1] + 1
for (i in r.lastIndex - 1 downTo 0) if (r[i] > r[i + 1]) c[i] = max(c[i], c[i + 1] + 1)
return c.sum()
}
// 4ms
fun candy(r: IntArray): Int {
var i = 1; var res = r.size
while (i < r.size) {
if (r[i] == r[i - 1]) { i++; continue }
var j = i; while (j < r.size && r[j] > r[j - 1]) ++j
var k = j; while (k < r.size && r[k] < r[k - 1]) ++k
var a = min(j - i, k - j) - 1; var b = max(j - i, k - j)
res += a * (a + 1) / 2 + b * (b + 1) / 2; i = k
}
return res
}
// 0ms
pub fn candy(r: Vec<i32>) -> i32 {
let (mut i, mut res, mut a, mut b) = (1, r.len() as i32, 0, 0);
while i < r.len() {
if r[i] == r[i - 1] { i += 1; continue }
a = 0; while i < r.len() && r[i] > r[i - 1] { i += 1; a += 1 }
b = 0; while i < r.len() && r[i] < r[i - 1] { i += 1; b += 1 }
(a, b) = (a.min(b) - 1, a.max(b)); res += a * (a + 1) / 2 + b * (b + 1) / 2
} res
}
// 0ms
int candy(vector<int>& r) {
int i = 1, res = size(r), a, b;
while (i < size(r)) {
if (r[i] == r[i - 1]) { ++i; continue; }
a = 0; while (i < size(r) && r[i] > r[i - 1]) ++i, res += ++a;
b = 0; while (i < size(r) && r[i] < r[i - 1]) ++i, res += ++b;
res -= min(a, b);
} return res;
}
01.06.2025
2929. Distribute Candies Among Children II medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1006
Problem TLDR
Ways to give limited from n candies to 3 kids #medium #math #combinations
Intuition
Didn’t solved this, as hint4 gave the exact answer.
Useful hint instead of hint4:
- for each first kid loked
i = 0..min(n, limit) - do a running sum
- of allowed range that both second and third kid can take
- n - i - limit .. n - i
- trim the range: max(0, n - i - limit)..min(limit, n - i)
- the length of range a..b = b - a + 1
Chain-of-thoughts:
// 10^6 (should be faster then linear?)
// is this completely math problem? like Cr(a, b)?
// 4 hints, acceptance rate <50% (shold be hard problem?)
// ok let's think how the distribution works:
// 5 candles, limit 2
// always 3 chilren
// | A | B | C |
// (0..limit) | (0..limit) | (0..limit)
// the number of ways is countA * countB * countC
// is n <= 3 * limit ? (let's run test case n=4, limit = 1, yes, the number of ways is 0)
// no, do we have to handle the symmetry:
// 0..limit | 0..min(n - countA, limit) | 0..min(n - countA - countB, limit)
// consider n = 5 limit = 2
// 1 2 2
// 2 1 2
// 2 2 1 symmetry with 1 2 2, counts separately
//
// so, we have 3 numbers,
// A=0..min(n, limit)
// B=0..min(n - A, limit)
// C=0..min(n - A - B, limit)
// the result is A * B * C (is this correct?, no, b=0, c=0)
// should we do a 3-step dfs dp? (10^6 will give TLE, but let's try)
// ok, dp works, but TLE
// probably requires some math idea from combinatorics
// let's look for hints (22 minute)
// enumerate first 0..min(n, limit) (already knew)
// second is 0..j..limit, i + j less n (interesting way to write this)
// j less n - i
// 0..min(n - i, limit) (already knew)
// hint: "after some transformations"
// basically give you the answer on the hint4
There is a math solution:
-
total nstars and2bars (to separate candies to three kids: * ** * * * ) - trick is how to count
invalidcombinations - there is a math theory for this https://en.wikipedia.org/wiki/Inclusion%E2%80%93exclusion_principle
- good explanation: https://leetcode.com/problems/distribute-candies-among-children-ii/solutions/4278816/o-1-combinatorics/
Let’s try to summarize explanation for counding the invalid combinations:
- one kid has more than a limit, (limit + 1), 3 kids, remove
limit + 1and count ways to set bars C(n - (limit+1), 2), call those combinations asA - two kids has more than a limit, (limit + 1), 3 pairs of kids, remove
2 * (limit + 1)and count ways to set bars C(n-2*(limit+1), 2), call those combinations asB - three kids has more than a limit, single tripple of kids, remove
3 * (limit + 1), count ways to set bars C(n-3(limit+1), 2) important trick: theAcombinations are including theBcombinations already, so we have to subract theB(weak point)- some math for stars and bars:
// 1 2 3 4 5 | |
// . . . . . .
// (n+1) positions, choose 2
// C(n+1, 2) = n!/(r!*(n-r)!) = (n+1)!/(2!*(n+1-2)!) = (n+1)*n*(n-1)!/(2 *(n-1)!) = n(n+1)/2
Approach
- try to understand the combinatorics, it seems the level has been raised to require this
- c++ solution for this
Complexity
-
Time complexity: \(O(n)\) or O(1) if you are genius
-
Space complexity: \(O(1)\)
Code
// 123ms
fun distributeCandies(n: Int, limit: Int) =
(0..min(n, limit)).sumOf { i ->
1L * max(0, min(limit, n - i) - max(0, n - i - limit) + 1) }
// 15ms
pub fn distribute_candies(n: i32, limit: i32) -> i64 {
(0..=n.min(limit)).map(|i|
0.max(limit.min(n - i) - 0.max(n - i - limit) + 1) as i64
).sum()
}
// 0ms
long long distributeCandies(int n, int limit) {
auto c = [&](this const auto& c, long n) -> long {return n*(n+1)/2;};
n++; // stars are places between candies to put the bars
long long nStarsTwoBars = 1LL * c(n);
long long oneOutOfLimit = 1LL * max(0, n - (limit + 1));
long long twoOutOfLimit = max(0, n - 2 * (limit + 1));
long long threeOutOfLimit = max(0, n - 3 * (limit + 1));
long long invalidCombinations = 3 * c(oneOutOfLimit)
-3 * c(twoOutOfLimit)
+1 * c(threeOutOfLimit);
return nStarsTwoBars - invalidCombinations;
}
31.05.2025
909. Snakes and Ladders medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1005
Problem TLDR
Shortest path bottom-top in zig-zag matrix with jumps #medium #bfs
Intuition
Surprisingly, didn’t covered all corener cases.
// 1:15, still some corner case not covered, looking for solutions....
My issue was a premature optimization, trying to inline visited set with jumps. After making a separate visited set it all worked out.
Approach
- LinkedList vs ArrayDeque is 5ms vs 20ms drop-in replacement difference in Kotlin
- don’t premature optimize on the first go
- read instructions slowly: we never do jump-jump, even in 2 ticks
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n^2)\)
Code
// 6ms
fun snakesAndLadders(b: Array<IntArray>): Int {
var s = -1; val n = b.size; var (q, q1) = List(2) { ArrayList<Int>(400) }; q1 += 1
while (q1.size > 0 && ++s >= 0.also { q = q1.also { q1 = q }; q1.clear() })
for (i in q) for (j in i + 1..min(i + 6, n * n)) {
val y = n - 1 - (j - 1) / n
val x = if (y % 2 != n % 2) (j - 1) % n else n - 1 - (j - 1) % n
if (b[y][x] < -1) continue
val k = if (b[y][x] >= 0) b[y][x] else j; b[y][x] = -2; q1 += k
if (k == n * n) return s + 1
}
return -1
}
// 0ms
pub fn snakes_and_ladders(mut b: Vec<Vec<i32>>) -> i32 {
let (mut s, mut n, mut q, mut q1) = (0, b.len(), vec![1], vec![]);
while q.len() > 0 {
for &i in &q { for j in i + 1..=(i + 6).min(n * n) {
let y = n - 1 - (j - 1) / n;
let x = if y % 2 != n % 2 { (j - 1) % n } else { n - 1 - (j - 1) % n };
if b[y][x] < -1 { continue }
let k = if b[y][x] >= 0 { b[y][x] } else { j as i32 }; b[y][x] = -2;
if k == (n * n) as i32 { return s + 1 }
q1.push(k as usize) }}
s += 1; (q, q1) = (q1, q); q1.clear();
}; -1
}
// 0ms
int snakesAndLadders(vector<vector<int>>& b) {
int n = b.size(), s = -1; vector<int> q, q1 = {1};
while (!q1.empty()) {
s++; q.swap(q1); q1.clear();
for (int i : q) for (int j = i + 1, end = min(i + 6, n * n); j <= end; j++) {
int y = n - 1 - (j - 1) / n;
int x = (y % 2 != n % 2) ? (j - 1) % n : n - 1 - (j - 1) % n;
if (b[y][x] < -1) continue;
int k = (b[y][x] >= 0 ? b[y][x] : j); b[y][x] = -2;
if (k == n * n) return s + 1; q1.push_back(k);
}
}
return -1;
}
30.05.2025
2359. Find Closest Node to Given Two Nodes medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1004
Problem TLDR
Closest common node #medium #bfs
Intuition
Walk from two nodes in a parallel BFS by using two queues. First intersection is the answer.
// 0 1 2
// 2 0 0
// 1 -. 0 .-. 2 a = 2, b = 0
// 0 1 2 3 4 5 6
// 5 4 5 4 3 6 -1
// 0 -. 5 -. 6 a = 0 b = 1
// 2 -.^
//
// 1 -. 4 .-. 3
Approach
- start with parallel BFS
- replace queues with single variables
- replace visited sets with marker variables in the edges
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 4ms
fun closestMeetingNode(e: IntArray, a: Int, b: Int): Int {
var a = a; var b = b; var r = e.size
while (a >= 0 || b >= 0) {
if (a >= 0) if (e[a] == -2) r = a else a = e[a].also { e[a] = -3 }
if (b >= 0) if (e[b] == -3) r = min(r, b) else b = e[b].also { e[b] = -2 }
if (r < e.size) return r
}
return -1
}
// 54ms
fun closestMeetingNode(e: IntArray, a: Int, b: Int): Int {
val qa = ArrayDeque<Int>(); qa += a; var res = e.size
val qb = ArrayDeque<Int>(); qb += b
val va = HashSet<Int>(); val vb = HashSet<Int>();
while (qa.size > 0 || qb.size > 0) {
for (i in 0..<qa.size) {
val x = qa.removeFirst()
if (x in vb) res = min(res, x)
if (va.add(x) && e[x] >= 0) qa += e[x]
}
for (i in 0..<qb.size) {
val x = qb.removeFirst()
if (x in va) res = min(res, x)
if (vb.add(x) && e[x] >= 0) qb += e[x]
}
if (res < e.size) return res
}
return -1
}
// 0ms
pub fn closest_meeting_node(mut e: Vec<i32>, mut a: i32, mut b: i32) -> i32 {
while a >= 0 || b >= 0 { let (i, j) = (a as usize, b as usize);
if a >= 0 && e[i] == -2 { return if b >= 0 && e[j] == -3 { a.min(b) } else { a }}
if a >= 0 { let x = e[i]; e[i] = -3; a = x }
if b >= 0 { if e[j] == -3 { return b } else { let x = e[j]; e[j] = -2; b = x }}
} -1
}
// 0ms
int closestMeetingNode(vector<int>& e, int a, int b) {
while (a >= 0 || b >= 0) {
if (a >= 0 && e[a] == -2) return b >= 0 && e[b] == -3 ? min(a, b) : a;
if (a >= 0) { int t = e[a]; e[a] = -3; a = t; }
if (b >= 0) if (e[b] == -3) return b; else { int t = e[b]; e[b] = -2, b = t; }
} return -1;
}
29.05.2025
3373. Maximize the Number of Target Nodes After Connecting Trees II hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1003
Problem TLDR
Max even-edged siblings after merging trees #hard #graph
Intuition

1. node either in the odd or even set
2. mark nodes, calculate count_odd, count_even
Approach
- track parent or just check mark[y] == 0
- use DFS or BFS
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 110ms
fun maxTargetNodes(e1: Array<IntArray>, e2: Array<IntArray>): IntArray {
val (cm1, cm2) = listOf(e1, e2).map { e ->
val g = Array(e.size + 1) { ArrayList<Int>() }
for ((a, b) in e) { g[a] += b; g[b] += a }
val m = IntArray(g.size); val c = IntArray(3)
fun dfs(x: Int, o: Int) {
m[x] = o; c[o]++; for (y in g[x]) if (m[y] < 1) dfs(y, 3 - o) }
dfs(0, 1); c to m
}
val (c1, m1) = cm1; val (c2, m2) = cm2; val cmax = c2.max()
return IntArray(m1.size) { c1[m1[it]] + cmax }
}
// 63ms
pub fn max_target_nodes(e1: Vec<Vec<i32>>, e2: Vec<Vec<i32>>) -> Vec<i32> {
let [(c1, m1), (c2, m2)] = [e1, e2].map(|e| {
let (mut g, mut m, mut c, mut q, mut q1, mut o) =
(vec![vec![]; e.len() + 1], vec![0; e.len() + 1], [0; 3], vec![0], vec![], 1);
for e in e { let (a, b) = (e[0] as usize, e[1] as usize);
g[a].push(b); g[b].push(a) }
while q.len() > 0 { for &x in &q {
m[x] = o; c[o] += 1; for &y in &g[x] { if m[y] < 1 { q1.push(y) }}}
(q, q1) = (q1, q); o = 3 - o; q1.clear()
}; (c, m)
});
let cmax = c2[1].max(c2[2]); m1.into_iter().map(|m1| c1[m1] + cmax).collect()
}
// 277ms
vector<int> maxTargetNodes(vector<vector<int>>& e1, vector<vector<int>>& e2) {
auto f = [&](auto& e){
vector<vector<int>> g(size(e) + 1);
for (auto& p: e) g[p[0]].push_back(p[1]), g[p[1]].push_back(p[0]);
vector<int> m(size(g)), c(3); queue<int> q; q.push(0); m[0] = 1; c[1]++;
while (size(q)) {
int u = q.front(); q.pop();
for(int v: g[u]) if(!m[v]) m[v] = 3 - m[u], c[m[v]]++, q.push(v); }
return pair {c, m};
};
auto [c1, m1] = f(e1); auto [c2, m2] = f(e2);
int cm = max(c2[1], c2[2]); vector<int> r(size(m1));
for (int i = 0; i < size(m1); ++i) r[i] = c1[m1[i]] + cm;
return r;
}
28.05.2025
3372. Maximize the Number of Target Nodes After Connecting Trees I medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1002
Problem TLDR
Max k-reachable nodes of merged trees #medium #dfs
Intuition
The brute-force DFS is accepted.
Chain-of-thoughts:
// for k - 1
// find the most optimal spot on edges2
// how many nodes can be (k-1) reached from each node
// solve same problem for edges1(k) and edges2(k-1)
// 1000 edges, brute-force bfs from each 1000*k, n^2
// lets write brute-force, no good ideas (23 minutes)
Approach
- sometimes it is better to start with brute-force, then spending too much time thinking about a better algorithm
Complexity
-
Time complexity: \(O(n^2)\), n = 1000
-
Space complexity: \(O(n)\)
Code
// 147ms
fun maxTargetNodes(e1: Array<IntArray>, e2: Array<IntArray>, k: Int): IntArray {
val (g1, g2) = listOf(e1, e2).map { e ->
Array(e.size + 1) { ArrayList<Int>() }.also { g ->
for ((a, b) in e) { g[a] += b; g[b] += a }}}
fun dfs(x: Int, g: Array<ArrayList<Int>>, p: Int, k: Int): Int =
if (k < 0) 0 else 1 + g[x].sumOf { if (it == p) 0 else dfs(it, g, x, k - 1) }
val cnt2 = g2.indices.maxOf { dfs(it, g2, -1, k - 1) }
return IntArray(g1.size) { cnt2 + dfs(it, g1, -1, k) }
}
// 67ms
pub fn max_target_nodes(e1: Vec<Vec<i32>>, e2: Vec<Vec<i32>>, k: i32) -> Vec<i32> {
let [g1, g2] = [e1, e2].map(|e| { let mut g = vec![vec![]; e.len() + 1];
for e in e { let (a, b) = (e[0] as usize, e[1] as usize);
g[a].push(b); g[b].push(a) }; g });
fn dfs(x: usize, g: &[Vec<usize>], p: usize, k: i32) -> i32 {
if k < 0 { 0 } else {
1 + g[x].iter().map(|&s| if s == p { 0 } else { dfs(s, g, x, k - 1)}).sum::<i32>() }}
let cnt2 = (0..g2.len()).map(|x| dfs(x, &g2, 1001, k - 1)).max().unwrap();
(0..g1.len()).map(|x| cnt2 + dfs(x, &g1, 1001, k)).collect()
}
// 95ms
vector<int> maxTargetNodes(vector<vector<int>>& e1, vector<vector<int>>& e2, int k) {
int n = size(e1) + 1, m = size(e2) + 1, c2 = 0; vector<vector<int>> g1(n), g2(m);
for (auto& e: e1) g1[e[0]].push_back(e[1]), g1[e[1]].push_back(e[0]);
for (auto& e: e2) g2[e[0]].push_back(e[1]), g2[e[1]].push_back(e[0]);
auto dfs = [&](this const auto& dfs, int x, vector<vector<int>>& g, int p, int k) -> int {
if (k < 0) return 0; int cnt = 1; for (int s: g[x]) if (s != p) cnt += dfs(s, g, x, k - 1);
return cnt;
}; vector<int> r(n);
for (int i = 0; i < m; ++i) c2 = max(c2, dfs(i, g2, -1, k - 1));
for (int i = 0; i < n; ++i) r[i] = c2 + dfs(i, g1, -1, k); return r;
}
27.05.2025
2894. Divisible and Non-divisible Sums Difference easy
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1001
Problem TLDR
Sum non-divisible minus sum divisible #easy #math
Intuition
I was happy to spot we can do this in a single iteration, sum += x % m ? x : -x
There is an arithmetic math solution however:
// a + b = n*(n+1)/2
// b = m * k*(k+1)/2, k = n/m, m, 2m, 3m...km
// a - b = (a + b) - 2b
// a - b = n*(n+1)/2 - 2*m*k*(k+1)/2
Approach
- how short can it be?
Complexity
-
Time complexity: \(O(n)\), or O(1)
-
Space complexity: \(O(1)\)
Code
// 5ms (52 symbols)
fun differenceOfSums(n: Int, m: Int) =
(1..n).sumOf { if (it % m < 1) -it else it }
// 0ms (49 symbols)
fun differenceOfSums(n: Int, m: Int) =
n * (n + 1) / 2 - n / m * (n / m + 1) * m
// 13ms (47 symbols)
fun differenceOfSums(n: Int, m: Int) =
(1..n).sum() - n / m * (n / m + 1) * m
// 12ms (46 symbols)
fun differenceOfSums(n: Int, m: Int) =
(1..n).sum() - (1..n/m).sum() * m * 2
// 0ms
pub fn difference_of_sums(n: i32, m: i32) -> i32 {
n * (n + 1) / 2 - n / m * (n / m + 1) * m
}
// 0ms
int differenceOfSums(int n, int m) {
return n * (n + 1) / 2 - n / m * (n / m + 1) * m;
}
26.05.2025
1857. Largest Color Value in a Directed Graph hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/1000
Problem TLDR
Max color freq path #hard #dp #toposort
Intuition
// for every node
// (freq of colors)
// we want max(freq)
As graph is directed asyclic graph, we can assume each node has definite answer of top color frequencies of all path from it.
Walk those paths in DFS or BFS with toposort.
Approach
- to check cycle use a hashset, don’t forget to remove from it after we done, as we can have two different valid paths to the same node
- the toposort is: 1) count incoming nodes 2) always add to the queue
zeroincoming nodes
Complexity
-
Time complexity: \(O(VE)\)
-
Space complexity: \(O(V + E)\)
Code
// 1213ms
fun largestPathValue(c: String, e: Array<IntArray>): Int {
val g = Array(c.length) { ArrayList<Int>() }; for ((a, b) in e) g[a] += b
val v = HashSet<Int>(); val dp = HashMap<Int, IntArray>()
fun dfs(i: Int): IntArray? = dp.getOrPut(i) { val res = IntArray(26)
for (s in g[i]) {
if (!v.add(s)) return@dfs null; val next = dfs(s) ?: return@dfs null
v.remove(s); for (j in 0..25) res[j] = max(res[j], next[j])
}; res[c[i] - 'a']++; res
}
return c.indices.maxOf { dfs(it)?.max() ?: return -1 }
}
// 802ms
fun largestPathValue(c: String, e: Array<IntArray>): Int {
val d = IntArray(c.length); val g = Array(d.size) { ArrayList<Int>() }
val cnt = Array(d.size) { IntArray(26) }; for ((a, b) in e) { g[a] += b; ++d[b] }
var q = ArrayList<Int>(); var q1 = ArrayList<Int>(); var r = 0; var v = 0;
for (i in d.indices) if (d[i] == 0) q += i;
while (q.size > 0) {
for (i in q) {
++v; r = max(r, ++cnt[i][c[i] - 'a'])
for (j in g[i]) {
for (k in 0..25) cnt[j][k] = max(cnt[j][k], cnt[i][k])
if (--d[j] == 0) q1 += j
}
}
q = q1.also { q1 = q; q1.clear() }
}
return if (v == d.size) r else -1
}
// 69ms
pub fn largest_path_value(c: String, e: Vec<Vec<i32>>) -> i32 {
let (mut g, c, mut d, mut q) = (vec![vec![]; c.len()], c.as_bytes(), vec![0; c.len()], vec![]);
let (mut cnt, mut q1, mut r, mut v) = (vec![vec![0; 26]; c.len()], vec![], 0, 0);
for e in e { let (a, b) = (e[0] as usize, e[1] as usize); g[a].push(b); d[b] += 1; }
for i in 0..d.len() { if d[i] == 0 { q.push(i) }}
while q.len() > 0 {
for &i in &q { let c = (c[i] - b'a') as usize;
v += 1; cnt[i][c] += 1; r = r.max(cnt[i][c]);
for &j in &g[i] {
for k in 0..26 { cnt[j][k] = cnt[j][k].max(cnt[i][k]); }
d[j] -= 1; if d[j] == 0 { q1.push(j) } }
} (q, q1) = (q1, q); q1.clear()
} if v == d.len() { r } else { -1 }
}
// 312ms
int largestPathValue(string c, vector<vector<int>>& e) {
int n = size(c), v = 0, r = 0; vector<array<int,26>> cnt(n);
vector<vector<int>> g(n); vector<int> d(n); queue<int> q;
for (auto& p : e) { g[p[0]].push_back(p[1]); ++d[p[1]]; }
for (int i = 0; i < n; i++) if (!d[i]) q.push(i);
while (!q.empty()) {
int i = q.front(); q.pop(); ++v; r = max(r, ++cnt[i][c[i] - 'a']);
for (int j: g[i]) {
for (int k = 0; k < 26; k++) cnt[j][k] = max(cnt[j][k], cnt[i][k]);
if (--d[j] == 0) q.push(j);
}
}
return v == n ? r : -1;
}
25.05.2025
2131. Longest Palindrome by Concatenating Two Letter Words medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/999
Problem TLDR
Max palindrome length from 2 char words #medium
Intuition
Calculate frequencies.
- count mirrors, take min f[ab], f[ba]
- take a single odd from twins f[aa] % 2
Approach
- don’t forget *2
- take half of twins: f[aa] / 2
- we can do it one-pass, runtime is worse as we are doing more operations in the longest loop O(10^5)
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 38ms
fun longestPalindrome(w: Array<String>): Int {
val f = w.groupBy { it }; var o = 0
return 2 * f.entries.sumOf { (w, f1) ->
if (w[0] == w[1]) { if (f1.size % 2 > 0) o = 2; 2 * (f1.size / 2) }
else min(f1.size, f[w.reversed()]?.size ?: 0) } + o
}
// 20ms
fun longestPalindrome(w: Array<String>): Int {
val f = IntArray(676); var o = 0; var r = 0
for (w in w) {
val a = w[0] - 'a'; val b = w[1] - 'a'
val w = a * 26 + b
if (f[w] > 0) { --f[w]; r += 4 } else ++f[b * 26 + a]
if (a == b) o += 2 * (f[w] and 1) - 1
}
return r + if (o > 0) 2 else 0
}
// 7ms https://leetcode.com/problems/longest-palindrome-by-concatenating-two-letter-words/submissions/1643834111
fun longestPalindrome(w: Array<String>): Int {
val f = IntArray(676); var o = 0; var r = 0
for (w in w) ++f[(w[0] - 'a') * 26 + (w[1] - 'a')]
for (w in 0..675) if (f[w] > 0) r +=
if (w / 26 == w % 26) { o = o or (f[w] and 1); f[w] and (-2) }
else min(f[w], f[(w % 26) * 26 + w / 26])
return 2 * (r + o)
}
// 20ms
pub fn longest_palindrome(words: Vec<String>) -> i32 {
let (mut f, mut r, mut o) = ([0; 676], 0, 0);
for w in words { let w = w.as_bytes();
let (a, b) = ((w[0] - b'a') as usize, (w[1] - b'a') as usize);
let w = a * 26 + b;
if f[w] > 0 { f[w] -= 1; r += 4 } else { f[b * 26 + a] += 1 }
if a == b { o += 2 * (f[w] & 1) - 1 }
} r + (o > 0) as i32 * 2
}
// 6ms https://leetcode.com/problems/longest-palindrome-by-concatenating-two-letter-words/submissions/1643877476
pub fn longest_palindrome(words: Vec<String>) -> i32 {
let (mut f, mut o) = ([0; 676], 0);
for w in words { let w = w.as_bytes();
let (a, b) = ((w[0] - b'a') as usize, (w[1] - b'a') as usize);
f[a * 26 + b] += 1
}
(0..26).flat_map(|a| (a..26).map(move |b| (a, b, f[a * 26 + b])))
.map(|(a, b, fw)| if a == b { o |= fw & 1; fw >> 1 }
else { fw.min(f[b * 26 + a]) }).sum::<i32>() * 4 + o * 2
}
// 1ms
int longestPalindrome(vector<string>& words) {
int f[676]={}, o = 0, r = 0;
for (auto& s: words) {
int a = s[0] - 'a', b = s[1] - 'a';
int w = a * 26 + b;
if (f[w]) --f[w], r += 4; else ++f[b * 26 + a];
if (a == b) o += 2 * (f[w] & 1) - 1;
} return r + 2 * (o > 0);
}
24.05.2025
2942. Find Words Containing Character easy
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/998
Problem TLDR
Indices with x #easy
Intuition
Do what is asked
Approach
- the answer can be in
any ordersuggests some interesting optimizations: what if we unroll loops or even start work in parallel? (however, in Kotlin I wasnt able to gain any performance)
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 25ms
fun findWordsContaining(w: Array<String>, x: Char) =
w.indices.filter { x in w[it] }
// 9ms
fun findWordsContaining(w: Array<String>, x: Char): List<Int> {
val res = ArrayList<Int>(w.size)
for (i in w.indices) if (x in w[i]) res += i
return res
}
// 3ms
fun findWordsContaining(w: Array<String>, x: Char): List<Int> {
val res = ArrayList<Int>(w.size)
for (i in w.indices)
for (c in w[i]) if (c == x) { res += i; break }
return res
}
// 0ms
pub fn find_words_containing(w: Vec<String>, x: char) -> Vec<i32> {
(0..w.len()).filter(|&i| w[i].contains(x)).map(|i| i as _).collect()
}
// 0ms
vector<int> findWordsContaining(vector<string>& w, char x) {
vector<int> r;
for (int i = 0; i < size(w); ++i) if (w[i].contains(x)) r.push_back(i);
return r;
}
23.05.2025
3068. Find the Maximum Sum of Node Values hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/997
Problem TLDR
Max sum by k-xoring edges #hard #tree #dp
Intuition
Didn’t solved the second time (2024 was the previous attempt)
// 1 - 0 - 2
// a - b - c
// ^k ^k
// ^k ^k a^k - b - c^k
// a - b - c - d
// ^ ^
// ^ ^
// ^ ^ a^k - b - c - d^k
//
// a^k b c d^k
// a^k b c^k d
// a^k b^k c d
// a^k b^k c^k d^k
// a b^k c^k d
// a b c^k d^k
// a b^k c d^k
// a - b - c a*- b*- c - e*
// | |
// d d*
// didn't see any simple law
// maybe full search?
// wong answer: careful with flipping the last (it flips the previous?)
// 0-2-4-3
// |
// 1
//
// 5-0-1*-3*-6-2*
// |
// 4*
// flip current without flipping previous:
// 1. if has next
// 51 minutes, use hints, looks like the same dp (and what is parity?)
// looks like i did the same mistake in 2024 (and didn't finished dp)
What was missing:
- I didn’t paid attention to the detail: only even number of flipped numbers is possible
Why my DFS+cache simultaion didn’t worked:
- when children count > 1, we can’t flip them all simultaneously
Approach
- attention to details: how many flips can be done, how flips happen when node has many chilren
- can you rewrite DFS dp to return a single Long result?
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\), O(n) for dp
Code
fun maximumValueSum(nums: IntArray, k: Int, edges: Array<IntArray>): Long {
var sum = 0L; var xored = 0; var diff = Int.MAX_VALUE / 2
for (x in nums) {
sum += 1L * max(x, x xor k)
if (x xor k > x) xored++
diff = min(diff, abs((x xor k) - x))
}
return sum - diff * (xored % 2)
}
fun maximumValueSum(nums: IntArray, k: Int, edges: Array<IntArray>): Long {
val g = Array(nums.size) { ArrayList<Int>() }
for ((u, v) in edges) { g[u] += v; g[v] += u }
val dp = HashMap<Int, Pair<Long, Long>>()
fun dfs(u: Int, p: Int): Pair<Long, Long> = dp.getOrPut(u) {
var sumFlip = Long.MIN_VALUE / 2
var sumStay = 0L
for (v in g[u]) if (v != p) {
val (flip, stay) = dfs(v, u)
sumFlip = max(sumStay + stay, sumFlip + flip).also {
sumStay = max(sumStay + flip, sumFlip + stay) }
}
val stay = nums[u]
val flip = stay xor k
sumFlip = max(sumStay + stay, sumFlip + flip).also {
sumStay = max(sumStay + flip, sumFlip + stay) }
sumFlip to sumStay
}
return dfs(0, -1).first
}
fun maximumValueSum(nums: IntArray, k: Int, edges: Array<IntArray>): Long {
val g = Array(nums.size) { ArrayList<Int>() }
for ((u, v) in edges) { g[u] += v; g[v] += u }
val dp = HashMap<Pair<Int, Int>, Long>()
fun dfs(u: Int, p: Int, f: Int): Long = dp.getOrPut(u to f) {
val flip = (nums[u] xor k xor f).toLong()
val stay = (nums[u] xor f).toLong()
var sum = max(flip, stay)
var flips = if (flip > stay) 1 else 0
var diff = abs(flip - stay)
for (v in g[u]) if (v != p) {
val flip = dfs(v, u, k)
val stay = dfs(v, u, 0)
if (flip > stay) flips = flips xor 1
diff = min(diff, abs(flip - stay))
sum += max(flip, stay)
}
sum - diff * flips
}
return dfs(0, -1, 0)
}
pub fn maximum_value_sum(n: Vec<i32>, k: i32, edges: Vec<Vec<i32>>) -> i64 {
let (mut s, mut c, mut d) = (0, 0, i32::MAX);
for x in n {
s += x.max(x ^ k) as i64;
if x ^ k > x { c ^= 1 }
d = d.min(((x ^ k) - x).abs())
} s - d as i64 * c
}
long long maximumValueSum(vector<int>& n, int k, vector<vector<int>>& edges) {
long long s = 0, c = 0, d = 1e9;
for (int& x: n) {
s += max(x, x ^ k);
if ((x ^ k) > x) c ^= 1;
d = min(d, 1LL * abs((x ^ k) - x));
} return s - d * c;
}
22.05.2025
3362. Zero Array Transformation III medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/996
Problem TLDR
Max removed queries still zero-fy an array #medium #heap
Intuition
Didn’t solved.
Irrelevant chain-of-thougths for history:
// [1,1,1,1]
// [[1,3],[0,2],[1,3],[1,2]]
// 0,2 1,2 1,3 1,3
// 0 1 2 3
// 0, 3, 3, 1, -2
// i j 0,2 take
// 1,2 drop, 3,3 -> 2,2 min=2
// i j 1,3 drop, 2,2,1 -> 2,2,0, min=0
// *running interval minimum* increasing queue?
// looks like too hard for medium, maybe wrong algo?
// use hints
// sort: already done
// pick max end: already do ?
//
// [1,1,1,1]
// i 1..3
// i max = 1
// 1..3
// 2 0 2
// 1 1 0..2
//
// 2 2 0..2
// 1 1..1 move and compute running sum
// ok, i fail
The working solution:
- sort queries by start
- iterate the nums
- maintain the current accepted queries sum
- put accepted queries (start, end) into a line sweep diff array
- hard part: put candidate queries (same start) ends into a sorted heap, poll lazily when needed
Approach
- it looks like I’ve solved it previously in contest, but havn’t absorbed the solution, or, even possible degraded in the solution search
- I’ve solved the wrong problem on the start and spent some mind power
Complexity
-
Time complexity: \(O(nlog(n))\)
-
Space complexity: \(O(n)\)
Code
fun maxRemoval(nums: IntArray, queries: Array<IntArray>): Int {
val h = PriorityQueue<Int>(); val d = IntArray(nums.size + 1)
queries.sortBy { it[0] }; var qsum = 0; var j = 0
for ((i, x) in nums.withIndex()) {
while (j < queries.size && queries[j][0] == i) h += -queries[j++][1]
qsum += d[i]
while (x > qsum && h.size > 0 && -h.peek() >= i) {
d[-h.poll() + 1]--; qsum++
}
if (x > qsum) return -1
}
return h.size
}
pub fn max_removal(n: Vec<i32>, mut q: Vec<Vec<i32>>) -> i32 {
let (mut h, mut d) = (BinaryHeap::new(), vec![0; n.len() + 1]);
q.sort_unstable(); let (mut lvl, mut j) = (0, 0);
for i in 0..n.len() {
while j < q.len() && q[j][0] == i as i32 { h.push(q[j][1] as usize); j += 1 }
lvl += d[i];
while n[i] > lvl && h.len() > 0 && *h.peek().unwrap() >= i {
d[h.pop().unwrap() + 1] -= 1; lvl += 1
}
if n[i] > lvl { return -1 }
} h.len() as _
}
int maxRemoval(vector<int>& n, vector<vector<int>>& q) {
priority_queue<int> h; int l = 0, j = 0;
vector<int> d(n.size() + 1); sort(q.begin(), q.end());
for (int i = 0, N = n.size(); i < N; ++i) {
while (j < q.size() && q[j][0] == i)
h.push(q[j++][1]);
l += d[i];
while (l < n[i] && !h.empty() && h.top() >= i)
l++, d[h.top() + 1]--, h.pop();
if (l < n[i]) return -1;
}
return h.size();
}
21.05.2025
73. Set Matrix Zeroes medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/995
Problem TLDR
Zero-fy rows and columns #medium
Intuition
Do what is asked. In-place: use first row and column
Approach
- don’t fall into trap of overriding the good rows
- minimize iterations by checking
m[0][x] || m[y][0] - check separately if you need to zero-fy the first row and column
Complexity
-
Time complexity: \(O(mn)\)
-
Space complexity: \(O(n)\) or O(1)
Code
// 16ms
fun setZeroes(m: Array<IntArray>): Unit {
val zc = m[0].indices.filter { x -> m.any { it[x] == 0 }}
for (r in m) if (0 in r) r.fill(0)
for (x in zc) for (r in m) r[x] = 0
}
// 1ms
fun setZeroes(m: Array<IntArray>): Unit {
var fr = false; var fc = false; val c = m[0]
for ((y, r) in m.withIndex()) for (x in r.indices) if (r[x] == 0)
{ if (y == 0) fr = true; if (x == 0) fc = true; c[x] = 0; r[0] = 0 }
for (y in 1..<m.size) for (x in 1..<c.size)
if (c[x] == 0 || m[y][0] == 0) m[y][x] = 0
if (fc) for (r in m) r[0] = 0; if (fr) for (x in c.indices) c[x] = 0
}
// 0ms
pub fn set_zeroes(m: &mut Vec<Vec<i32>>) {
let (mut fr, mut fc) = (false, false);
for y in 0..m.len() { for x in 0..m[0].len() { if m[y][x] == 0 {
fr |= y == 0; fc |= x == 0; m[0][x] = 0; m[y][0] = 0
}}}
for y in 1..m.len() { for x in 1..m[0].len() {
if m[0][x] == 0 || m[y][0] == 0 { m[y][x] = 0 }
}}
if fc { for y in 0..m.len() { m[y][0] = 0 } }
if fr { m[0][..].fill(0) }
}
// 0ms
void setZeroes(vector<vector<int>>& m) {
int fr = 0, fc = 0; vector<int>& c = m[0];
for (int y = 0; y < size(m); ++y) for (int x = 0; x < size(c); ++x) if (!m[y][x])
fr |= y == 0, fc |= x == 0, c[x] = 0, m[y][0] = 0;
for (int y = 1; y < size(m); ++y) for (int x = 1; x < size(c); ++x) if (!c[x] || !m[y][0]) m[y][x] = 0;
if (fc) for (int y = 0; y < size(m); ++y) m[y][0] = 0;
if (fr) for (int x = 0; x < size(c); ++x) c[x] = 0;
}
20.05.2025
3355. Zero Array Transformation I medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/994
Problem TLDR
Can intersecting intervals decrease an array #medium #line_sweep
Intuition
Line sweep trick: store starts and ends of the intervals, then do the line sweep by increasing and decreasing prefix sum.
Approach
- decreasing should be
afterthe end
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 22ms
fun isZeroArray(nums: IntArray, queries: Array<IntArray>): Boolean {
val d = IntArray(nums.size + 1); var s = 0
for ((s, e) in queries) { d[s]++; d[e + 1]-- }
return nums.zip(d).all { (n, d) -> s += d; s >= n }
}
// 3ms
fun isZeroArray(nums: IntArray, queries: Array<IntArray>): Boolean {
val d = IntArray(nums.size + 1); var s = 0
for ((s, e) in queries) { d[s]++; d[e + 1]-- }
for ((i, x) in nums.withIndex()) {
s += d[i]
if (s < x) return false
}
return true
}
// 5ms
pub fn is_zero_array(nums: Vec<i32>, queries: Vec<Vec<i32>>) -> bool {
let (mut d, mut s) = (vec![0; nums.len() + 1], 0);
for q in queries { d[q[0] as usize] += 1; d[q[1] as usize + 1] -= 1 }
nums.iter().zip(d.iter()).all(|(x, d)| { s += d; s >= *x })
}
// 0ms https://leetcode.com/problems/zero-array-transformation-i/submissions/1638961889
bool isZeroArray(vector<int>& nums, vector<vector<int>>& queries) {
vector<int> d(size(nums) + 1); int s = 0;
for (auto& q: queries) ++d[q[0]], --d[q[1] + 1];
for (int i = 0; int x: nums) { s += d[i++]; if (s < x) return 0; }
return 1;
}
19.05.2025
3024. Type of Triangle easy
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/993
Problem TLDR
Triangle type by lengths #easy
Intuition
Was surprisingly hard to work all the corner cases.
Approach
- a = max(), b = min(), c = sum() - a - b
Complexity
-
Time complexity: \(O(brain)\)
-
Space complexity: \(O(1)\)
Code
fun triangleType(n: IntArray) =
listOf("none", "equilateral", "isosceles", "scalene")[
if (2 * n.max() >= n.sum()) 0 else n.toSet().size]
pub fn triangle_type(mut n: Vec<i32>) -> String {
n.sort();
(if n[2] >= n[0] + n[1] { "none" } else
if n[0] == n[2] { "equilateral" } else
if n[0] == n[1] || n[1] == n[2] { "isosceles" } else { "scalene" }).into()
}
string triangleType(vector<int>& nums) {
int f[101]={}, m = 0, mf = 0, s = 0;
for (int x: nums) mf = max(mf, ++f[x]), m = max(m, x), s += x;
return array{"none", "scalene", "isosceles", "equilateral"}[2 * m >= s ? 0 : mf];
}
18.05.2025
1931. Painting a Grid With Three Different Colors hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/992
Problem TLDR
Ways to 3-color m*n grid, no adjucents #hard #dp #matrix
Intuition
The naive DP works:
- walk all possible ways to color the current column with DFS
- pre-compute all possible columns (at max 5 length)
- make a bitmask to compare with the previous
- cache by the
bitmaskand thecurrent column
// masks
// 00000
// 12121
// 12131 3^5 9*9*3 = 81*3 x 1000 = 100.000 ok
Then we can rewrite DFS into iterative, and we only have to keep the previous result.
For each mask we can use its indice.
Then the matrix trick:
- notice we do
noperations of the same trasformationop(X) = Y - the operation can be described as a
transition matrix:Y = X * M - doing it
ntimes can be written asY = X * M^n
The transition matrix is as follows:
mask1\mask2 a b c d ...
a 1 x x = 1 if a & b == 0
b
c 1 x x = 1 if c & d == 0
d
.
.
.
The starting X matrix is an identity matrix i == j ? 1 : 0.
The exponentiation trick is derived from the arithmetics: x^n = x^(2 * n/2 + n%2) = x^2 * x^(n/2) * x^(n%2)
Approach
- use 3 bits in the mask to quick check
m & mask == 0later
Complexity
-
Time complexity: \(O(n)\), consider m small as constant
-
Space complexity: \(O(1)\)
Code
// 188ms
fun colorTheGrid(m: Int, n: Int): Int {
val M = 1000000007; val masks = ArrayList<Int>()
fun msk(i: Int, curr: Int, prev: Int) {
if (i > m) masks += curr else
for (j in 1..3) if (j != prev) msk(i + 1, (curr shl 3) or (1 shl j), j)
}
val dp = HashMap<Pair<Int, Int>, Int>()
fun dfs(i: Int, mask: Int): Int = if (i == n) 1 else
dp.getOrPut(i to mask) {
masks.fold(0) { c, m -> if ((m and mask) == 0) (c + dfs(i + 1, m)) % M else c }
}
msk(1, 0, 0); return dfs(0, 0)
}
// 98ms
fun colorTheGrid(m: Int, n: Int): Int {
val M = 1000000007; val ms = ArrayList<Int>()
fun msk(i: Int, curr: Int, p: Int) {
if (i > m) ms += curr else for (j in 1..3) if (j != p)
msk(i + 1, (curr shl 3) or (1 shl j), j)
}
msk(1, 0, 0); val s = ms.size; var n = n - 1; var res = 0
var m = Array(s) { a -> IntArray(s) { if ((ms[a] and ms[it]) == 0) 1 else 0 }}
fun mmul(b: Array<IntArray>) = Array(s) { IntArray(s) }.also { r ->
for (i in 0..<s) for (j in 0..<s) for (k in 0..<s)
r[i][j] = (r[i][j] + ((1L * b[i][k] * m[k][j]) % M).toInt()) % M
}
var mn = Array(s) { y -> IntArray(s) { if (y == it) 1 else 0 }}
while (n > 0) { if (n % 2 > 0) mn = mmul(mn); m = mmul(m); n /= 2 }
for (i in 0..<s) for (j in 0..<s) res = (res + mn[i][j]) % M
return res
}
// 28ms https://leetcode.com/problems/painting-a-grid-with-three-different-colors/submissions/1637068717
fun colorTheGrid(m: Int, n: Int): Int {
val M = 1000000007; val masks = ArrayList<Int>()
fun msk(i: Int, curr: Int, prev: Int) {
if (i > m) masks += curr else
for (j in 1..3) if (j != prev) msk(i + 1, (curr shl 3) or (1 shl j), j)
}
msk(1, 0, 0); var dp = IntArray(masks.size) { 1 }; var dp2 = IntArray(masks.size)
for (i in 1..<n) {
for (mask in masks.indices) {
var c = 0
for (m in masks.indices)
if ((masks[m] and masks[mask]) == 0) c = (c + dp[m]) % M
dp2[mask] = c
}
dp = dp2.also { dp2 = dp }
}
return dp.fold(0) { r, t -> (r + t) % M }
}
// 11ms
pub fn color_the_grid(m: i32, n: i32) -> i32 {
let M = 1000000007; let mut ms = vec![];
fn msk(i: i32, c: i32, p: i32, ms: &mut Vec<i32>) {
if i < 1 { ms.push(c); return }
for j in 1..4 { if j != p { msk(i - 1, (c << 3) | (1 << j), j, ms) }}
}; msk(m, 0, 0, &mut ms); let s = ms.len();
let (mut dp, mut dp2) = (vec![1; s], vec![0; s]);
for _ in 1..n { for mask in 0..s { let mut c = 0; for m in 0..s {
if (ms[m] & ms[mask]) == 0 { c = (c + dp[m]) % M }}; dp2[mask] = c
}; (dp, dp2) = (dp2, dp) }
dp.into_iter().fold(0, |r, t| (r + t) % M)
}
// 19ms
int colorTheGrid(int m, int n) {
vector<int> ms;
auto msk = [&](this const auto& msk, int i, int c, int p) -> void {
if (!i) ms.push_back(c); else for (int j = 1; j < 4; ++j)
if (j != p) msk(i - 1, (c << 3) | (1 << j), j);
};
msk(m, 0, 0);
int M = 1e9+7, s = size(ms), r = 0; vector<int> dp(s, 1), dp2(s);
for (int i = 1; i < n; ++i) {
for (int mask = 0; mask < s; ++mask) {
int c = 0; for (int m = 0; m < s; ++m)
if (!(ms[m] & ms[mask])) c = (c + dp[m]) % M;
dp2[mask] = c;
}
dp.swap(dp2);
}
for (int x: dp) r = (r + x) % M; return r;
}
17.05.2025
75. Sort Colors medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/991
Problem TLDR
Sort 0,1,2 array #medium #two_pointers
Intuition
The two-pass solution is trivial: count, then write. Was very close to implement the single-pass solution:
// 2,0,2,1,1,0
// z t
// i
// 0 t 2
// i
// z
// i
// 1 t 2
//
// 0 0 1 1 2 2
// 2 0 1
// z t
// i
// t
// 1 0 2
What was missing: the final check i == t to check if nums[t] is zero.
Approach
Single pass:
- fill prefix with
0and suffix with2 - skip
1 - the corner case is
10: swapnums[t]with prefix if it is0 - or, we can make the final check
i == t, then it is handled by thenums[i] == 0condition
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
fun sortColors(nums: IntArray): Unit {
val c = IntArray(3); var i = 0
for (x in nums) ++c[x]
for (x in 0..2) while (c[x]-- > 0) nums[i++] = x
}
fun sortColors(n: IntArray): Unit {
var z = 0; var t = n.size - 1; var i = 0
while (i <= t)
if (n[i] == 2) { n[i] = n[t]; n[t--] = 2 }
else if (n[i] == 0) { n[i++] = n[z]; n[z++] = 0 }
else i++
}
pub fn sort_colors(n: &mut Vec<i32>) {
let (mut z, mut t, mut i) = (0, n.len() - 1, 0);
while i <= t && t < n.len() { match n[i] {
0 => { n.swap(i, z); i += 1; z += 1 }
2 => { n.swap(i, t); t -= 1 }
_ => { i += 1 }
}}
}
void sortColors(vector<int>& n) {
for (int i = 0, z = 0, t = size(n) - 1; i <= t;)
if (n[i] == 0) n[i++] = n[z], n[z++] = 0;
else if (n[i] == 2) n[i] = n[t], n[t--] = 2;
else i++;
}
16.05.2025
2901. Longest Unequal Adjacent Groups Subsequence II medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/990
Problem TLDR
Longest subsequence humming distance 1, alterating groups #medium #dp
Intuition
The naive DP works: consider each position, take or not. Cache by the current and the previous taken position.
Approach
Optimizations:
- only the previous position matters for the cache; search for the tail after it
- rewrite DFS into iterative backwards
for - then reverse the iterations: for each
iconsider0..i-1prefixes, choose the longest - use the
parentsarray to save only the lengths intodparray
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(n)\)
Code
// 166ms
fun getWordsInLongestSubsequence(w: Array<String>, g: IntArray): List<String> {
val dp = Array(w.size + 1) { listOf<String>() }
for (i in 0..w.size) for (j in 0..<i)
if (i == w.size || g[i] != g[j] && w[i].length == w[j].length &&
w[i].indices.count { w[i][it] != w[j][it] } < 2)
if (dp[j].size + 1 > dp[i].size) dp[i] = dp[j] + w[j]
return dp[w.size]
}
// 44ms https://leetcode.com/problems/longest-unequal-adjacent-groups-subsequence-ii/submissions/1635364675
fun getWordsInLongestSubsequence(w: Array<String>, g: IntArray): List<String> {
val dp = Array(w.size) { listOf<String>() }
for (i in w.indices) {
val wi = w[i]; val gi = g[i]
for (j in 0..<i) if (g[i] != g[j] && wi.length == w[j].length) {
val wj = w[j]; var c = 0
for (k in wi.indices) {
if (wi[k] != wj[k]) c++
if (c > 1) break
}
if (c < 2 && dp[j].size + 1 > dp[i].size) dp[i] = dp[j] + wj
}
}
var res = listOf<String>()
for (j in w.indices) if (dp[j].size + 1 > res.size) res = dp[j] + w[j]
return res
}
// 31ms https://leetcode.com/problems/longest-unequal-adjacent-groups-subsequence-ii/submissions/1635402651
fun getWordsInLongestSubsequence(w: Array<String>, g: IntArray): Array<String?> {
val dp = IntArray(w.size + 1); val p = IntArray(dp.size)
for (i in w.indices) {
val wi = w[i]; val gi = g[i]
for (j in 0..<i) if (g[i] != g[j] && wi.length == w[j].length) {
val wj = w[j]; var c = 0
for (k in wi.indices) {
if (wi[k] != wj[k]) c++
if (c > 1) break
}
if (c < 2 && dp[j] + 1 > dp[i]) { dp[i] = dp[j] + 1; p[i] = j + 1 }
}
}
for (j in w.indices) if (dp[j] + 1 > dp[w.size]) { dp[w.size] = dp[j] + 1; p[w.size] = j + 1 }
val res = Array<String?>(dp[w.size]) { null }; var x = w.size; var k = res.size - 1
while (p[x] > 0) { res[k--] = w[p[x] - 1]; x = p[x] - 1 }
return res
}
// 304ms
pub fn get_words_in_longest_subsequence(w: Vec<String>, g: Vec<i32>) -> Vec<String> {
let mut dp = vec![Vec::<String>::new(); w.len() + 1];
for i in 0..dp.len() { for j in 0..i { if
i == w.len() || g[i] != g[j] && w[i].len() == w[j].len() &&
w[i].bytes().zip(w[j].bytes()).filter(|(a, b)| a != b).count() < 2 {
if dp[j].len() + 1 > dp[i].len() { let mut s = dp[j].clone(); s.push(w[j].clone()); dp[i] = s }}}}
dp[w.len()].clone()
}
// 7ms https://leetcode.com/problems/longest-unequal-adjacent-groups-subsequence-ii/submissions/1635396131
pub fn get_words_in_longest_subsequence(w: Vec<String>, g: Vec<i32>) -> Vec<String> {
let mut dp = vec![0; w.len() + 1]; let mut p = vec![None; dp.len()];
for i in 1..=w.len() { for j in 0..i {
if (i == w.len() || (g[i] != g[j] && w[i].len() == w[j].len()
&& w[i].bytes().zip(w[j].bytes()).filter(|(a, b)| a != b).count() < 2))
&& dp[j] + 1 > dp[i] { dp[i] = dp[j] + 1; p[i] = Some(j); }
}}
let (mut res, mut i) = (Vec::with_capacity(dp[w.len()]), w.len());
while let Some(j) = p[i] { res.push(w[j].clone()); i = j; }
res.reverse(); res
}
// 59ms
vector<string> getWordsInLongestSubsequence(vector<string>& w, vector<int>& g) {
int n = w.size(); vector<int> dp(n+1), p(n+1, -1); vector<string> r;
for (int i = 1; i <= n; ++i) for (int j = 0; j < i; ++j) {
bool ok = i == n
|| (g[i] != g[j] && size(w[i]) == size(w[j])
&& [&]{ int c=0;
for (int k=0; k<size(w[i]); ++k)
if (w[i][k]!=w[j][k] && ++c>=2) return false;
return true;
}());
if (ok && dp[j] + 1 > dp[i]) dp[i] = dp[j] + 1, p[i] = j;
}
for (int i = n; p[i] != -1; i = p[i]) r.push_back(w[p[i]]);
reverse(r.begin(), r.end()); return r;
}
15.05.2025
2900. Longest Unequal Adjacent Groups Subsequence I easy
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/989
Problem TLDR
Longest subsequence alterating g #easy #gready
Intuition
Taking the first is always the optimal greedy strategy:
// 101
// 010
Approach
- we actually don’t have to remember the last
g[i], compare with the previous - O(n^2), O(1) memory solution: remove from
words(c++)
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
// 22ms
fun getLongestSubsequence(w: Array<String>, g: IntArray) =
g.indices.filter { it < 1 || g[it - 1] != g[it] }.map(w::get)
// 15ms
fun getLongestSubsequence(w: Array<String>, g: IntArray) = buildList {
for (i in g.indices) if (i < 1 || g[i] != g[i - 1]) this += w[i]
}
// 1ms
fun getLongestSubsequence(w: Array<String>, g: IntArray): List<String> {
val res = ArrayList<String>()
for (i in g.indices) if (i < 1 || g[i] != g[i - 1]) res += w[i]
return res
}
// 0ms
pub fn get_longest_subsequence(mut w: Vec<String>, g: Vec<i32>) -> Vec<String> {
for i in (1..g.len()).rev() { if g[i] == g[i - 1] { w.remove(i); }} w
}
// 0ms
pub fn get_longest_subsequence(w: Vec<String>, g: Vec<i32>) -> Vec<String> {
w.into_iter().enumerate().filter(|&(i, _)| i < 1 || g[i - 1] != g[i]).map(|(_, w)| w).collect()
}
// 0ms
vector<string> getLongestSubsequence(vector<string>& w, vector<int>& g) {
for(int i = w.size(); i-- > 1; ) if (g[i] == g[i-1]) w.erase(begin(w) + i);
return w;
}
14.05.2025
3337. Total Characters in String After Transformations II hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/988
Problem TLDR
t steps to convert char into next nums[c] chars #hard #dp #math
Intuition
Didn’t solve. Irrelevant chain of thoughts:
// a -> bc t = 1
// b -> cd
// c -> de 1c 2d 1e t = 2
// c -> de
// 2d -> ef ef
// e -> fg 1d 3e 3f 1g t = 3
// d -> ef
// 3e -> fg fg fg
// 3f -> gh gh gh
// g -> hi 1e 4f 6g 4h 1i t = 4
// ...
// t = 26
//
// exponentiation...
// t = 492153482 /26 = 18 928 980.0769
// 1hr hint "Model the problem as a matrix multiplication problem." lol"
How growth law described by matrix:
from\to
a b c d e f g .. z
a 1 1 nums[a] = 2
b 1 1 1 1 nums[b] = 4
c 1 nums[c] = 1
d 1 1 1 nums[d] = 3
e
..
z
Now, by applying the matrix into initial frequency we will make a single step: f = f x M.
To make t steps: f_t = f x M^t.
The exponentiation trick is from math: a^t = a^(2 * t/2) + a^(2 * t%2)
Approach
- what’s missing: matrix trick for dp
Complexity
-
Time complexity: \(O(s + log(t))\)
-
Space complexity: \(O(1)\)
Code
// 701ms
fun lengthAfterTransformations(s: String, t: Int, nums: List<Int>): Int {
var f = LongArray(26); for (c in s) ++f[c - 'a']; val M = 1000000007L
var m = Array(26) { c -> LongArray(26) }; var t = t; var res = 0L
for (i in 0..25) for (j in i + 1..<i + nums[i] + 1) m[i][j % 26] = 1
fun matMul(m1: Array<LongArray>): Array<LongArray> {
val res = Array(26) { LongArray(26)}
for (i in 0..25) for (j in 0..25) for (k in 0..25)
res[i][j] = (res[i][j] + (m1[i][k] * m[k][j]) % M + M) % M
return res
}
var mt = Array(26) { y -> LongArray(26) { x -> if (x == y) 1 else 0 }}
while (t > 0) { if (t % 2 > 0) mt = matMul(mt); m = matMul(m); t /= 2 }
for (j in 0..25) for (k in 0..25) res = (res + (f[k] * mt[k][j]) % M) % M
return res.toInt()
}
// 24ms
pub fn length_after_transformations(s: String, mut t: i32, n: Vec<i32>) -> i32 {
const M: u64 = 1_000_000_007; let (mut f, mut m) = ([0u64; 26], [[0u64; 26]; 26]);
for b in s.bytes() { f[(b - b'a') as usize] += 1 }
for i in 0..26 { for j in 1..=n[i] as usize { m[i][(i + j) % 26] = 1 }}
let mut e = [[0u64; 26]; 26]; for i in 0..26 { e[i][i] = 1 }
let mul = |a: &[[u64; 26]; 26], b: &[[u64; 26]; 26]| {
let mut c = [[0u64; 26]; 26];
for i in 0..26 { for k in 0..26 { let v = a[i][k];
if v != 0 { for j in 0..26 { c[i][j] = (c[i][j] + v * b[k][j]) % M; }}
}}; c
};
while t > 0 { if t & 1 == 1 { e = mul(&e, &m) }; m = mul(&m, &m); t >>= 1 }
let mut r = 0u64; for i in 0..26 { for j in 0..26 { r = (r + f[i] * e[i][j]) % M }}
r as _
}
// 111ms
int lengthAfterTransformations(string s, int t, vector<int>& n) {
long long f[26] = {}, m[26][26] = {}, e[26][26] = {}, c[26][26], r = 0;
const long long M = 1000000007; for (auto b : s) f[b - 'a']++;
for (int i = 0; i < 26; i++) for (int j = 1; j <= n[i]; j++) m[i][(i + j) % 26] = 1;
for (int i = 0; i < 26; i++) e[i][i] = 1;
auto mul = [&](long long A[26][26], long long B[26][26]) {
memset(c, 0, sizeof c);
for (int i = 0; i < 26; i++) for (int k = 0; k < 26; k++) if (A[i][k])
for (int j = 0; j < 26; j++) c[i][j] = (c[i][j] + A[i][k] * B[k][j]) % M;
memcpy(A, c, sizeof c);
};
while (t) { if (t & 1) mul(e, m); mul(m, m); t >>= 1; }
for (int i = 0; i < 26; i++) for (int j = 0; j < 26; j++) r = (r + f[i] * e[i][j]) % M;
return r;
}
13.05.2025
3335. Total Characters in String After Transformations I medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/987
Problem TLDR
String length after t shifts c=c+1,z=ab #medium #dp
Intuition
My chain-of-thougths:
// a + 25 = z len = 1
// a + 26 = z + 1 = a + b len = 2
// b + 24 = z
// b + 25 = z + 1 = a + b len = 2
// ab + 25 = abz
// ab + 26 = bcab
// each char grows at its own rate
// naive dp - TLE
Each char has it’s own growth law that can be cached by remaining time.
Another intuition is from the hint: just simulate the process for chars frequencies.
Approach
- speed up by quick-jumping to
z - for simultaion we can jump to
ztoo, full 0..26 circle would produce a new char for each existing char
Complexity
-
Time complexity: \(O(t + s)\)
-
Space complexity: \(O(t)\) for dp, O(1) for the simulation
Code
// 420ms https://leetcode.com/problems/total-characters-in-string-after-transformations-i/submissions/1632533567
fun lengthAfterTransformations(s: String, t: Int): Int {
val M = 1000000007; val dp = HashMap<Pair<Char, Int>, Int>()
fun dfs(c: Char, t: Int): Int = if (t == 0) 1 else dp.getOrPut(c to t) {
if (c == 'z') (dfs('a', t - 1) + dfs('b', t - 1)) % M
else if (t >= 'z' - c) dfs('z', t - ('z' - c)) else dfs(c + 1, t - 1)
}
var res = 0; for (c in s) res = (res + dfs(c, t)) % M
return res
}
// 57ms
fun lengthAfterTransformations(s: String, t: Int): Int {
val M = 1000000007; val dp = Array(26) { IntArray(t + 1) { -1 }}
fun dfs(c: Int, t: Int): Int = if (t == 0) 1 else
if (dp[c][t] >= 0) dp[c][t] else
(if (c == 25) (dfs(0, t - 1) + dfs(1, t - 1)) % M
else if (t >= 25 - c) dfs(25, t - (25 - c)) else dfs(c + 1, t - 1))
.also { dp[c][t] = it }
var res = 0; for (c in s) res = (res + dfs(c - 'a', t)) % M
return res
}
// 28ms
fun lengthAfterTransformations(s: String, t: Int): Int {
var f = IntArray(26); for (c in s) ++f[c - 'a']
var f2 = IntArray(26); val M = 1000000007; var res = 0
for (i in 1..t) {
f2[0] = f[25]; for (c in 0..24) f2[c + 1] = f[c]
f2[1] = (f2[1] + f[25]) % M
f = f2.also { f2 = f }
}
for (c in f) res = (res + c) % M
return res
}
// 11ms https://leetcode.com/problems/total-characters-in-string-after-transformations-i/submissions/1632555700
fun lengthAfterTransformations(s: String, t: Int): Int {
var f = IntArray(26); for (c in s) ++f[c - 'a']
val M = 1000000007; var res = 0
for (i in 1..t / 26) for (c in 0..25) {
val a = (26 - c) % 26; f[a] = (f[a] + f[25 - c]) % M
}
for (c in 0..<t % 26) {
val a = (26 - c) % 26; f[a] = (f[a] + f[25 - c]) % M
}
for (c in f) res = (res + c) % M
return res
}
// 0ms https://leetcode.com/problems/total-characters-in-string-after-transformations-i/submissions/1632553112
pub fn length_after_transformations(s: String, t: i32) -> i32 {
let (mut f, M) = ([0; 26], 1000000007);
for b in s.bytes() { f[(b - b'a') as usize] += 1 }
for i in 0..t / 26 { for c in 0..26 {
let a = (26 - c) % 26; f[a] = (f[a] + f[25 - c]) % M
}}
for c in 0..t as usize % 26 {
let a = (26 - c) % 26; f[a] = (f[a] + f[25 - c]) % M
}
f.iter().fold(0, |r, c| (r + c) % M)
}
// 6ms https://leetcode.com/problems/total-characters-in-string-after-transformations-i/submissions/1632563226
int lengthAfterTransformations(string s, int t) {
int f[26]={}, r = 0, M = 1e9+7; for (char c: s) ++f[c - 'a'];
for (int i = 0; i < t / 26; ++i) for (int c = 0; c < 26; ++c) {
int a = (26 - c) % 26; f[a] = (f[a] + f[25 - c]) % M;
}
for (int c = 0; c < t % 26; ++c) {
int a = (26 - c) % 26; f[a] = (f[a] + f[25 - c]) % M;
}
for (int c: f) r = (r + c) % M; return r;
}
12.05.2025
2094. Finding 3-Digit Even Numbers easy
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/986
Problem TLDR
Triple digit even numbers from digits #easy #backtrack
Intuition
This problem is not easy if you didn’t spot the problem size of 1000 possible number total.
The backtracking works and is the fastest: pick a digit one-by-one, increase counter, compare with frequency, decrease back after.
Approach
- 3-loop solution is also possible (but 2ms vs 1ms of backtracking in Kotlin, which is unexplainable to me rn)
Complexity
-
Time complexity: \(O(range)\) or O(9^3) for backtracking DFS: depth is 3, 9 digits each
-
Space complexity: \(O(answer)\)
Code
// 41ms
fun findEvenNumbers(digits: IntArray) =
(100..999 step 2).filter { n ->
"$n".groupBy { it }.all { (k, v) -> v.size <= digits.count { it == k - '0' }}
}
// 2ms
fun findEvenNumbers(digits: IntArray): IntArray {
val f = IntArray(10); for (d in digits) ++f[d]
val r = IntArray(450); var i = 0
for (a in 1..9) if (f[a] > 0) {
f[a]--
for (b in 0..9) if (f[b] > 0) {
f[b]--
for (c in 0..9 step 2) if (f[c] > 0) r[i++] = a * 100 + b * 10 + c
f[b]++
}
f[a]++
}
return r.copyOf(i)
}
// 1ms https://leetcode.com/problems/finding-3-digit-even-numbers/submissions/1631643083
fun findEvenNumbers(digits: IntArray): List<Int> {
val f = IntArray(10); for (d in digits) ++f[d]
val res = ArrayList<Int>(); val taken = IntArray(10)
fun dfs(soFar: Int, start: Int) {
if (soFar > 99) {
if (soFar % 2 == 0) res += soFar
} else for (d in start..9) if (taken[d] < f[d]) {
taken[d]++; dfs(soFar * 10 + d, 0); taken[d]--
}
}
dfs(0, 1)
return res
}
// 0ms
pub fn find_even_numbers(digits: Vec<i32>) -> Vec<i32> {
let (mut f, mut r) = ([0; 10], vec![]);
for d in digits { f[d as usize] += 1}
for a in 1..10 { if f[a] > 0 { f[a] -= 1;
for b in 0..10 { if f[b] > 0 { f[b] -= 1;
for c in (0..10).step_by(2) { if f[c] > 0 {
r.push((a * 100 + b * 10 + c) as i32 )}}
f[b] += 1 }}
f[a] += 1 }}; r
}
// 0ms
vector<int> findEvenNumbers(vector<int>& digits) {
int f[10]={}; vector<int> r; for (int& d: digits) ++f[d];
for (int x = 100; x < 1000; x += 2) {
int c[10]={}, g = 1, d = x; while (d) g &= ++c[d % 10] <= f[d % 10], d /= 10;
if (g) r.push_back(x);
}; return r;
}
11.05.2025
1550. Three Consecutive Odds easy
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/985
Problem TLDR
3 odds #easy #bitmask
Intuition
Count odds.
Approach
- use bit
& 1to check for odds - use bitmask
0b111 = 7to check for 3 odds
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
```kotlin []
// 22ms fun threeConsecutiveOdds(a: IntArray) = “1, 1, 1” in “” + a.map { it % 2 }
```kotlin
// 21ms
fun threeConsecutiveOdds(a: IntArray) =
a.asList().windowed(3).any { it.all { it % 2 > 0 }}
// 23ms
fun threeConsecutiveOdds(a: IntArray) =
a.asList().windowed(3).any { it.reduce(Int::and) % 2 > 0 }
// 4ms
fun threeConsecutiveOdds(a: IntArray) = (1..<a.size - 1)
.any { a[it - 1] and a[it] and a[it + 1] % 2 > 0 }
// 0ms https://leetcode.com/problems/three-consecutive-odds/submissions/1630809266
fun threeConsecutiveOdds(a: IntArray): Boolean {
var c = 0
return a.any { c = (it % 2) * (c + 1); c > 2 }
}
// 0ms
fun threeConsecutiveOdds(a: IntArray): Boolean {
var c = 0
return a.any { c = it and 1 or (c shl 1) and 7; c > 6 }
}
// 0ms https://leetcode.com/problems/three-consecutive-odds/submissions/1630796680
pub fn three_consecutive_odds(a: Vec<i32>) -> bool {
a[..].windows(3).any(|w| 0 < 1 & w[0] & w[1] & w[2])
}
// 0ms
bool threeConsecutiveOdds(vector<int>& a) {
for(int c = 0; int &x: a) if ((c = x & 1 | (c << 1) & 7) > 6)
return 1; return 0;
}
10.05.2025
2918. Minimum Equal Sum of Two Arrays After Replacing Zeros medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/984
Problem TLDR
Min equal array sum, fill zeros #medium
Intuition
Any zero place can act as any number. Compare minimum sums by filling zeros with ones, then equalize.
Approach
- the interesting golf is how to make it CPU-branchless:
if (x == 0) 1 else 0can be written as((x | -x) >> 31) + 1wherex | -xwould will everything but a sign bit, transforming into -1 for any non-zero value
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
| Kotlin | Rust | C++ |
|---|---|---|
![]() |
![]() |
![]() |
// 523ms
fun minSum(n1: IntArray, n2: IntArray): Long {
val s1 = n1.sumOf { 1L * max(1, it) }; val s2 = n2.sumOf { 1L * max(1, it) }
return if (s1 < s2 && 0 !in n1 || s1 > s2 && 0 !in n2) -1 else max(s1, s2)
}
// 411ms https://leetcode.com/problems/minimum-equal-sum-of-two-arrays-after-replacing-zeros/submissions/1630261946
fun minSum(nums1: IntArray, nums2: IntArray): Long {
var s1 = 0L; var s2 = 0L; var z1 = 0; var z2 = 0
for (x in nums1) { s1 += x + ((x or -x).ushr(31) xor 1); z1 = z1 or ((x or -x).ushr(31) xor 1) }
for (x in nums2) { s2 += x + ((x or -x).ushr(31) xor 1); z2 = z2 or ((x or -x).ushr(31) xor 1) }
return if (s1 < s2 && z1 < 1 || s1 > s2 && z2 < 1) -1 else max(s1, s2)
}
// 8ms https://leetcode.com/problems/minimum-equal-sum-of-two-arrays-after-replacing-zeros/submissions/1630002606
pub fn min_sum(n1: Vec<i32>, n2: Vec<i32>) -> i64 {
let s1: i64 = n1.iter().map(|&n| n.max(1) as i64).sum();
let s2: i64 = n2.iter().map(|&n| n.max(1) as i64).sum();
let z1 = n1.contains(&0); let z2 = n2.contains(&0);
if (s1 < s2 && !z1) || (s1 > s2 && !z2) { -1 } else { s1.max(s2) }
}
// 43ms https://leetcode.com/problems/minimum-equal-sum-of-two-arrays-after-replacing-zeros/submissions/1630272912
long long minSum(vector<int>& n1, vector<int>& n2) {
long long s1 = size(n1), s2 = size(n2); int z1 = s1, z2 = s2;
for (int& n: n1) s1 += n + ((n|-n)>>31), z1 += (n|-n)>>31;
for (int& n: n2) s2 += n + ((n|-n)>>31), z2 += (n|-n)>>31;
return s1 < s2 && !z1 || s1 > s2 && !z2 ? -1 : max(s1, s2);
}
09.05.2025
3343. Count Number of Balanced Permutations hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/983
Problem TLDR
Permutations of even-odd position sums equal #hard #dp #math
Intuition
Didn’t solved. Chain-of-thoughts (mostly irrelevant):
// 80^80 (will TLE)
// digits are uniq
// partition into 2 buckets size/2
// 123 12 3
// 12342 132 42
// i.i.i
// let's brute force first
// permutation: can take next any
// we only have 10 digits: 0,1,2,3,4,5,6,7,8,9
// we can count them first
// every even frequency is good to split -- count must be equal
// every odd frequency should be brute-forced
// 18 minutes
// we can calc a sum, then search for a bag of digits to match sum / 2
// 28 minutes
// 44 minutes, idea of bugs is not working for 112, a = 2, b = 11
// the problem with duplicates "11" - not considered a permutation
// 55 minutes, idea to keep both halves in bags
// 60 minutes: wrong answer for 53374 4 instead of 6
// looking for hints:
// freq (known)
// dp (somewhat known)
// useless?
// 1:15 look for solution
Working solution:
- for every digit
i = 9..0 - take up to
j = frequency[i]numbers on the one half - another half would contain
frequency[i] - jautomatically - sum would change by
i * jdigit times how many we take - search for the final condition
Now the interesting part - combinatorics. How many permutations we have?
- we take
xdigits and place it at odd positions - that isCombinations(x, o) - and another half
Combinations(frequency[i] - x, e)
How to count combinations C(a, b)?
- precompute
C[A][B]like this:i in 0..a, j in 1..i, c[i][j] = c[i - 1][j] + c[i - 1][j - 1](just remember, but better to gain an intuition why it is: permutation is c[i] += c[i - 1], Pascal triangle is computing over previos row, and why it is relevant https://www.perplexity.ai/search/why-combinations-c-i-j-c-i-j-1-5fkL_k8BRXmllKs_FieusA)
Approach
- gave up after 1hr
- whats missing: combinatorics intuition
Complexity
-
Time complexity: \(O(n^3)\)
-
Space complexity: \(O(n^3)\)
Code
fun countBalancedPermutations(s: String): Int {
var sum = 0; val f = IntArray(10); for (x in s) { ++f[x - '0']; sum += x - '0' }
val c = Array(81) { LongArray(81)}; val M = 1000000007L
for (i in s.indices) { c[i][0] = 1; for (j in 1..i) c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % M }
data class K(val i: Int, val odd: Int, val balance: Int); val dp = HashMap<K, Long>()
fun dfs(i: Int, o: Int, e: Int, b: Int): Long = if (o == 0 && e == 0 && b == 0) 1L
else if (i < 0 || o < 0 || e < 0 || b < 0) 0L else dp.getOrPut(K(i, o, b)) {
var res = 0L; for (j in 0..f[i]) res +=
(((c[o][j] * c[e][f[i] - j]) % M) * dfs(i - 1, o - j, e - f[i] + j, b - i * j)) % M
res % M
}
return if (sum % 2 > 0) 0 else dfs(9, (1 + s.length) / 2, s.length / 2, sum / 2).toInt()
}
pub fn count_balanced_permutations(s: String) -> i32 {
let (mut sum, mut f, mut c, M) = (0, [0; 10], [[0; 81]; 81], 1000000007);
for b in s.bytes() { f[(b - b'0') as usize] += 1; sum += (b - b'0') as i64 }
if sum & 1 > 0 { return 0 }; let mut dp = [[[-1; 81]; 81]; 361];
for i in 0..81 { c[i][0] = 1; for j in 1..=i { c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % M }}
fn dfs(i: i64, o: i64, e: i64, b: i64, c: &[[i64; 81]; 81], dp: &mut [[[i64; 81]; 81]; 361], f: &[i64; 10]) -> i64 {
if o == 0 && e == 0 && b == 0 { return 1 } else if i.min(o).min(e).min(b) < 0 { return 0 }
if dp[b as usize][i as usize][o as usize] >= 0 { return dp[b as usize][i as usize][o as usize] };
let (mut r, M) = (0, 1000000007);
for j in 0..=f[i as usize] {
let k = f[i as usize] - j; let comb = (c[o as usize][j as usize] * c[e as usize][k as usize]) % M;
let next = dfs(i - 1, o - j, e - k, b - i * j, c, dp, f);
r = (r + (comb * next) % M) % M
}
dp[b as usize][i as usize][o as usize] = r; r
} dfs(9, (1 + s.len() as i64) / 2, s.len() as i64 / 2, sum / 2, &c, &mut dp, &f) as _
}
int countBalancedPermutations(string s) {
int sum = 0, f[10]={}, c[81][81]={}, dp[81][81][361]={}, M = 1e9+7;
for(auto c: s) { ++f[c - '0']; sum += c - '0'; }; if (sum & 1 > 0) return 0;
for (int i = 0; i < 81; ++i)
{ c[i][0] = 1; for (int j = 1; j <= i; ++j) c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % M; }
auto d = [&](this const auto& d, int i, int o, int e, int b) -> int {
if (o == 0 && e == 0 && b == 0) return 1; if (i < 0 || o < 0 || e < 0 || b < 0) return 0;
if (dp[i][o][b]) return dp[i][o][b] - 1;
int r = 0;
for (int j = 0; j <= f[i]; ++j) {
int k = f[i] - j; int comb = (1LL * c[o][j] * c[e][k]) % M;
int next = d(i - 1, o - j, e - k, b - i * j);
r = (1LL * r + (1LL * comb * next) % M) % M;
}
dp[i][o][b] = r + 1; return r;
};
return d(9, (1 + size(s)) / 2, size(s) / 2, sum / 2);
}
08.05.2025
3342. Find Minimum Time to Reach Last Room II medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/982
Problem TLDR
Fastest travel in graph, alternating dt=1,2 #medium #bfs
Intuition
The naive Dijkstra without heap would give TLE. With heap it is accepted.
Approach
Some optimizations implementation details
- return result as fast as possible
- no need to store the best time and compare it if heap is already picks the best
- mark visited by mutating the graph (not production code, time golf)
Complexity
-
Time complexity: \(O(V + ElogV)\)
-
Space complexity: \(O(V)\)
Code
// 47ms https://leetcode.com/problems/find-minimum-time-to-reach-last-room-ii/submissions/1628359473
fun minTimeToReach(g: Array<IntArray>): Int {
val w = g[0].size - 1; val h = g.size - 1
val q = PriorityQueue<IntArray>(compareBy { it[0] })
val d = intArrayOf(0, 1, 0, -1, 0); q += intArrayOf(0, 0, 0, 1)
while (q.size > 0) {
val (t, x, y, dt) = q.poll()
for (i in 0..3) {
val y = y + d[i]; val x = x + d[i + 1]
if (x !in 0..w || y !in 0..h || g[y][x] < 0) continue
val t = dt + max(t, g[y][x]); if (x == w && y == h) return t
g[y][x] = -1; q += intArrayOf(t, x, y, 3 - dt)
}
}
return 0
}
// 11ms https://leetcode.com/problems/find-minimum-time-to-reach-last-room-ii/submissions/1628358131
pub fn min_time_to_reach(mut g: Vec<Vec<i32>>) -> i32 {
let (mut w, mut h) = (g[0].len() - 1, g.len() - 1);
let (mut d, mut q) = ([0, 1, 0, -1, 0], BinaryHeap::from([(0, 0, 0, 1)]));
while let Some((t, x, y, dt)) = q.pop() {
for i in 0..4 {
let y = (y as i32 + d[i]) as usize; let x = (x as i32 + d[i + 1]) as usize;
if x > w || y > h || g[y][x] < 0 { continue }
let t = dt + (-t).max(g[y][x]); if x == w && y == h { return t }
g[y][x] = -1; q.push((-t, x, y, 3 - dt))
}
} 0
}
// 0ms https://leetcode.com/problems/find-minimum-time-to-reach-last-room-ii/submissions/1628349530
int minTimeToReach(vector<vector<int>>& g) {
priority_queue<tuple<int, int, int, int>, vector<tuple<int, int, int, int>>, greater<>> q;
q.emplace(0, 0, 0, 1); int h = size(g) - 1, w = size(g[0]) - 1, d[] = {0, 1, 0, -1, 0};
while (size(q)) {
auto [t1, x1, y1, dt] = q.top(); q.pop();
for (int i = 0; i < 4; ++i) {
int x = x1 + d[i]; int y = y1 + d[i + 1];
if (min(x, y) < 0 || x > w || y > h || g[y][x] < 0) continue;
int t = dt + max(t1, g[y][x]); if (x == w && y == h) return t;
g[y][x] = -1; q.emplace(t, x, y, 3 - dt);
}
} return 0;
}
07.05.2025
3341. Find Minimum Time to Reach Last Room I medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/981
Problem TLDR
Fastest path in graph #medium #bfs
Intuition
Use BFS, track time.
Approach
- use time-improvement condition, or a Heap (heap is faster)
Complexity
-
Time complexity: \(O(V^2)\), or (E + V)logV for heap
-
Space complexity: \(O(V)\)
Code
// 184ms
fun minTimeToReach(moveTime: Array<IntArray>): Int {
val w = moveTime[0].size; val time = IntArray(moveTime.size * w) { Int.MAX_VALUE }
val q = ArrayDeque<Int>(); q += 0; time[0] = 0; val dxy = intArrayOf(-1, 1, -w, w)
while (q.size > 0) {
val xy = q.removeFirst(); val x1 = xy % w; val y1 = xy / w; val t = time[xy]
for (d in dxy) {
val xy2 = xy + d; val y2 = xy2 / w; val x2 = xy2 % w
if (xy2 in 0..<time.size && (y1 == y2 || x1 == x2)) {
val t2 = 1 + max(t, moveTime[y2][x2])
if (t2 < time[xy2]) { time[xy2] = t2; q += xy2 }
}
}
}
return time.last()
}
// 163ms https://leetcode.com/problems/find-minimum-time-to-reach-last-room-i/submissions/1627622531
fun minTimeToReach(moveTime: Array<IntArray>): Int {
val w = moveTime[0].size; val n = w * moveTime.size - 1
val q = PriorityQueue<IntArray>(compareBy { it[1] })
q += intArrayOf(0, 0); val dxy = intArrayOf(-1, 1, -w, w)
while (q.size > 0) {
val (xy, t) = q.poll(); val x1 = xy % w; val y1 = xy / w
if (xy == n) return t
for (d in dxy) {
val xy2 = xy + d; val y2 = xy2 / w; val x2 = xy2 % w
if (xy2 in 0..n && (y1 == y2 || x1 == x2) && moveTime[y2][x2] >= 0) {
q += intArrayOf(xy2, (1 + max(t, moveTime[y2][x2])))
moveTime[y2][x2] = -1
}
}
}
return -1
}
// 0ms https://leetcode.com/problems/find-minimum-time-to-reach-last-room-i/submissions/1627635883
pub fn min_time_to_reach(mut move_time: Vec<Vec<i32>>) -> i32 {
let mut w = move_time[0].len(); let n = w * move_time.len() - 1;
let mut q = BinaryHeap::from([(0, 0)]);
let dxy = [-1, 1, -(w as i32), w as i32];
while let Some((t, xy)) = q.pop() {
let (x1, y1) = (xy % w, xy / w);
if xy == n { return -t }
for d in dxy {
let xy2 = (xy as i32 + d) as usize; let (y2, x2) = (xy2 / w, xy2 % w);
if xy2 <= n && (y1 == y2 || x1 == x2) && move_time[y2][x2] >= 0 {
q.push((-1 + t.min(-move_time[y2][x2]), xy2));
move_time[y2][x2] = -1
}
}
} 0
}
// 0ms https://leetcode.com/problems/find-minimum-time-to-reach-last-room-i/submissions/1627644831
int minTimeToReach(vector<vector<int>>& g) {
int h = size(g), w = size(g[0]), n = h * w - 1;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> q;
int dir[4] = {-1, 1, -w, w}; q.push({0, 0});
while (size(q)) {
auto [t, u] = q.top(); q.pop(); if (u == n) return t;
for (int i = 0; i < 4; ++i) {
int v = u + dir[i];
if (v >= 0 && v <= n && (u / w == v / w || u % w == v % w) && g[v / w][v % w] >= 0)
q.push({max(t, g[v / w][v % w]) + 1, v}), g[v / w][v % w] = -1;
}
} return 0;
}
06.05.2025
1920. Build Array from Permutation easy
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/980
Problem TLDR
n[n[i]] #easy
Intuition
The follow up is more tricky: we have to store the result and preserver the initial values somehow, shift bits or do * and % operations.
Approach
- do golf
- do follow-up
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\) or O(1)
Code
// 3ms
fun buildArray(n: IntArray) = n.map { n[it] }
// 2ms
fun buildArray(n: IntArray): IntArray {
for (i in n.indices) n[i] += (n[n[i]] and 0xFFFF) shl 16
for (i in n.indices) n[i] = n[i] shr 16
return n;
}
// 1ms
fun buildArray(n: IntArray) = IntArray(n.size) { n[n[i]] }
// 0ms
pub fn build_array(mut n: Vec<i32>) -> Vec<i32> {
for i in 0..n.len() { n[i] |= (n[n[i] as usize] & 0xFFFF) << 16 }
for i in 0..n.len() { n[i] >>= 16 } n
}
// 0ms
pub fn build_array(n: Vec<i32>) -> Vec<i32> {
n.iter().map(|&x| n[x as usize]).collect()
}
// 0ms
vector<int> buildArray(vector<int>& n) {
vector<int> r(size(n));
for (int i = 0; auto& x: n) r[i++] = n[x];
return r;
}
05.05.2025
790. Domino and Tromino Tiling meidum
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/979
Problem TLDR
Ways to fill 2xn board with I,L shapes #medium #dp
Intuition
Let’s full-search by trying every possible way of placing every domino shape at current position i with Depth-First Search. If the final column is filled, count this way as 1. Result only depends on the current position i and the column filled condition of 00 as empty, 01 as bottom filled and 10 as top filled. Can be cached.
Another fun way to optimize the solution is to look at the pattern of the results:
1
1
2
5
11 5 * 2 + 1
24 11 * 2 + 2
53 24 * 2 + 5
117 53 * 2 + 11
258
569
1255
2768
Approach
- for dp we can either go
i+2or introduce another filled state11 - there is also an O(log(n)) solution by doing matrix^n
// [ a_n ] [ 2 0 1 ] [ a_{n-1} ]
// [a_{n-1}] = [ 1 0 0 ] [ a_{n-2} ]
// [a_{n-2}] [ 0 1 0 ] [ a_{n-3} ]
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\), or O(1) for the arithmetic solution
Code
// 6ms
fun numTilings(n: Int): Int {
val M = 1_000_000_007; val dp = HashMap<Pair<Int, Int>, Int>()
fun dfs(i: Int, tb: Int): Int = if (i > n) 0 else if (i == n)
{ if (tb == 0) 1 else 0 } else dp.getOrPut(i to tb) {
val vertical = if (tb > 0) 0 else dfs(i + 1, 0b00)
val horizontal = dfs(i + 2, 0b00)
val trtop = if (tb == 0b10) 0 else dfs(i + 1, 0b10)
val trbot = if (tb == 0b01) 0 else dfs(i + 1, 0b01)
(((vertical + horizontal) % M + trtop) % M + trbot) % M
}
return dfs(0, 0)
}
// 0ms
fun numTilings(n: Int): Int {
var a = 1; var b = 1; var c = 2; val m = 1000000007
for (i in 3..n) { val t = a; a = b; b = c; c = ((2 * b) % m + t) % m }
return if (n < 2) 1 else if (n < 3) 2 else c
}
// 0ms
pub fn num_tilings(n: i32) -> i32 {
let (mut a, mut b, mut c, m) = (1, 1, 2, 1000000007);
for i in 3..=n { (a, b, c) = (b, c, ((2 * c) % m + a) % m) }
if n < 2 { 1 } else if n < 3 { 2 } else { c }
}
// 0ms
int numTilings(int n) {
int c = 2;
for (int i = 3, t, a = 1, b = 1, m = 1e9+7; i <= n; ++i)
t = a, a = b, b = c, c = ((2 * b) % m + t) % m;
return n < 2 ? 1 : n < 3 ? 2 : c;
}
04.05.2025
1128. Number of Equivalent Domino Pairs easy
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/978
Problem TLDR
Dominoes pairs #easy #hash
Intuition
The brute-force O(n^2) is accepted. More optimal O(n) is the counting pattern: count visited pairs, each new will pair with previous count.
Approach
- we can try to CPU-branching optimize by using a symmetric cache key
a * b + 10 * (a + b) - otherwise, space-optimizations are possible too: we have a symmetric matrix of 9x9 and a total of 45 uniq keys
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 4ms
fun numEquivDominoPairs(ds: Array<IntArray>): Int {
val m = Array(10) { IntArray(10) }
return ds.sumOf { (a, b) -> m[min(a, b)][max(a, b)]++ }
}
// 2ms https://leetcode.com/problems/number-of-equivalent-domino-pairs/submissions/1625039917
fun numEquivDominoPairs(ds: Array<IntArray>): Int {
val m = IntArray(262); var c = 0
for ((a, b) in ds) c += m[a * b + 10 * (a + b)]++
return c
}
// 0ms
pub fn num_equiv_domino_pairs(ds: Vec<Vec<i32>>) -> i32 {
let mut m = [0; 100];
ds.iter().map(|d| {
let k = (d[0].min(d[1]) * 10 + d[0].max(d[1])) as usize;
let c = m[k]; m[k] += 1; c
}).sum()
}
// 0ms
int numEquivDominoPairs(vector<vector<int>>& ds) {
int m[100], c = 0;
for (auto& d: ds) c += m[min(d[0], d[1]) * 10 + max(d[0], d[1])]++;
return c;
}
03.05.2025
1007. Minimum Domino Rotations For Equal Row medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/977
Problem TLDR
Min swaps to make a top or bottom row #medium
Intuition
It’s all about the implementation and edge cases. Consider counting the frequencies for the top and for the bottom row. Then detect a dominant value. Then check it can fill the row.
Approach
- first domino contains a dominant value
- consider both values as possible dominant
- we can use a recursion, or a single iteration with four counters (can be less?)
- in jvm test machine two passes are faster than a single pass, possible beacuse of the instructions prediction or cache can’t handle too many variables at once
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 19ms
fun minDominoRotations(tops: IntArray, bottoms: IntArray, d: Int = 0): Int =
if (d < 1) {
val a = minDominoRotations(tops, bottoms, tops[0])
if (a < 0) minDominoRotations(tops, bottoms, bottoms[0]) else a
} else if (tops.indices.any { tops[it] != d && bottoms[it] != d }) -1
else tops.size - max(tops.count { it == d }, bottoms.count { it == d })
// 6ms
fun minDominoRotations(top: IntArray, bottom: IntArray): Int {
var d1 = top[0]; var d2 = bottom[0]
var a = top.size; var b = a; var c = a; var d = a
for (i in 0..<a) {
val tp = top[i]; val bt = bottom[i]
if (tp != d1 && bt != d1) if (d2 == 0) return -1 else d1 = 0
if (tp != d2 && bt != d2) if (d1 == 0) return -1 else d2 = 0
if (tp == d1) --a else if (tp == d2) --b
if (bt == d1) --c else if (bt == d2) --d
}
return min(min(a, b), min(c, d))
}
// 4ms
fun minDominoRotations(top: IntArray, bottom: IntArray): Int {
var d = top[0]; var a = 0; var b = 0
for (i in top.indices) {
if (top[i] != d && bottom[i] != d) { a = -1; b = -1; break }
if (top[i] == d) ++a; if (bottom[i] == d) ++b
}
var r = max(a, b); if (r >= 0) return top.size - r
d = bottom[0]; a = 0; b = 0
for (i in top.indices) {
if (top[i] != d && bottom[i] != d) { a = -1; b = -1; break }
if (top[i] == d) ++a; if (bottom[i] == d) ++b
}
r = max(a, b)
return if (r < 0) -1 else top.size - r
}
// 0ms
pub fn min_domino_rotations(tops: Vec<i32>, bottoms: Vec<i32>) -> i32 {
let (mut d1, mut d2, mut a) = (tops[0], bottoms[0], tops.len());
let (mut b, mut c, mut d) = (a, a, a);
for i in 0..a {
let (tp, bt) = (tops[i], bottoms[i]);
if tp != d1 && bt != d1 { if d2 < 1 { return -1 }; d1 = 0 }
if tp != d2 && bt != d2 { if d1 < 1 { return -1 }; d2 = 0 }
if tp == d1 { a -= 1 } else if tp == d2 { b -= 1 }
if bt == d1 { c -= 1 } else if bt == d2 { d -= 1 }
} a.min(b).min(c).min(d) as _
}
// 0ms
int minDominoRotations(vector<int>& tops, vector<int>& bottoms) {
int d1 = tops[0], d2 = bottoms[0], j = 0, a = size(tops);
int b = a, c = a, d = a;
for (int tp: tops) {
int bt = bottoms[j++];
if (tp != d1 && bt != d1) if (!d2) return -1; else d1 = 0;
if (tp != d2 && bt != d2) if (!d1) return -1; else d2 = 0;
a -= tp == d1; b -= tp == d2; c -= bt == d1; d -= bt == d2;
} return min(min(a, b), min(c, d));
}
02.05.2025
838. Push Dominoes medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/976
Problem TLDR
Dominoes simulation #medium
Intuition
My first idea was to use force balance, but I didn’t find the working algorigthm for that (it is possible to make it work, but force should be decreasing from n)
// 0123456789
// .L.R...LR..L..
// 00012340123000 to the right
// 21004321032100 to the left
// 1?02 1?
// LL.RR.LLRR
// 21 20?1 1
The more simple approach is to notice how ..L, R.., L..R and R..L ranges are behaving. Then it is all about the implementation details.
Approach
- the golfed code here is completely obfuscates the logic: consider only
Land backtrack to the half ofRrange or full otherwise.
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\) or O(1)
Code
// 30ms
fun pushDominoes(d: String) = buildString {
var r = false; var l = 1
for ((i, c) in d.withIndex())
if (c == '.') { append(if (r) 'R' else c); ++l } else { append(c)
if (c == 'L') for (j in (if (r) i - l / 2 else i - l + 1)..<i) set(j, c)
if (c == 'L' && r && l % 2 < 1) set(i - l / 2, '.')
r = c == 'R'; l = 1
}
}
// 10ms
fun pushDominoes(dominoes: String): String {
val r = dominoes.toCharArray(); var isR = false; var l = 1
for ((i, c) in r.withIndex())
if (c == '.') { if (isR) r[i] = 'R'; ++l } else {
if (c == 'L') for (j in (if (isR) i - l / 2 else i - l + 1)..<i) r[j] = 'L'
if (c == 'L' && isR && l % 2 < 1) r[i - l / 2] = '.'
isR = c == 'R'; l = 1
}
return String(r)
}
// 1ms
pub fn push_dominoes(mut d: String) -> String {
unsafe { let (mut r, mut l, mut b) = (false, 1, d.as_bytes_mut());
for i in 0..b.len() {
if b[i] == b'.' { if r { b[i] = b'R'}; l += 1 } else {
if b[i] == b'L' { b[if r { i - l / 2 } else { i - l + 1 }..i].fill(b'L') }
if b[i] == b'L' && r && l % 2 < 1 { b[i - l / 2] = b'.' }
r = b[i] == b'R'; l = 1
}}} d
}
// 0ms
string pushDominoes(string d) {
for (int i = 0, n = size(d), l = 1, r = 0; i < n; ++i)
if (d[i] == '.') { if (r) d[i] = 'R'; ++l; } else {
if (d[i] == 'L') fill(begin(d) + (r ? i - l/2 : i - l + 1), begin(d) + i, 'L');
if (d[i] == 'L' && r && l % 2 < 1) d[i - l/2] = '.';
r = d[i] == 'R'; l = 1;
}
return d;
}
01.05.2025
2071. Maximum Number of Tasks You Can Assign hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/975
Problem TLDR
Tasks can be done by workers with pills #hard #binary_search
Intuition
Didn’t solve myself.
Thought process:
// 5 9 8 5 9 5 5 8 9 9 p=1 s=5
// 1 6 4 2 6 1 2 4 6 6
// 5 5 8 9 9
// * 1+5 p=0 not optimal
// * 6
// -
// maybe start with whats already fits?
// or just DP by (i,j,pills) - n^3
//
// idea: real pointer + heap of skipped enchanced values (optimal?)-not optimal
// idea: all in heap, real + enchanced, use greedy (not optimal)
// hint: first smallest k to the workers
// use binary search
// but how to assign k smallest to all workers?
// 5 5 8 9 9 - tasks 1 2 4 6 6 - workers p=1 s=5
// . . k, all must fit - key idea
// still, how to optimally give the pills?
// 5 5 8 1 2 3 4 5 6 p=1 s=5 can assign all tasks to workers?
// start with biggest
// 8 assign it to smallest+pill
The hint: the is a greedy way to check if x workers can or can not do x tasks.
Now, after the hint I was able to discover the working greedy algorithm:
- start with the biggest task and worker
- if it works - it works
- if it not, don’t give the pill to that worker, instead, find the weakest worker that will do that with pill
Another weak point of mine was: how to actually implement this search for the weakest worker? Do we have to track the used workers somehow? Is the solution becomes O(workers^2)
Thats where I gave up and looked for the answer:
- put all the workers in a queue by their
pill potential - if task is doable - take from the front of the queue (meaning the strongest worker)
- if its not - consume the pill and the weakest worker (back of the
pill potential queue)
Approach
- some greedy ideas are not working, we have to try different examples
- the
implementationcan be the hardest part even if you know the algorithm - 1 hr - brain can’t give its full power after this line (for me)
Complexity
-
Time complexity: \(O(nlog(n))\)
-
Space complexity: \(O(n)\)
Code
// 180ms
fun maxTaskAssign(t: IntArray, ws: IntArray, pills: Int, s: Int): Int {
t.sort(); ws.sort(); var lo = 0; var hi = t.lastIndex; var res = -1
while (lo <= hi) {
val m = (lo + hi) / 2
var j = ws.lastIndex; var p = pills; var good = true; val q = ArrayDeque<Int>()
for (i in m downTo 0) {
while (j >= 0 && j >= ws.lastIndex - m && ws[j] + s >= t[i]) q += ws[j--]
if (q.size < 1) { good = false; break }
if (q.first() >= t[i]) q.removeFirst() else if (--p < 0) { good = false; break } else q.removeLast()
}
if (good) { res = max(res, m); lo = m + 1 } else hi = m - 1
}
return res + 1
}
// 15ms
pub fn max_task_assign(mut t: Vec<i32>, mut ws: Vec<i32>, pills: i32, s: i32) -> i32 {
t.sort_unstable(); ws.sort_unstable(); let (mut lo, mut hi, mut r) = (0, t.len() as i32 - 1, -1);
while lo <= hi {
let m = (lo + hi) as usize / 2;
let (mut j, mut p, mut good, mut q) = (ws.len() - 1, pills, true, VecDeque::new());
for i in (0..=m).rev() {
while j < ws.len() && j >= ws.len() - m - 1 && ws[j] + s >= t[i] { q.push_back(ws[j]); j -= 1 }
if q.len() < 1 { good = false; break }
if *q.front().unwrap() >= t[i] { q.pop_front(); } else if p < 1 { good = false; break }
else { q.pop_back(); p -= 1 }
}
if good { r = r.max(m as i32); lo = m as i32 + 1 } else { hi = m as i32 - 1 }
}
r + 1
}
// 66ms
int maxTaskAssign(vector<int>& t, vector<int>& ws, int pills, int s) {
int l = 0, r = min(size(t), size(ws)); sort(begin(t), end(t)); sort(begin(ws), end(ws));
while (l < r) {
int m = (l + r + 1) / 2, p = pills, j = size(ws) - 1, g = 1; deque<int> q;
for (int i = m - 1; i >= 0 && g; --i) {
while (j >= 0 && j >= size(ws) - m && ws[j] + s >= t[i]) q.push_back(ws[j--]);
if (!size(q)) g = 0; else
if (q.front() >= t[i]) q.pop_front(); else if (--p < 0) g = 0; else q.pop_back();
}
if (g) l = m; else r = m - 1;
} return l;
}
30.04.2025
1295. Find Numbers with Even Number of Digits easy
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/974
Problem TLDR
Even length numbers #easy
Intuition
Do what is asked
Approach
- some golf and counter acrobatics possible
- how the input range can be used?
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 3ms
fun findNumbers(n: IntArray) =
n.count { "$it".length % 2 < 1 }
// 1ms
fun findNumbers(n: IntArray) = n
.count { it in 10..99 || it in 1000..9999 || it == 100000 }
// 0ms
pub fn find_numbers(n: Vec<i32>) -> i32 {
n.iter().map(|&x| { let (mut x, mut c) = (x, 1);
while x > 0 { x /= 10; c = 1 - c }; c
}).sum()
}
// 0ms
int findNumbers(vector<int>& n) {
int r = 0;
for (int c = 0; int x: n)
for (c = 1, r++; x > 0; x /= 10 ) r += 2 * (++c & 1) - 1;
return r;
}
29.04.2025
2962. Count Subarrays Where Max Element Appears at Least K Times medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/973
Problem TLDR
Subarrays at least k maxes #medium #two_pointers
Intuition
Two pointers pattern:
- always move the right
- move the left until condition
- count how many valid subarray starting positions are
// 1,3,2,3,3
// j i i
Approach
- we can compute
maxas we go - we can use a queue instead of the second pointer (slower runtime though)
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\), or O(n) or O(k) for the queue solution
Code
// 43ms
fun countSubarrays(n: IntArray, k: Int): Long {
var m = n.max(); val q = ArrayList<Int>()
return n.withIndex().sumOf { (i, x) ->
if (x == m) q += i
if (q.size >= k) 1L + q[q.size - k] else 0L
}
}
// 20ms
fun countSubarrays(n: IntArray, k: Int): Long {
var j = 0; var m = n.max(); var c = 0
return n.sumOf { x ->
if (x == m) ++c
while (c >= k) if (n[j++] == m) --c
1L * j
}
}
// 13ms
fun countSubarrays(n: IntArray, k: Int): Long {
var r = 0L; var m = 0; val q = ArrayList<Int>()
for (i in n.indices) {
if (n[i] > m) { r = 0; m = n[i]; q.clear(); q += i }
else if (n[i] == m) q += i
if (q.size >= k) r += q[q.size - k] + 1
}
return r
}
// 8ms
fun countSubarrays(n: IntArray, k: Int): Long {
var j = 0; var r = 0L; var m = 0; var c = 0
for (x in n) {
if (x > m) { r = 0; c = 1; j = 0; m = x } else if (x == m) ++c
while (c >= k) if (n[j++] == m) --c
r += j
}
return r
}
// 6ms
fun countSubarrays(n: IntArray, k: Int): Long {
var j = 0; var r = 0L; var m = 0; var c = 0
for ((i, x) in n.withIndex()) {
if (x > m) { r = 0; c = 1; j = i; m = x } else if (x == m) ++c
while (c > k || n[j] != m) if (n[j++] == m) --c
if (c == k) r += j + 1
}
return r
}
// 0ms
pub fn count_subarrays(n: Vec<i32>, k: i32) -> i64 {
let (mut j, mut r, mut m, mut c) = (0, 0, 0, 0);
for &x in &n {
if x > m { r = 0; c = 1; j = 0; m = x } else if x == m { c += 1 }
while c >= k { if n[j] == m { c -= 1 }; j += 1 }
r += j as i64
} r
}
// 0ms
long long countSubarrays(vector<int>& n, int k) {
int j = 0, m = 0, c = 0; long long r = 0;
for (int x: n) {
if (x > m) r = 0, c = 1, j = 0, m = x; else if (x == m) ++c;
while (c >= k) if (n[j++] == m) --c;
r += j;
} return r;
}
28.04.2025
2302. Count Subarrays With Score Less Than K hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/972
Problem TLDR
Subarrays sum * cnt <= k #hard #two_pointers
Intuition
This is a standart two-pointers pattern task: always move the right pointer, move the left util condition, count how many good subarray starting point are.
Approach
- you can use
i - j + 1or a separatecountvariable - careful with
intoverflow
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 28ms
fun countSubarrays(n: IntArray, k: Long): Long {
var s = 0L; var j = 0
return n.withIndex().sumOf { (i, x) ->
s += x; while (s * (i - j + 1) >= k) s -= n[j++]
1L + i - j
}
}
// 3ms
fun countSubarrays(n: IntArray, k: Long): Long {
var s = 0L; var r = 0L; var j = 0
for ((i, x) in n.withIndex()) {
s += x
while (s * (i - j + 1) >= k) s -= n[j++]
r += i - j + 1
}
return r
}
// 0ms
pub fn count_subarrays(n: Vec<i32>, k: i64) -> i64 {
let (mut s, mut j) = (0, 0);
n.iter().enumerate().map(|(i, &x)| {
s += x as i64;
while s * (i - j + 1) as i64 >= k { s -= n[j] as i64; j += 1 }
i - j + 1
}).sum::<usize>() as _
}
// 0ms
long long countSubarrays(vector<int>& n, long long k) {
long long s = 0, r = 0; int j = 0, c = 0;
for (int x: n) {
s += x; ++c;
while (c * s >= k) s -= n[j++], --c;
r += c;
} return r;
}
27.04.2025
3392. Count Subarrays of Length Three With a Condition easy
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/971
Problem TLDR
3-subarrays 2a + 2c == b #easy
Intuition
Constrains are small, even the brute-force solution is O(n)
Approach
- let’s golf it
- some CPU-cache friendliness possible
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 31ms
fun countSubarrays(n: IntArray) = n.asList()
.windowed(3).count { 2 * it.sum() == 3 * it[1] }
// 2ms
fun countSubarrays(n: IntArray): Int {
var c = 0; var l = 0; var m = -300
for (r in n) {
if (l + l + r + r == m) c++
l = m; m = r
}
return c
}
// 0ms
pub fn count_subarrays(n: Vec<i32>) -> i32 {
n[..].windows(3).filter(|w| 2 * w[0] + 2 * w[2] == w[1]).count() as _
}
// 0ms
int countSubarrays(vector<int>& n) {
int c = 0, l = 0, m = 300;
for (int r: n) c += l + l + r + r == m, l = m, m = r;
return c;
}
26.04.2025
2444. Count Subarrays With Fixed Bounds hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/970
Problem TLDR
Subarrays with min=minK, max=maxK #hard #two_pointers
Intuition
I’ve encounter this problem for a 3rd time (last https://leetcode.com/problems/count-subarrays-with-fixed-bounds/solutions/4951301/kotlin-rust/).
This time I felt pretty fluent with subarrays logic:
two pointers maintain the minimum valid window, and a third pointer s is a start position of the valid starting positions of possible subarrays s..j.
// 2 2 2 1 3 5 2 2 7 1 3 5 1..5
// j j i
// 1 3 5 2 7 5 1..5
// *minj
// *maxj
// j i
// not in *range* but *equal*
Approach
- attention: subarray should have exact min=minK and max=maxK
- there is some pointer acrobatics trick: instead of a
startposition, trackcount, increase it by pointers diff
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
// 38ms
fun countSubarrays(n: IntArray, minK: Int, maxK: Int): Long {
var a = -1; var b = -1; var s = -1
return n.withIndex().sumOf { (i, x) ->
if (x == minK) a = i; if (x == maxK) b = i
if (x < minK || x > maxK) { s = i; a = i; b = i }
1L * min(a, b) - s
}
}
// 6ms
fun countSubarrays(n: IntArray, minK: Int, maxK: Int): Long {
var a = -1; var b = -1; var c = 0; var r = 0L
for ((i, x) in n.withIndex())
if (x < minK || x > maxK) { a = i; b = i; c = 0 }
else {
if (x == minK) { if (a < b) c += b - a; a = i }
if (x == maxK) { if (b < a) c += a - b; b = i }
r += c
}
return r
}
// 0ms
pub fn count_subarrays(n: Vec<i32>, min_k: i32, max_k: i32) -> i64 {
let (mut a, mut b, mut c) = (-1, -1, 0);
n.into_iter().enumerate().map(|(i, x)| {
if x < min_k || x > max_k { a = i as i32; b = i as i32; c = 0 }
if x == min_k { if a < b { c += b - a }; a = i as i32 }
if x == max_k { if b < a { c += a - b }; b = i as i32 }
c as i64
}).sum()
}
// 0ms
long long countSubarrays(vector<int>& n, int minK, int maxK) {
int a = -1, b = -1, c = 0; long long r = 0;
for (int i = 0; i < size(n); ++i) {
if (n[i] < minK || n[i] > maxK) a = i, b = i, c = 0;
if (n[i] == minK) c += max(0, b - a), a = i;
if (n[i] == maxK) c += max(0, a - b), b = i;
r += c;
} return r;
}
25.04.2025
2845. Count of Interesting Subarrays medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/969
Problem TLDR
Subarrays, count a[i]%m=k is c%m=k #medium #hash_map
Intuition
Failed to solve.
Wrong two-pointers reasoning:
// 0 1 2 3
// 3 1 9 6 m=3 k=0
// 0,3,6,9... cnt indices
// * * * the interesting indices are known
// what possible patterns are
// ...***..., ....*....*....*..., .***.***, .***.***.***
// i..j
// i.....j
// window of 0, window of 3, window of 6,...
// what if k=1, m=3
// ..*..*..*.
// window of 1, window of 4, window of x*m+1
// how many windows possible?
// m = 1, k = 0, windows_count = n, so it is n^2 algo
// 012345678
// .***.***.***.***..
// .i j. j .j j. j ..
// i .j j. j .j j..
// i. j .j j.j j.. every j is a valid end
// it is (i+m-1)%m (* only)
// .***.***.***.***..
// i . . s=0 js=0
// j i . . s=0 js=1
// j i . . s=0 js=2
// * j i. . s=1 js=3
// * j i . s=1 js=4
// * * j i . s=2 js=5
// * * j i. s=2 js=6
// * * * * j i the number of prefix stars=4, number of js=7
// s=(js+1)/3 ?
// .
// \how to count this dot?
I’ve almost come to the conclusion of counting prefix good j’s. But do not understood how can I also count non-divisible dots.
Then I used the hints:
- if we are at
iand have goodcount[i] - then how many
goodstartingjs are?jis good if(count[i] - count[j]) % m == k. Number of good startingjs isfreq[count[j]]. - I have to be fluid with modulo arithmetics:
(a - b) % m == k,a%m - b%m == k,b%m == a%m - k,b%m == (a%m + m - k)%m(+m to make positive)
Approach
- zero case is
map[0] = 1 non-divisiblepositions are counted because we increaserby previous running sumcnt
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
fun countInterestingSubarrays(nums: List<Int>, m: Int, k: Int): Long {
var r = 0L; var cnt = 0; var map = HashMap<Int, Int>(); map[0] = 1
for (x in nums) {
cnt = (cnt + (if (x % m == k) 1 else 0)) % m
r += map[(cnt + m - k) % m] ?: 0
map[cnt] = 1 + (map[cnt] ?: 0)
}
return r
}
pub fn count_interesting_subarrays(n: Vec<i32>, m: i32, k: i32) -> i64 {
let (mut cnt, mut r, mut map) = (0, 0, HashMap::new()); map.insert(0, 1);
for x in n {
if x % m == k { cnt += 1}
r += map.get(&((cnt + m - k) % m)).unwrap_or(&0);
*map.entry(cnt % m).or_insert(0) += 1
} r
}
long long countInterestingSubarrays(vector<int>& n, int m, int k) {
unordered_map<int, int> map; long long r = 0; int cnt = 0; map[0] = 1;
for (int x: n) {
cnt = (cnt + (x % m == k)) % m;
r += map[(cnt + m - k) % m];
++map[cnt];
} return r;
}
24.04.2025
2799. Count Complete Subarrays in an Array medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/968
Problem TLDR
Subarrays having all uniqs #medium #two_pointers
Intuition
This is a standard two-pointers problem: count frequencies, always move right, move left until condition. All prefixes are valid starts of the subarrays.
// 0 1 2 3 4
// 1,3,1,2,2
// j i
- subarrays are valid for all indexes
0..j
Approach
- try to dry-run solution before pressing “submit”
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
fun countCompleteSubarrays(nums: IntArray): Int {
val f = IntArray(2001); var u = nums.toSet().size
return nums.sumOf { x ->
if (f[x]++ < 1) u--
while (u < 1) if (--f[nums[f[0]++]] < 1) u++
f[0]
}
}
fun countCompleteSubarrays(nums: IntArray): Int {
val f = IntArray(2001); var j = 0; var u = 0
for (x in nums) if (f[x] < 1) { u++; ++f[x] }
return nums.sumOf { x ->
if (f[x]++ < 2) u--
while (u < 1) if (--f[nums[j++]] < 2) u++
j
}
}
fun countCompleteSubarrays(nums: IntArray): Int {
val f = IntArray(2001); var j = 0; var r = 0
for (x in nums) {
if (f[x]++ < 1) r = 0
while (f[nums[j]] > 1) --f[nums[j++]]
r += j + 1
}
return r
}
pub fn count_complete_subarrays(nums: Vec<i32>) -> i32 {
let (mut f, mut j, mut u) = ([0; 2001], 0, 0);
for &x in &nums { if f[x as usize] < 1 { u += 1; f[x as usize] = 1}}
(0..nums.len()).map(|i| { let x = nums[i] as usize;
if f[x] < 2 { u -= 1 }; f[x] += 1;
while u < 1 { let x = nums[j] as usize; j += 1;
f[x] -= 1; if f[x] < 2 { u += 1 }}
j
}).sum::<usize>() as _
}
int countCompleteSubarrays(vector<int>& nums) {
int f[2001] = {}, u = 0, r = 0, j = 0;
for (int x: nums) if (!f[x]) ++u, ++f[x];
for (int x: nums) {
if (f[x]++ < 2) --u;
while (u < 1) if (--f[nums[j++]] < 2) ++u;
r += j;
} return r;
}
23.04.2025
1399. Count Largest Group easy
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/967
Problem TLDR
Count of max groups by digits sum 1..n #easy
Intuition
The brute-force is accepted.
Approach
- max digits sum is
9+9+9+9 = 36
Complexity
-
Time complexity: \(O(nlg(n))\)
-
Space complexity: \(O(n)\)
Code
fun countLargestGroup(n: Int): Int =
(1..n).groupBy { "$it".sumOf { it - '0' }}.values
.run { count { it.size == maxOf { it.size }}}
fun countLargestGroup(n: Int): Int {
val f = IntArray(37); var cnt = 0; var gmax = 0
for (x in 1..n) {
var s = 0; var y = x
while (y > 0) { s += y % 10; y /= 10 }
val g = ++f[s]
if (g > gmax) { gmax = g; cnt = 1 }
else if (g == gmax) cnt++
}
return cnt
}
pub fn count_largest_group(n: i32) -> i32 {
let (mut f, mut gmax, mut cnt) = ([0; 37], 0, 0);
for x in 1..=n {
let (mut s, mut y) = (0, x);
while y > 0 { s += y as usize % 10; y /= 10 }
f[s] += 1; let g = f[s];
if g > gmax { gmax = g; cnt = 1 }
else if g == gmax { cnt += 1 }
} cnt
}
int countLargestGroup(int n) {
int f[37], gmax = 0, cnt = 0;
for (;n;n--) {
int x = n, s = 0;
while (x) s += x % 10, x /= 10;
int g = ++f[s];
if (g > gmax) gmax = g, cnt = 1;
else if (g == gmax) cnt++;
} return cnt;
}
22.04.2025
2338. Count the Number of Ideal Arrays hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/966
Problem TLDR
Arrays a[i] % a[i - 1] == 0, i..n, a[i]..max #hard #combinatorics
Intuition
Didn’t solve. And didn’t understand the solution.
To make it work you have to be fluent with combinatorics.
You have to be fluent with Stars and bars https://cp-algorithms.com/combinatorics/stars_and_bars.html.
My thoughts rundown is irrelevant here, so I will not post it.
Some thoughts about the solution:
- arrays are
aaa | bbb | ccc, where|is the bars.1 | 2 | 4 4or1 1| 2 |4or1 | 2 2 | 4. - the max uniq sequence length is for
2:1,2,4,8,2^4,2^5,...2^i,..10000, max i is 2^13=8192 < 10000 - res +=
n choose k, n in1..maxValue, k in0..13. We considering placing1..maxValuenumbers into a length of0..13places
Approach
- maybe I should try more combinatorics problems to better understand them; right now they are not picturing in my brain canvas
Complexity
-
Time complexity: \(O(nlog(n))\)
-
Space complexity: \(O(nlog(n))\)
Code
fun idealArrays(n: Int, maxValue: Int): Int {
val comb = Array(10001) { IntArray(14) }; val cnt = Array(10001) { IntArray(14) }
val M = 1_000_000_007; comb[0][0] = 1; var res = 0L
for (s in 1..10000) { comb[s][0] = 1
for (r in 1..13) comb[s][r] = (comb[s - 1][r - 1] + comb[s - 1][r]) % M }
for (div in 1..10000) {
++cnt[div][0]
for (i in 2 * div..10000 step div)
for (bars in 0..12) cnt[i][bars + 1] += cnt[div][bars]
}
for (i in 1..maxValue) for (bars in 0..min(13, n))
res = (1L * cnt[i][bars] * comb[n - 1][bars] + res) % M
return res.toInt()
}
21.04.2025
2145. Count the Hidden Sequences medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/965
Problem TLDR
Possible arrays from diff array and lo..hi #medium
Intuition
Let’s observe the numbers, x is some starting point:
// 3,-4,5,1,-2 -4..5 len1 = 5-(-4) = 9
// x x
// x+3 x+3
// x+3-4 x-1 -1
// x+3-4+5 x+4
// x+3-4+5+1 x+5 5
// x+3-4+5+1-2 x+3
// -1..5 in -4..5 = (-4..2, -3..3, -2..4, -1..5)
// len2 = 5-(-1) = 6
// len1 - len2 + 1
// 1 -3 4 1..6, len1=6-1=5
// x x
// x+1 x+1
// x+1-3 x-2
// x+1-3+4 x+2
// -2..2, len2 = 2-(-2)=4
// len1 - len2 + 1 = 5-4+1=2
// -40 -46..53, len1=99
// x
// x-40
// len2=0-(-40)=40
// 99-40+1 = 60
- compute the
x_maxandx_min - find how many ranges of
x_min..x_maxin the rangelo..hi
Approach
- beware of the int overflow
- early exit is possible
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(1)\)
Code
```kotlin [Kotlin(5ms]
fun numberOfArrays(diff: IntArray, lo: Int, up: Int): Int {
var x = 0L; var a = 0L; var b = 0L
for (d in diff) { x += d; a = max(a, x); b = min(b, x) }
return max(0, 1L * up - lo - a + b + 1).toInt()
}
```kotlin [2ms)]
fun numberOfArrays(diff: IntArray, lo: Int, up: Int): Int {
var x = 0; var a = 0; var b = 0; val r = up - lo
for (d in diff) {
x += d
if (x > a) { a = x; if (a - b > r) return 0 }
else if (x < b) { b = x; if (a - b > r) return 0 }
}
return r - a + b + 1
}
```rust [Rust(0ms]
pub fn number_of_arrays(diff: Vec<i32>, lo: i32, up: i32) -> i32 {
let (mut x, mut a, mut b) = (0, 0, 0);
for d in diff { x += d as i64; a = a.max(x); b = b.min(x) }
0.max(up - lo + 1 - (a - b) as i32)
}
```rust [0ms)]
pub fn number_of_arrays(diff: Vec<i32>, lo: i32, up: i32) -> i32 {
let (mut x, mut a, mut b) = (0, 0, 0);
for d in diff { x += d; a = a.max(x); b = b.min(x);
if a - b > up - lo { return 0 } }
up - lo + 1 - a + b
}
```c++ [C++(0ms)]
int numberOfArrays(vector<int>& diff, int lo, int up) {
long long x = 0, a = 0, b = 0;
for (int d: diff) a = max(a, x += d), b = min(b, x);
return (int) max(0LL, b - a + up - lo + 1);
}
# 20.04.2025
[781. Rabbits in Forest](https://leetcode.com/problems/rabbits-in-forest/description) medium
[blog post](https://leetcode.com/problems/rabbits-in-forest/solutions/6669530/kotlin-rust-by-samoylenkodmitry-epo4/)
[substack](https://open.substack.com/pub/dmitriisamoilenko/p/20042025-781-rabbits-in-forest?r=2bam17&utm_campaign=post&utm_medium=web&showWelcomeOnShare=true)
[youtube](https://youtu.be/a2Bwo9E0RDo)

#### Join me on Telegram
https://t.me/leetcode_daily_unstoppable/964
#### Problem TLDR
Count total rabbits from other numbers #medium #math #brainteaser
#### Intuition
* the rabbit tells how many *other* rabbits are
Thoughts process:
```j
// 10,10,10 11 how?
// brain teaser
// 10 red
// 10 red
// 10 red it is 3 that answered,
// 10 - 3 = 7 not answered
// 2 2 2 2 2
// 5 +
// I do not understand the problem
// "have the same color as you"
// is it including or excluding?
// suppose excluding
// 1 1 2
// * one other - mark red
// * one other - mark red
// * two others - no other with two
// 3 + 2 of no-matches
// 10 10 10
// * ten others - mark red (total 1 + 10)
// * ten others - red
// * ten others - red
// total = 11
// 2 2 2
// * 2 others (total 1 + 2 = 3)
// * 2 others
// * 2 others
// 3 of red
// 1 1 = 2
// 1 1 1 = 1 1 | 1 = 2 + 2
// 1 1 1 1 = 1 1 | 1 1 = 2 + 2
// 1 1 1 1 1 = 1 1 | 1 1 | 1 = 2 + 2 + 2 = 6
// 2 2 2 2
// so we have 4 rabbits
// only 3 can be same color (2 + 1)
// x = 2
// group = 3 = (2 + 1) = g = x + 1
// buckets = f(2) / (2 + 1) = f / g + f % g
// = 4 / 3 + 4 % 3 = 2
// count = buckets * g = 2 * 3 = 6
// 2 = 3
// 2 2 = 3
// 2 2 2 = 3
// 2 2 2 2 = 2 2 2 | 2 = 3 + 3 = 6
- each group defined by the
othersanswer,group countisothers + 1 - total answered rabbits should be split into the buckes of
group count
Approach
- from
u/votrubac/&u/lee215/: we can increment a new group on the go
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
fun numRabbits(answers: IntArray) = answers.groupBy { it }
.entries.sumOf { (x, f) -> (f.size + x) / (x + 1) * (x + 1) }
fun numRabbits(answers: IntArray): Int {
val f = IntArray(1001); for (x in answers) ++f[x]
for (x in 0..999) if (f[x] > 0)
f[1000] += (f[x] + x) / (x + 1) * (x + 1)
return f[1000]
}
fun numRabbits(answers: IntArray): Int {
val f = IntArray(1000); var r = 0;
for (x in answers) if (f[x]++ % (x + 1) < 1) r += x + 1
return r
}
pub fn num_rabbits(answers: Vec<i32>) -> i32 {
let (mut f, mut r) = ([0; 1000], 0);
for x in answers {
if f[x as usize] % (x + 1) < 1 { r += x + 1 }
f[x as usize] += 1
} r
}
int numRabbits(vector<int>& a) {
int r = 0, f[1000];
for (int x: a) if (f[x]++ % (x + 1) < 1) r += x + 1;
return r;
}
19.04.2025
2563. Count the Number of Fair Pairs medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/963
Problem TLDR
Pairs a + b in lower..upper #medium #two_pointers
Intuition
This time I was able to solve it with hints. Previous time was a fail (5 month ago https://leetcode.com/problems/count-the-number-of-fair-pairs/solutions/6040302/kotlin-rust/).
The hints that helped the most:
- both boundaries move only in a single direction (you have to know how to use them though)
Here is my thougths rundown:
// 0,1,7,4,4,5 3..6
// i
// how many visited numbers are in range
// 3 <= x + a[i] <= 6
// 3 - a[i] <= x <= 6 - a[i]
// i
// expect numbers in range
// 3 <= a[i] + x <= 6
// 3 - a[i]..6 - a[i] segment tree?
// sort and binary search
//
// 0,1, 7,4,4,5 3..6
// 3 2 -4
// 4 3 -3
// 5 4 -2
// 6 5 -1
// total n^2 pairs possible, i < j is irrelevant
// 0 1 4 4 5 7 two-sum
// l-> (increase left to make sum bigger)
// r-> (increase right to make sum bigger)
// count of pairs > upper
// count of pairs < lower
// -2 -1 0 1 2 0..1
// * *
// * *
// * *
// * *
// 0 1 4 4 5 7 3..6
// * 3..6 just move l and r, they always go to the left
// * 2..5 -1
// * -1..2 -3
// *
// * -2..1 -1
// * -4..-1 -2
// 1 2 5 7 9 11..11
My observations:
- i and j positions are irrelevant, we can safely sort
- we can do a binary search (I have failed to implement this in Kotlin)
- we can move both borders left as we go right
- for count lower..upper we may apply count(upper) - count(lower) rule
Approach
- let’s implement everything and see what’s the best
Complexity
-
Time complexity: \(O(nlog(n))\)
-
Space complexity: \(O(1)\)
Code
fun countFairPairs(n: IntArray, lower: Int, upper: Int): Long {
n.sort(); val n = n.asList()
return n.withIndex().sumOf { (i, x) -> 1L *
max(i + 1, -n.binarySearch { if (it <= upper - x) -1 else 1 } - 1) -
max(i + 1, -n.binarySearch { if (it < lower - x) -1 else 1 } - 1)
}
}
fun countFairPairs(n: IntArray, lower: Int, upper: Int): Long {
n.sort(); var r = 0L; val n = Array(n.size) { n[it] }
val cmp = Comparator<Int> { a, b -> if (a < b) -1 else 1 }
for (i in 0..<n.size) r -=
Arrays.binarySearch(n, i + 1, n.size, upper - n[i] + 1, cmp) -
Arrays.binarySearch(n, i + 1, n.size, lower - n[i], cmp)
return r
}
fun countFairPairs(n: IntArray, lower: Int, upper: Int): Long {
n.sort(); var l = n.size - 1; var r = l
return (0..r).sumOf { i ->
while (l > i && n[l] + n[i] >= lower) l--
while (r > l && n[r] + n[i] > upper) r--
1L * max(i, r) - max(i, l)
}
}
fun countFairPairs(n: IntArray, lower: Int, upper: Int): Long {
n.sort(); var res = 0L; var l = n.size - 1; var r = l
for (i in 0..r) {
while (l > i && n[l] + n[i] >= lower) l--
while (r > l && n[r] + n[i] > upper) r--
if (r <= i) break; res += r - max(i, l)
}
return res
}
fun countFairPairs(n: IntArray, lower: Int, upper: Int): Long {
fun cnt(max: Int): Long {
var res = 0L; var l = 0; var r = n.size - 1
while (l < r) if (n[l] + n[r] > max) r-- else res += r - l++
return res
}
n.sort(); return cnt(upper) - cnt(lower - 1)
}
pub fn count_fair_pairs(mut nums: Vec<i32>, lower: i32, upper: i32) -> i64 {
nums.sort();
(0..nums.len()).map(|i|
nums[..i].partition_point(|&n| n <= upper - nums[i]) -
nums[..i].partition_point(|&n| n < lower - nums[i])
).sum::<usize>() as _
}
pub fn count_fair_pairs(mut nums: Vec<i32>, lower: i32, upper: i32) -> i64 {
fn cnt(nums: &Vec<i32>, max: i32) -> i64 {
let (mut res, mut l, mut r) = (0, 0, nums.len() - 1);
while l < r {
if nums[l] + nums[r] > max { r -= 1 }
else { res += (r - l) as i64; l += 1 }
} res
}
nums.sort(); cnt(&nums, upper) - cnt(&nums, lower - 1)
}
pub fn count_fair_pairs(mut n: Vec<i32>, lower: i32, upper: i32) -> i64 {
n.sort(); let (mut l, mut r, mut res) = (n.len() - 1, n.len() - 1, 0);
for i in 0..=r {
while l > i && n[i] + n[l] >= lower { l -= 1 }
while r > l && n[i] + n[r] > upper { r -= 1 }
if r <= i { break }; res += (r - i.max(l)) as i64
} res
}
pub fn count_fair_pairs(mut n: Vec<i32>, lower: i32, upper: i32) -> i64 {
n.sort(); let (mut l, mut r) = (n.len() - 1, n.len() - 1);
(0..=r).map(|i| {
while l > i && n[i] + n[l] >= lower { l -= 1 }
while r > l && n[i] + n[r] > upper { r -= 1 }
(i.max(r) - i.max(l)) as i64 }).sum()
}
long long countFairPairs(vector<int>& a, int l, int u) {
sort(begin(a), end(a)); long long r = 0;
for(int m: array{u, l - 1}) for (int i = 0, j = a.size() - 1; i < j;)
if (a[i] + a[j] > m) --j;
else r += (m == u ? 1 : -1) * (j - i++);
return r;
}
18.04.2025
38. Count and Say medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/962
Problem TLDR
nth run-length encoded string #medium
Intuition
Just simulate, the n is small.
Approach
- it is interesting to optimize this solution
- it is well-known sequence
A005150named “Look-and-say” https://en.wikipedia.org/wiki/Look-and-say_sequence https://oeis.org/A005150 - the only numbers are 1, 2 and 3
Complexity
-
Time complexity: \(O(n^2)\), according to wiki, it grows 30% per generation
-
Space complexity: \(O(n^2)\)
Code
fun countAndSay(n: Int): String = if (n < 2) "1" else buildString {
val s = countAndSay(n - 1); var i = 0; var j = 0
while (i < s.length) {
while (j < s.length && s[i] == s[j]) j++
append(j - i).append(s[i]); i = j
}
}
fun countAndSay(n: Int): String {
var a = CharArray((49 * n * n + 20 * n) / 10); var b = CharArray(a.size)
a[0] = '1'; var sz = 1
for (r in 2..n) {
var i = 0; var j = 0; var k = 0
while (i < sz) {
val x = a[i]
while (j < sz && a[j] == x) j++
b[k++] = '0' + j - i
b[k++] = x
i = j
}
a = b.also { b = a }; sz = k
}
return String(a, 0, sz)
}
val answers = {
var a = CharArray(3410); var b = CharArray(4463)
a[0] = '1'; var sz = 1; val res = Array(31) { "1" }
for (r in 2..30) {
var i = 0; var j = 0; var k = 0
while (i < sz) {
val x = a[i]
while (j < sz && a[j] == x) j++
b[k++] = '0' + j - i
b[k++] = x
i = j
}
a = b.also { b = a }; sz = k
res[r] = String(a, 0, sz)
}
res
}()
class Solution { fun countAndSay(n: Int) = answers[n] }
pub fn count_and_say(n: i32) -> String {
if n < 2 { return "1".into() }
let s = Self::count_and_say(n - 1); let s = s.as_bytes();
let (mut i, mut j, mut v) = (0, 0, vec![]);
while i < s.len() {
while j < s.len() && s[i] == s[j] { j += 1 }
v.push(b'0' + (j - i) as u8); v.push(s[i]); i = j
} String::from_utf8(v).unwrap()
}
string countAndSay(int n) {
if (n < 2) return "1";
string s = countAndSay(n - 1), r;
for (int i = 0, j = 0; i < size(s); i = j) {
while (j < size(s) && s[i] == s[j]) ++j;
r += '0' + j - i; r += s[i];
} return r;
}
17.04.2025
2176. Count Equal and Divisible Pairs in an Array easy
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/961
Problem TLDR
Pairs a[i] == b[j], i * j % k == 0 #easy
Intuition
The brute force is accepted.
Approach
- the problem has also more optimal solution by using
gcd(i, k) * gcd(j, k) % k == 0equality
Complexity
-
Time complexity: \(O(n^2)\)
-
Space complexity: \(O(1)\)
Code
fun countPairs(nums: IntArray, k: Int) =
nums.indices.sumOf { i ->
(i + 1..<nums.size).count { j ->
(i * j) % k == 0 && nums[i] == nums[j] }}
pub fn count_pairs(n: Vec<i32>, k: i32) -> i32 {
(0..n.len()).map(|i| (i + 1..n.len()).filter(|&j|
(i * j) as i32 % k < 1 && n[i] == n[j]).count() as i32).sum()
}
int countPairs(vector<int>& n, int k) {
int r = 0;
for (int i = 0; i < size(n); ++i)
for (int j = i + 1; j < size(n); ++j)
r += i * j % k < 1 && n[i] == n[j];
return r;
}
16.04.2025
2537. Count the Number of Good Subarrays medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/960
Problem TLDR
Subarrays with at least k equal pairs #medium #sliding_window #math
Intuition
Let’s observe sliding window:
// [3,1,4,3,2,2,4], k = 2
// freq
// i j 3->2
// i j 3->2 + 2->2 2
// i j 3->2 + 2->2 + 4->2 3
// i j 2->2 + 4->2 2
// i j 2->2 + 4->2 2
// when to move second pointer to shrink?
// ****************
// i j-> expand until good, + all before i count
// i-> j shrink while good
Expand window until we get k equal pairs.
The hardest part is to reason about when to shrink the window.
The count & shrink technique is: we always freeze the right border and shrink left while we can. The prefix is all valid subarrays, so count all of them.
Now, how to increase and decrease the frequency?
// freq = 4, (n - 1) * (n - 2) / 2
// freq = 5, n * (n - 1) / 2 - (n - 1) * (n - 2) / 2
// (n - n + 2) * (n - 1) / 2
// 2 * (n - 1) / 2
// n - 1
By looking at 1 1 1 1 1 example, the pairs count is p = f * (f - 1) / 2. So, the diff is p(n) - p(n - 1) = n - 1.
Approach
- we can shrink window up to the
invalidstate andnotcheck if it is valid to addj, asj = 0initially
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
fun countGood(n: IntArray, k: Int): Long {
val f = HashMap<Int, Int>(); var j = 0; var p = 0
return n.indices.sumOf { i ->
p += f[n[i]] ?: 0
f[n[i]] = 1 + (f[n[i]] ?: 0)
while (p >= k) { f[n[j]] = f[n[j]]!! - 1; p -= f[n[j++]]!! }
1L * j
}
}
pub fn count_good(n: Vec<i32>, mut k: i32) -> i64 {
let (mut f, mut j) = (HashMap::new(), 0);
(0..n.len()).map(|i| {
k -= f.get(&n[i]).unwrap_or(&0); *f.entry(n[i]).or_default() += 1;
while k <= 0 { *f.entry(n[j]).or_default() -= 1; k += f[&n[j]]; j += 1 }
j as i64
}).sum::<i64>()
}
long long countGood(vector<int>& n, int k) {
long long r = 0LL; unordered_map<int, int> f;
for (int i = 0, j = 0; i < size(n); ++i, r += j) {
k -= f[n[i]]++; while (k <= 0) k += --f[n[j++]];
} return r;
}
15.04.2025
2179. Count Good Triplets in an Array hard
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/959
Problem TLDR
Triplets in same order in both (0..n)-arrays #hard #bit
Intuition
Didn’t solve, as I am not familiar with Fenwick Tree or Binary Indexed Tree.
Some of my thought process and observations:
// 4,0,1,3,2
// 4,1,0,2,3
//*4 (0 1 3 2) and (1 0 2 3)
// 0 (1 3 2) and (2 3) -> 2,3
// 1 (3 2) and (0 2 3) -> 2,3
//
// *0 (1 3 2) and (2 3)
// 1- can't take, pos2(-1) < pos2(0)
// 3 (2) and ()
// this is an n^2 algo
// numbers are exactly 0..n-1
// 0 1 2 3 4 can we sort both and preserve the relations?
// 0 1 2
// 0 3 4
// 0 1 2 3 4
// 4,0,1,3,2 -> 0 1 2 3 4
// 4,1,0,2,3 -> 0 2 1 4 3 now the problem is to count increasing sequencies
// 0 2 1 4 3 . . number of increasing triplets? or subsequences?
// 0 2 4
// 0 2 . 3
// 0 . 1 4
// 0 . 1 . 3
// . . monotonic stack count smaller than current
// 0 . . 0 0
// 2 . 02 1
// 1 . 01 1
// 4 014 2 (lost '2')
// use the hint - totally different algo
// the useful hint - triplets are better observed by middle: count smaller * count bigger
// 0 count less = 0, count bigger = n - 1
// 2 count less = 1, count bigger = n - 1 - 1
The most helpful observation was that problem can be narrowed down to a single array with increased triplets.
The most helpful hint is for triplets: consider the middle, then the problem became how much to the left and how much to the right.
However, to answer how many numbers are less than current in a less than O(n^2) you have to know BIT.
BIT:
//
// 2 0 1 3 -> 0 1 2 3
// 0 1 2 3 -> 1 2 0 3
//
// didn't quite get how to use BIT here
// count values smaller/bigger than x
// add x, remove x
// 16
// 8 16
// 4 8 12 16
// 2 4 6 8 10 12 14 16
// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
//
// add 6: 7 -> 8 -> 16
// add 4: 5 -> 6 -> 8 -> 16
// count less than 8: 9_1001(0) -> 8_1000(2) -> 0
// count less than 7: 8_1000(2) -> 0
// count less than 6: 7_111(0) -> 6_110(1) -> 4_100 -> 0
// count less than 5: 6_110(1) -> 4_100 -> 0
// count less than 4: 5_101(0) -> 4_100 -> 0
This is not the first time I see the BIT, but it is so rare, I forgot how it works.
The idea is the bits: each rightmost bit is a parent of all the left bits.
The core implementation tricks:
- use idx + 1
- use i & (-i), and
+makes it go to the parent,-iterates all the children


