Skip to content

Commit 519e952

Browse files
3750x
1 parent 580542e commit 519e952

File tree

13 files changed

+653
-166
lines changed

13 files changed

+653
-166
lines changed

data/book-sets.json

Lines changed: 159 additions & 166 deletions
Large diffs are not rendered by default.

explanations/3750/en.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
## Explanation
2+
3+
### Strategy
4+
5+
**Constraints & Edge Cases**
6+
7+
* **Binary Representation:** We are working with the bits of an integer $n$. The length of the binary string depends on the magnitude of $n$ (up to $\approx 30$ bits for standard integers).
8+
* **Time Complexity:** Since the number of bits is small ($\log_2 n$), the solution will be very fast, effectively $O(\log n)$.
9+
* **Edge Case:** If $n=0$ or $n$ is a single bit (e.g., 1), the reverse is identical to the original, so the answer is 0.
10+
11+
**High-level approach**
12+
The problem asks for the minimum flips to make a number equal to its **original** binary reverse.
13+
Imagine the binary string as a row of lights. We compare the light at the very start (left) with the light at the very end (right).
14+
15+
* If the left bit is `1` and the right bit is `0`, we have a mismatch.
16+
* To make the number equal to its reverse, the left position *must* become what the right position was, and the right position *must* become what the left position was. This requires flipping **both** bits.
17+
* Therefore, every mismatching symmetric pair costs exactly **2 flips**.
18+
19+
**Brute force vs. optimized strategy**
20+
21+
* **Brute Force:** Calculate the reverse of $n$ separately, then iterate through every bit of $n$ and the reverse to count differences.
22+
* **Optimized (Two Pointers):** We extract the binary string once. We place pointers at the start and end. We move them inward, counting mismatches. This is efficient and requires only one pass over the bits.
23+
24+
**Decomposition**
25+
26+
1. **Bit Extraction:** Convert the integer $n$ into its binary string format (removing the '0b' prefix).
27+
2. **Two-Pointer Scan:** Initialize `left` at index 0 and `right` at the last index.
28+
3. **Check Pairs:** If `s[left] != s[right]`, we found a mismatch. Add 2 to our result (1 flip for each side).
29+
4. **Converge:** Move `left` forward and `right` backward until they meet.
30+
31+
### Steps
32+
33+
1. **Convert to Binary**
34+
Turn the integer $n$ into a string of bits. For example, if $n=10$, we get the string `"1010"`.
35+
36+
2. **Initialize Pointers**
37+
Set a variable `res` to 0. Set `l` to the start of the string and `r` to the end.
38+
39+
3. **Iterate and Compare**
40+
While `l` is less than `r`:
41+
42+
* Check if the bit at `l` is different from the bit at `r`.
43+
* **Why?** If the bits are different (e.g., `1` and `0`), then to swap their values effectively (so the number equals its reverse), both positions must be flipped.
44+
* If they differ, add **2** to `res`.
45+
46+
4. **Close the Window**
47+
Increment `l` and decrement `r` to check the next pair of bits. Continue until the pointers meet in the middle.
48+
49+
-----
50+
51+
See the solution code in `solutions/3750/01.py`.

