3461. Check If Digits Are Equal in String After Operations I
Problem Description
You are given a string s
that contains only digits. Your task is to repeatedly perform a specific operation on this string until it has exactly two digits remaining.
The operation works as follows:
- Starting from the first digit, look at each pair of consecutive digits in the string
- For each pair, calculate the sum of the two digits and take the result modulo 10 (this gives you the last digit of the sum)
- Create a new string using all these calculated digits in the order they were computed
- Replace the original string with this new string
You keep repeating this process until the string is reduced to exactly two digits.
Once you have exactly two digits remaining, return true
if both digits are the same, and false
otherwise.
For example, if you start with "123"
:
- First iteration: pairs are (1,2) and (2,3), giving us
(1+2)%10 = 3
and(2+3)%10 = 5
, resulting in"35"
- The string now has 2 digits, so we stop
- Since 3 ≠ 5, we return
false
The solution uses a clever approach with nested loops. The outer loop controls how many iterations are needed (from n-1
down to 2), while the inner loop performs the modulo sum operation on consecutive pairs. By working directly with the array and updating values in place, it efficiently reduces the string to two digits and then compares them.
Intuition
The key insight is recognizing that each iteration reduces the number of digits by exactly 1. If we start with n
digits, after one iteration we'll have n-1
digits, after two iterations we'll have n-2
digits, and so on. This means we need exactly n-2
iterations to reduce an n
-digit string down to 2 digits.
Rather than creating a new array or string for each iteration, we can optimize by reusing the same array. The pattern becomes clear when we visualize what happens:
- In the first iteration, we compute
n-1
new values fromn
original values - In the second iteration, we compute
n-2
new values from then-1
values we just calculated - This continues until we have just 2 values left
The clever part is realizing we can overwrite the array from left to right during each iteration. When computing t[i] = (t[i] + t[i+1]) % 10
, we're done using the original value of t[i]
, so we can safely replace it with the new value. This in-place modification saves space and simplifies the code.
The outer loop for k in range(n-1, 1, -1)
controls how many values we compute in each iteration - starting with n-1
pairs in the first iteration, then n-2
pairs in the second, and so on. The inner loop for i in range(k)
performs the actual computation for each pair in that iteration.
After all iterations complete, the first two positions of our array contain the final two digits, so we simply check if t[0] == t[1]
to determine our answer.
Learn more about Math and Combinatorics patterns.
Solution Approach
The solution implements a simulation approach that directly manipulates the input string as a list of integers. Here's how the implementation works:
First, we convert the string s
into a list of integers: t = list(map(int, s))
. This allows us to work with numerical values directly rather than converting characters repeatedly.
We store the length n = len(t)
to determine how many iterations we need to perform.
The core logic uses nested loops:
- The outer loop
for k in range(n - 1, 1, -1):
controls the number of iterations. It starts fromn-1
and counts down to2
. The variablek
represents how many new digits we'll compute in each iteration. - The inner loop
for i in range(k):
iterates through each position where we need to compute a new digit.
In each inner loop iteration, we perform the key operation: t[i] = (t[i] + t[i + 1]) % 10
. This:
- Takes the current digit at position
i
and the next digit at positioni+1
- Adds them together
- Takes the result modulo 10 to get the last digit
- Stores this new value back at position
i
The beauty of this approach is that we're reusing the same array throughout all iterations. After the first iteration, positions 0
through n-2
contain our new values, and we ignore position n-1
. After the second iteration, positions 0
through n-3
contain the newer values, and so on.
When both loops complete, we're guaranteed to have exactly 2 digits stored in positions t[0]
and t[1]
. We simply return t[0] == t[1]
to check if they're the same.
The time complexity is O(n²)
where n
is the length of the input string, as we perform roughly (n-1) + (n-2) + ... + 2
operations total. The space complexity is O(n)
for storing the list of digits.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the solution with the string s = "4321"
.
Initial Setup:
- Convert string to integer list:
t = [4, 3, 2, 1]
- Length
n = 4
- We need
n-2 = 2
iterations to reduce to 2 digits
First Iteration (k = 3):
- We compute 3 new values (indices 0, 1, 2)
i = 0
:t[0] = (4 + 3) % 10 = 7
→t = [7, 3, 2, 1]
i = 1
:t[1] = (3 + 2) % 10 = 5
→t = [7, 5, 2, 1]
i = 2
:t[2] = (2 + 1) % 10 = 3
→t = [7, 5, 3, 1]
- After this iteration, we have 3 valid digits:
[7, 5, 3]
(ignore index 3)
Second Iteration (k = 2):
- We compute 2 new values (indices 0, 1)
i = 0
:t[0] = (7 + 5) % 10 = 2
→t = [2, 5, 3, 1]
i = 1
:t[1] = (5 + 3) % 10 = 8
→t = [2, 8, 3, 1]
- After this iteration, we have 2 valid digits:
[2, 8]
(ignore indices 2 and 3)
Final Check:
- Compare
t[0]
andt[1]
:2 ≠ 8
- Return
false
The key insight is how we reuse the same array throughout, only caring about the first k
positions in each iteration, where k
decreases by 1 each time. This eliminates the need to create new arrays and makes the solution both space and implementation efficient.
Solution Implementation
1class Solution:
2 def hasSameDigits(self, s: str) -> bool:
3 # Convert string of digits to list of integers
4 digits = list(map(int, s))
5 n = len(digits)
6
7 # Perform triangular reduction
8 # Each iteration reduces the effective array size by 1
9 # We stop when only 2 elements remain (k = 1)
10 for k in range(n - 1, 1, -1):
11 # Update first k elements by adding adjacent pairs
12 for i in range(k):
13 digits[i] = (digits[i] + digits[i + 1]) % 10
14
15 # Check if the final two elements are equal
16 return digits[0] == digits[1]
17
1class Solution {
2 /**
3 * Determines if a string of digits has a specific property after triangular reduction.
4 * The algorithm repeatedly replaces each adjacent pair of digits with their sum modulo 10,
5 * reducing the array size by 1 each iteration until only 2 elements remain.
6 *
7 * @param s A string consisting of digit characters
8 * @return true if the final two digits are equal, false otherwise
9 */
10 public boolean hasSameDigits(String s) {
11 // Convert the input string to a character array for manipulation
12 char[] digitArray = s.toCharArray();
13 int arrayLength = digitArray.length;
14
15 // Perform triangular reduction
16 // Start from the last position and work backwards to position 1
17 // This ensures we end up with exactly 2 elements
18 for (int currentLength = arrayLength - 1; currentLength > 1; --currentLength) {
19 // For each iteration, compute new values for positions 0 to currentLength-1
20 // Each new value is the sum of adjacent digits modulo 10
21 for (int position = 0; position < currentLength; ++position) {
22 // Calculate sum of current digit and next digit
23 int currentDigit = digitArray[position] - '0';
24 int nextDigit = digitArray[position + 1] - '0';
25 int sumModTen = (currentDigit + nextDigit) % 10;
26
27 // Store the result back as a character
28 digitArray[position] = (char) (sumModTen + '0');
29 }
30 }
31
32 // Check if the final two remaining digits are equal
33 return digitArray[0] == digitArray[1];
34 }
35}
36
1class Solution {
2public:
3 bool hasSameDigits(string s) {
4 int stringLength = s.size();
5 string workingString = s; // Create a copy to modify
6
7 // Perform triangular reduction from the end to position 2
8 // Each iteration reduces the effective array size by 1
9 for (int currentLength = stringLength - 1; currentLength > 1; --currentLength) {
10 // For each position up to currentLength, replace the digit
11 // with the sum of itself and the next digit (mod 10)
12 for (int position = 0; position < currentLength; ++position) {
13 // Convert characters to digits, add them, take mod 10, convert back to char
14 int currentDigit = workingString[position] - '0';
15 int nextDigit = workingString[position + 1] - '0';
16 int sumModTen = (currentDigit + nextDigit) % 10;
17 workingString[position] = sumModTen + '0';
18 }
19 }
20
21 // After reduction, check if the first two remaining digits are equal
22 return workingString[0] == workingString[1];
23 }
24};
25
1/**
2 * Checks if a numeric string satisfies a specific digit transformation property
3 * by repeatedly applying modulo 10 addition operations in a triangular pattern
4 * @param s - Input string containing numeric digits
5 * @returns true if the final two values are equal after transformation, false otherwise
6 */
7function hasSameDigits(s: string): boolean {
8 // Convert string to array of numbers by splitting each character and parsing as integer
9 const digits: number[] = s.split('').map(Number);
10
11 // Store the length of the digits array
12 const length: number = digits.length;
13
14 // Perform triangular reduction: start from the second-to-last position
15 // and work backwards, reducing the array size by one in each iteration
16 for (let currentLevel = length - 1; currentLevel > 1; --currentLevel) {
17 // For each level, update elements by adding adjacent pairs
18 for (let index = 0; index < currentLevel; ++index) {
19 // Replace current element with sum of itself and next element, modulo 10
20 digits[index] = (digits[index] + digits[index + 1]) % 10;
21 }
22 }
23
24 // After all transformations, check if the first two elements are equal
25 return digits[0] === digits[1];
26}
27
Time and Space Complexity
The time complexity is O(n^2)
, where n
is the length of the string s
. This is because we have two nested loops: the outer loop runs from n-1
down to 2
(approximately n-2
iterations), and for each iteration k
, the inner loop runs k
times. The total number of operations is approximately (n-1) + (n-2) + ... + 2 = (n-1) * (n-2) / 2
, which simplifies to O(n^2)
.
The space complexity is O(n)
, where n
is the length of the string s
. This is due to the conversion of the string to a list of integers t = list(map(int, s))
, which creates a new list of size n
. The algorithm then modifies this list in-place without using any additional space that scales with the input size.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Off-by-One Error in Loop Boundaries
The Pitfall: A common mistake is incorrectly setting the loop boundaries, particularly in the outer loop. Developers might write:
range(n, 1, -1)
instead ofrange(n-1, 1, -1)
- This would cause an index out of bounds errorrange(n-1, 0, -1)
instead ofrange(n-1, 1, -1)
- This would perform one extra unnecessary iteration
Why it happens: The confusion arises from not clearly understanding that in each iteration, we're computing k
new values from k+1
existing values. When we have n
digits initially, we can only compute n-1
new values.
Solution: Remember that:
- The outer loop variable
k
represents the number of new digits we're computing - We start with
n
digits, so we can compute at mostn-1
new values - We stop when
k=2
(notk=1
) because we need exactly 2 digits remaining
2. Modifying the Wrong Data Structure
The Pitfall: Creating a new list for each iteration instead of modifying in-place:
for k in range(n - 1, 1, -1):
new_digits = [] # Creating new list each time
for i in range(k):
new_digits.append((digits[i] + digits[i + 1]) % 10)
digits = new_digits # Reassigning
Why it happens: This approach seems more intuitive but is less efficient and can lead to errors if the indexing isn't adjusted properly for the shrinking list size.
Solution: Stick with in-place modification. The original approach cleverly reuses the same array, only updating the positions that matter for the next iteration.
3. Forgetting the Modulo Operation
The Pitfall: Writing digits[i] = digits[i] + digits[i + 1]
without the % 10
operation.
Why it happens: The problem description mentions "sum of two digits" which might lead developers to forget that we only want the last digit of the sum.
Solution: Always include % 10
to ensure we're storing only single digits. For example, if we have digits 7 and 8, their sum is 15, but we want to store 5 (15 % 10 = 5).
4. Incorrect Final Comparison
The Pitfall: Accessing the wrong indices for the final comparison, such as:
return digits[0] == digits[n-1]
- This would compare with an outdated valuereturn digits[1] == digits[2]
- Wrong indices entirely
Why it happens: After all the iterations, it's easy to lose track of where the final two values are stored.
Solution: The final two values are always at indices 0 and 1 after the reduction process completes. The algorithm overwrites the array from left to right, so digits[0]
and digits[1]
contain our final result.
What is the best way of checking if an element exists in a sorted array once in terms of time complexity? Select the best that applies.
Recommended Readings
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
Backtracking Template Prereq DFS with States problems dfs_with_states Combinatorial search problems Combinatorial search problems involve finding groupings and assignments of objects that satisfy certain conditions Finding all permutations combinations subsets and solving Sudoku are classic combinatorial problems The time complexity of combinatorial problems often grows rapidly with the size of
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Want a Structured Path to Master System Design Too? Don’t Miss This!