explanations/3751/en.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
## Explanation
2+
3+
### Strategy
4+
5+
**Constraints & Edge Cases**
6+
7+
* **Range Size:** The input numbers go up to 100,000.
8+
* **Performance:** If we calculate the waviness for every number in the range `[num1, num2]` every time the function is called, we will likely hit a Time Limit Exceeded (TLE) error. The constraints imply we need a faster way to query.
9+
* **Edge Case:** Numbers less than 100 (0-99) have fewer than 3 digits. You cannot have a "middle" digit with neighbors on both sides, so their waviness is always 0.
10+
11+
**High-level approach**
12+
We will use the **Prefix Sum** technique (also called Cumulative Sum). Instead of calculating the waviness on the fly, we will **precompute** the waviness for every possible number up to the maximum limit (100,000) once. We then store the cumulative totals in an array.
13+
14+
**Brute force vs. optimized strategy**
15+
16+
* **Brute Force:** Loop from `num1` to `num2`. For each number, convert to string, check digits, count peaks/valleys, and add to total. This repeats the same heavy work for every query.
17+
* **Optimized:** Create a lookup table `P`.
18+
`P[i]` stores the total waviness of *all* numbers from `0` to `i`.
19+
To find the waviness between `num1` and `num2`, we simply do `P[num2] - P[num1 - 1]`. This answers any query in $O(1)$ time.
20+
21+
**Decomposition**
22+
23+
1. **Helper Logic:** Define how to calculate waviness for a single number (check neighbors).
24+
2. **Precomputation:** Build an array where we store the cumulative waviness.
25+
3. **Range Query:** Use the array to answer the user's request instantly.
26+
27+
### Steps
28+
29+
1. **Define Waviness**
30+
A digit is part of a "wave" if it is strictly greater than its neighbors (Peak) or strictly smaller than its neighbors (Valley).
31+
32+
* *Visual Peak:* `1 -> 5 -> 2` (5 is a peak)
33+
* *Visual Valley:* `9 -> 0 -> 4` (0 is a valley)
34+
* We ignore the first and last digits because they don't have neighbors on both sides.
35+
36+
2. **Initialize the Prefix Array**
37+
We create an array `prefix` of size 100,001 (covering 0 to 100,000).
38+
We define `running_total` to keep track of the sum as we build the array.
39+
40+
3. **Populate the Array**
41+
We loop through every number `i` from 0 to 100,000.
42+
43+
* Convert `i` to a string (or use math) to access digits.
44+
* Count the peaks and valleys for `i`.
45+
* Add this count to `running_total`.
46+
* Store `running_total` in `prefix[i]`.
47+
48+
4. **Answer the Query**
49+
When the user asks for the range `[num1, num2]`:
50+
51+
* Take the total waviness up to `num2` (`prefix[num2]`).
52+
* Subtract the total waviness before the range starts (`prefix[num1 - 1]`).
53+
* Return the result.

explanations/3752/en.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
## Explanation
2+
3+
### Strategy
4+
5+
**The Bug Analysis**
6+
Your current logic checks two things for feasibility:
7+
8+
1. Is `target` greater than the maximum possible sum (`total_sum`)? (Handled by `diff < 0`)
9+
2. Is the parity correct? (Handled by `diff % 2 != 0`)
10+
11+
However, it misses the **Lower Bound** check.
12+
In your failing test case:
13+
14+
* `n = 1`
15+
* `target = -3`
16+
* Max possible sum (all positive) = $1$.
17+
* Min possible sum (all negative) = $-1$.
18+
19+
The target $-3$ is smaller than the minimum possible sum $-1$. Your code calculates a `negative_budget` of 2 (meaning we need to flip numbers summing to 2), but we only have the number 1 available. The greedy loop runs, subtracts 1, leaves the budget at 1, and returns `[-1]` (which sums to -1, not -3).
20+
21+
**The Fix**
22+
We must verify that the `target` is not smaller than the purely negative sum.
23+
Alternatively, and more robustly, we can check if `negative_budget` is exactly `0` after our greedy loop. If the budget isn't 0, it means we couldn't find enough numbers to flip to satisfy the target.
24+
25+
### Steps
26+
27+
1. **Calculate Total Sum:** Same as before ($n(n+1)/2$).
28+
2. **Expanded Feasibility Check:**
29+
* Check `abs(target) > total_sum`. If the target is outside the range `[-total_sum, total_sum]`, return `[]`.
30+
* Check parity (`diff % 2 != 0`).
31+
3. **Greedy Loop:** Same as before.
32+
4. **Final Verification:** (Optional if bounds check is strict, but good practice) Ensure `negative_budget` reached 0.

explanations/3754/en.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
## Explanation
2+
3+
### Strategy
4+
5+
**Constraints & Edge Cases**
6+
7+
* **Input Size:** This is the "easy" version of the problem, meaning $n$ is likely a standard integer. The number of digits ($D$) is small enough that we can process them directly without complex prefix arrays.
8+
* **Zeros:** The core constraint is ignoring zeros.
9+
* **Edge Case:** If $n = 0$, filtering out zeros leaves an empty set. We must handle this to avoid conversion errors or returning an incorrect result (the answer should be 0).
10+
11+
**High-level approach**
12+
The most readable way to handle digits is to treat the number as a string. We convert the number to text, filter out the characters equal to `'0'`, and then perform two parallel operations on the remaining digits: concatenate them to form a new number $x$, and sum them to form $s$.
13+
14+
**Brute force vs. optimized strategy**
15+
16+
* **Mathematical Approach:** We could use a loop with `% 10` and `/ 10` to extract digits. While memory-efficient, this logic is verbose because we extract digits in reverse order (right-to-left), requiring us to reverse them back for concatenation.
17+
* **String Approach:** Converting to a string allows strictly left-to-right processing using Python's powerful list comprehensions. This is $O(\log n)$ (proportional to the number of digits) and extremely clean.
18+
19+
**Decomposition**
20+
21+
1. **String Conversion:** Turn integer $n$ into string `s`.
22+
2. **Filter:** Create a list of digits excluding `'0'`.
23+
3. **Reconstruct:** Join the list to form the integer $x$.
24+
4. **Sum:** Calculate the sum of the digits.
25+
5. **Compute:** Return $x \times \text{sum}$.
26+
27+
### Steps
28+
29+
1. **Convert and Filter**
30+
Convert the input integer `n` to a string. Iterate through this string and collect only the characters that are not `'0'`.
31+
32+
2. **Handle Zeros**
33+
Check if our list of filtered digits is empty. This happens if the input was `0`. In this case, return `0` immediately.
34+
35+
3. **Form the Number (Concatenation)**
36+
Use the string `join` method to combine the filtered characters back into a single string, then convert that string into an integer. Let's call this `x`.
37+
38+
4. **Calculate Digit Sum**
39+
Iterate through the filtered list again (or use a generator), convert each character to an integer, and sum them up.
40+
41+
5. **Return Result**
42+
Multiply `x` by the sum and return the result.

explanations/3755/en.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
## Explanation
2+
3+
### Strategy
4+
5+
**Constraints & Edge Cases**
6+
7+
* **Array Size:** Typically up to $10^5$.
8+
* **Time Complexity:** Since we are looking for a subarray, a nested loop approach (Brute Force) would be $O(N^2)$, which is too slow. We need a linear $O(N)$ pass.
9+
* **Edge Case:** A valid subarray might start from the very beginning (index 0). We need to handle this by initializing our state tracking with a "dummy" start point.
10+
11+
**High-level approach**
12+
We are looking for a subarray that satisfies two conditions simultaneously: `XOR sum == 0` and `Odd Count == Even Count`.
13+
We can track the "state" of the array at every index using **Prefix Logic**. If the state at index `i` is identical to the state at index `j` (where `j < i`), then the subarray between them (`j+1` to `i`) has "zeroed out" the changes, satisfying our conditions.
14+
15+
**Brute force vs. optimized strategy**
16+
17+
* **Brute Force:** Iterate through every possible starting point `i` and ending point `j`, calculate the XOR and count odds/evens. This is inefficient.
18+
* **Optimized:** We use a Hash Map (Dictionary) to store the **first time** we encounter a specific state. As we iterate, if we see that state again, the distance between the current index and the stored index is a candidate for the maximum length.
19+
20+
**Decomposition**
21+
22+
1. **Track XOR:** Maintain a running XOR of all numbers seen so far.
23+
2. **Track Balance:** Maintain a running "balance" score. Add 1 for an odd number, subtract 1 for an even number. If the balance doesn't change between two indices, the number of odds and evens added in between must be equal.
24+
3. **Map States:** Store the tuple `(current_xor, current_balance)` in a dictionary mapping to its index.
25+
26+
### Steps
27+
28+
1. **Initialize Variables**
29+
We need `curr_xor` (starts at 0) and `balance` (starts at 0).
30+
We create a dictionary `seen` to store the first index where a specific state occurred.
31+
32+
* *Crucial Step:* Initialize `seen[(0, 0)] = -1`. This represents the state before we start reading the array. It ensures that if a valid subarray starts at index 0, we can calculate its length correctly (`current_index - (-1)`).
33+
34+
2. **Iterate Through the Array**
35+
Loop through `nums` using the index `i` and the value `num`.
36+
37+
3. **Update State**
38+
39+
* Update `curr_xor` by XORing it with `num`.
40+
* Check if `num` is odd or even:
41+
* If **Odd**: Increment `balance` (+1).
42+
* If **Even**: Decrement `balance` (-1).
43+
* *Concept:* The specific value of `balance` doesn't matter (it could be -5 or +100). What matters is that `balance` at index `i` equals `balance` at index `j`. This proves that between `j` and `i`, the net change in odd/even ratio is zero.
44+
45+
4. **Check Dictionary**
46+
Create a key: `state = (curr_xor, balance)`.
47+
48+
* **If `state` is already in `seen`:** This means we have encountered this exact scenario before. The subarray between the previous occurrence and now is valid.
49+
* Calculate `length = i - seen[state]`.
50+
* Update our result `res` if this length is the new maximum.
51+
* **If `state` is NOT in `seen`:** This is the first time we've encountered this particular combination of XOR and Balance. Store it: `seen[state] = i`.

explanations/3756/en.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
## Explanation
2+
3+
### Strategy
4+
5+
**Constraints & Edge Cases**
6+
We are dealing with string lengths ($n$) and query counts ($q$) up to 100,000.
7+
8+
* **Time Complexity:** A solution that loops through the substring for every query will be $O(n \cdot q)$, which is far too slow. We need an $O(1)$ solution per query.
9+
* **Large Numbers:** The resulting numbers can be massive. We must apply modulo $10^9 + 7$ at every addition or multiplication step.
10+
* **Zeros:** The problem asks us to ignore zeros. If a range contains only zeros, our logic needs to handle returning 0 gracefully.
11+
12+
**High-level approach**
13+
We will use the **Prefix Sum** technique, adapted for string concatenation. Instead of just summing numbers, we will maintain a "rolling hash" or "prefix value" that represents the integer formed by the string up to index $i$. To get a specific substring's value, we take the total value up to the end of the range and mathematically "subtract" the prefix before the range.
14+
15+
**Brute force vs. optimized strategy**
16+
17+
* **Brute Force:** For each query, slice the string `s[l:r+1]`, filter out '0', parse to int, and multiply. This involves heavy string manipulation inside a loop.
18+
* **Optimized:** Precompute three arrays: one for the concatenated value, one for the count of non-zero digits, and one for the simple sum of digits. We can then solve any query instantly using modular arithmetic.
19+
20+
**Decomposition**
21+
22+
1. **Map the Data:** Create prefix arrays that track the state of the string (value, count, sum) at every index.
23+
2. **Precompute Powers:** Calculate powers of 10 beforehand so we can "shift" numbers left efficiently.
24+
3. **Query Logic:** For each query, use the prefix arrays to isolate the target number and calculate the final result.
25+
26+
### Steps
27+
28+
1. **Initialize Prefix Arrays**
29+
We need three arrays of size $N+1$. We use $N+1$ to make 1-based indexing easier (index $i$ represents the state *after* processing character $i-1$).
30+
31+
* `p_val`: The integer value of all non-zero digits concatenated so far.
32+
* `p_cnt`: The total count of non-zero digits encountered so far.
33+
* `p_sum`: The simple arithmetic sum of non-zero digits so far.
34+
35+
2. **Build the Prefixes**
36+
Iterate through the string `s`.
37+
38+
* If the character is `'0'`, the state doesn't change. Copy the values from index $i$ to $i+1$.
39+
* If it's a non-zero digit $d$:
40+
* Update sum: `new_sum = old_sum + d`.
41+
* Update count: `new_cnt = old_count + 1`.
42+
* Update value: Append the digit by shifting the old value left (multiply by 10) and adding $d$. Formula: `(old_val * 10 + d) % MOD`.
43+
44+
3. **Precompute Powers of 10**
45+
To perform the "subtraction" logic later, we need to know what $10^k$ is for any $k$. Since we are working with modular arithmetic, we cannot just use `10 ** k` inside the loop (it's too slow). We precompute an array `pow10` where `pow10[k]` holds $10^k \pmod M$.
46+
47+
4. **Calculate Query Results**
48+
For each query `[l, r]`:
49+
50+
* **Step A (Simple Stats):** Calculate the number of non-zero digits (`cnt`) and their sum (`d_sum`) by subtracting the value at index $l$ from the value at index $r+1$.
51+
* **Step B (Extract Number):** We have the full prefix ending at `r` (`full`) and the prefix ending before `l` (`prev`). To isolate the middle part, we must subtract `prev` from `full`.
52+
* *Crucial Logic:* To align them correctly, `prev` must be shifted left by `cnt` positions.
53+
* Formula: `target = (full - (prev * pow10[cnt])) % MOD`.
54+
* **Step C:** Multiply `target` by `d_sum` and store it in `res`.

solutions/3750/01.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
class Solution:
2+
def minimumFlips(self, n: int) -> int:
3+
# Convert n to binary string, slicing off the "0b" prefix
4+
s = bin(n)[2:]
5+
6+
res = 0
7+
l = 0
8+
r = len(s) - 1
9+
10+
# Use two pointers to compare symmetric bits
11+
while l < r:
12+
# If the bits at the symmetric positions are different
13+
# we need to flip both to make the number equal to its reverse.
14+
if s[l] != s[r]:
15+
res += 2
16+
17+
l += 1
18+
r -= 1
19+
20+
return res

solutions/3751/01.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
class Solution:
2+
def __init__(self):
3+
# We precompute the values up to 100,000 (limit from problem constraints)
4+
MAX_N = 100000
5+
self.prefix = [0] * (MAX_N + 1)
6+
7+
running_total = 0
8+
9+
for i in range(MAX_N + 1):
10+
waviness = 0
11+
s = str(i)
12+
13+
# Only numbers with 3 or more digits can have waviness
14+
if len(s) >= 3:
15+
for j in range(1, len(s) - 1):
16+
prev_d = int(s[j-1])
17+
curr_d = int(s[j])
18+
next_d = int(s[j+1])
19+
20+
# Check for Peak (prev < curr > next)
21+
if prev_d < curr_d and curr_d > next_d:
22+
waviness += 1
23+
# Check for Valley (prev > curr < next)
24+
elif prev_d > curr_d and curr_d < next_d:
25+
waviness += 1
26+
27+
running_total += waviness
28+
self.prefix[i] = running_total
29+
30+
def totalWaviness(self, num1: int, num2: int) -> int:
31+
# Standard prefix sum range query formula:
32+
# Sum(L, R) = Prefix[R] - Prefix[L-1]
33+
34+
upper = self.prefix[num2]
35+
lower = self.prefix[num1 - 1] if num1 > 0 else 0
36+
37+
res = upper - lower
38+
return res
39+

solutions/3752/01.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
class Solution:
2+
def lexSmallestNegatedPerm(self, n: int, target: int) -> list[int]:
3+
# 1. Calculate the maximum possible sum (all positives)
4+
total_sum = n * (n + 1) // 2
5+
6+
# 2. Check Feasibility (Bounds AND Parity)
7+
# BUG FIX: We must check if target is smaller than the minimum possible sum (-total_sum)
8+
if target < -total_sum or target > total_sum:
9+
return []
10+
11+
diff = total_sum - target
12+
13+
if diff % 2 != 0:
14+
return []
15+
16+
# 3. Calculate "Negative Budget"
17+
# This is the sum of the subset of numbers we must flip to negative
18+
negative_budget = diff // 2
19+
20+
is_negative = [False] * (n + 1)
21+
22+
# 4. Greedy Selection: Pick largest numbers first
23+
for i in range(n, 0, -1):
24+
if i <= negative_budget:
25+
is_negative[i] = True
26+
negative_budget -= i
27+
28+
# Safety check: If we couldn't spend the full budget, it's impossible
29+
# (Though with the bounds check above, this is mathematically guaranteed for 1..n)
30+
if negative_budget != 0:
31+
return []
32+
33+
res = []
34+
for i in range(1, n + 1):
35+
if is_negative[i]:
36+
res.append(-i)
37+
else:
38+
res.append(i)
39+
40+
# 5. Sort to ensure lexicographically smallest order
41+
res.sort()
42+
43+
return res
44+

0 commit comments

Comments
 (0)