3438. Find Valid Pair of Adjacent Digits in String
Problem Description
You are given a string s
that contains only digit characters (0-9). Your task is to find a valid pair of digits in the string.
A valid pair is defined as two adjacent digits in the string that satisfy both of these conditions:
- The two digits must be different from each other (not equal)
- Each digit in the pair must appear in the entire string
s
exactly as many times as its numeric value
For example:
- The digit
3
would need to appear exactly 3 times in the string - The digit
5
would need to appear exactly 5 times in the string - The digit
0
would need to appear exactly 0 times (meaning it shouldn't exist in the string at all)
You need to traverse the string from left to right and return the first valid pair you find. The pair should be returned as a string containing the two adjacent digits.
If no valid pair exists in the entire string, return an empty string ""
.
The solution approach counts the frequency of each digit (0-9) in the string using an array cnt
. Then it checks each pair of adjacent digits using pairwise
to see if they form a valid pair. A pair (x, y)
is valid when x ≠ y
and cnt[x] == x
and cnt[y] == y
. The first such valid pair found is returned as a string f"{x}{y}"
, otherwise an empty string is returned.
Intuition
The key insight is that we need to check two conditions for each adjacent pair: the digits must be different, and each digit must appear in the string exactly as many times as its numeric value.
To efficiently check the second condition, we can preprocess the string by counting how many times each digit appears. This way, when we examine any adjacent pair, we can immediately know if each digit satisfies the frequency requirement without having to count again.
Why count first? If we tried to count the frequency of digits for each adjacent pair separately, we would be doing redundant work - counting the same digits over and over again. Since the frequency of each digit is fixed for the entire string, we can count once at the beginning and reuse this information.
The natural approach then becomes:
- First, count the frequency of all digits (0-9) in the string - this takes one pass through the string
- Then, iterate through all adjacent pairs from left to right - another pass through the string
- For each pair
(x, y)
, check ifx ≠ y
(different digits) and ifcnt[x] == x
andcnt[y] == y
(frequency matches numeric value) - Return the first pair that satisfies both conditions
This approach is efficient because we only need two passes through the string - one for counting and one for checking pairs. The checking step is O(1)
for each pair since we're just looking up precomputed values in our frequency array.
Solution Approach
The implementation follows a straightforward counting and validation approach:
Step 1: Count digit frequencies
cnt = [0] * 10
for x in map(int, s):
cnt[x] += 1
We create an array cnt
of size 10 (for digits 0-9) initialized with zeros. Then we iterate through each character in the string s
, convert it to an integer using map(int, s)
, and increment the corresponding counter. After this step, cnt[i]
contains the total number of times digit i
appears in the string.
Step 2: Check adjacent pairs
for x, y in pairwise(map(int, s)):
if x != y and cnt[x] == x and cnt[y] == y:
return f"{x}{y}"
We use the pairwise
function to iterate through consecutive pairs of digits. The pairwise
function takes an iterable and returns consecutive overlapping pairs. For example, if s = "1234"
, then pairwise(map(int, s))
yields (1,2)
, (2,3)
, (3,4)
.
For each pair (x, y)
, we check three conditions:
x != y
: The two digits must be differentcnt[x] == x
: The first digit appears exactly as many times as its numeric valuecnt[y] == y
: The second digit appears exactly as many times as its numeric value
If all three conditions are satisfied, we immediately return the pair as a string using f-string formatting: f"{x}{y}"
.
Step 3: Return empty string if no valid pair found
return ""
If we complete the iteration without finding any valid pair, we return an empty string.
The time complexity is O(n)
where n
is the length of the string, as we make two passes through the string. The space complexity is O(1)
since the cnt
array has a fixed size of 10 regardless of input size.
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 = "21233"
.
Step 1: Count digit frequencies
First, we count how many times each digit appears in the string:
- Digit '2' appears 2 times
- Digit '1' appears 1 time
- Digit '3' appears 2 times
Our frequency array becomes: cnt = [0, 1, 2, 2, 0, 0, 0, 0, 0, 0]
cnt[1] = 1
(digit 1 appears once)cnt[2] = 2
(digit 2 appears twice)cnt[3] = 2
(digit 3 appears twice)
Step 2: Check adjacent pairs from left to right
Now we examine each adjacent pair:
- Pair "21" (digits 2 and 1):
- Are they different? Yes, 2 ≠ 1 ✓
- Does digit 2 appear exactly 2 times? Yes,
cnt[2] = 2
✓ - Does digit 1 appear exactly 1 time? Yes,
cnt[1] = 1
✓ - All conditions satisfied! Return "21"
We found a valid pair immediately, so we return "21" without checking the remaining pairs.
For completeness, let's see what would happen if we continued:
- Pair "12": 1 ≠ 2,
cnt[1] = 1
(valid), butcnt[2] = 2
(valid) → Would be valid - Pair "23": 2 ≠ 3,
cnt[2] = 2
(valid), butcnt[3] = 2
(not equal to 3) → Invalid - Pair "33": 3 = 3 → Invalid (same digits)
The algorithm correctly returns "21" as the first valid pair found when traversing from left to right.
Solution Implementation
1from itertools import pairwise
2
3class Solution:
4 def findValidPair(self, s: str) -> str:
5 # Count frequency of each digit (0-9) in the string
6 digit_count = [0] * 10
7 for digit in map(int, s):
8 digit_count[digit] += 1
9
10 # Check consecutive pairs of digits in the string
11 for first_digit, second_digit in pairwise(map(int, s)):
12 # Valid pair conditions:
13 # 1. The two digits must be different
14 # 2. First digit's count must equal its value
15 # 3. Second digit's count must equal its value
16 if (first_digit != second_digit and
17 digit_count[first_digit] == first_digit and
18 digit_count[second_digit] == second_digit):
19 # Return the valid pair as a string
20 return f"{first_digit}{second_digit}"
21
22 # No valid pair found
23 return ""
24
1class Solution {
2 /**
3 * Finds a valid pair of adjacent digits in the string where each digit's value
4 * equals its frequency count in the entire string.
5 *
6 * @param s the input string containing only digit characters
7 * @return a substring of length 2 representing the valid pair, or empty string if none exists
8 */
9 public String findValidPair(String s) {
10 // Array to store the frequency count of each digit (0-9)
11 int[] digitFrequency = new int[10];
12
13 // Count the frequency of each digit in the string
14 for (char c : s.toCharArray()) {
15 digitFrequency[c - '0']++;
16 }
17
18 // Check each pair of adjacent digits
19 for (int i = 1; i < s.length(); i++) {
20 // Get the numeric value of the current pair of adjacent digits
21 int firstDigit = s.charAt(i - 1) - '0';
22 int secondDigit = s.charAt(i) - '0';
23
24 // Check if the pair satisfies the conditions:
25 // 1. The two digits are different
26 // 2. The first digit's value equals its frequency count
27 // 3. The second digit's value equals its frequency count
28 if (firstDigit != secondDigit &&
29 digitFrequency[firstDigit] == firstDigit &&
30 digitFrequency[secondDigit] == secondDigit) {
31 // Return the valid pair as a substring
32 return s.substring(i - 1, i + 1);
33 }
34 }
35
36 // Return empty string if no valid pair is found
37 return "";
38 }
39}
40
1class Solution {
2public:
3 string findValidPair(string s) {
4 // Initialize frequency array to count occurrences of each digit (0-9)
5 int digitFrequency[10] = {0};
6
7 // Count the frequency of each digit in the string
8 for (char c : s) {
9 digitFrequency[c - '0']++;
10 }
11
12 // Iterate through consecutive pairs of digits in the string
13 for (int i = 1; i < s.size(); i++) {
14 // Extract the two consecutive digits
15 int firstDigit = s[i - 1] - '0';
16 int secondDigit = s[i] - '0';
17
18 // Check if the pair meets the criteria:
19 // 1. The two digits are different
20 // 2. The frequency of the first digit equals its value
21 // 3. The frequency of the second digit equals its value
22 if (firstDigit != secondDigit &&
23 digitFrequency[firstDigit] == firstDigit &&
24 digitFrequency[secondDigit] == secondDigit) {
25 // Return the valid pair as a substring of length 2
26 return s.substr(i - 1, 2);
27 }
28 }
29
30 // Return empty string if no valid pair is found
31 return "";
32 }
33};
34
1/**
2 * Finds a valid pair of adjacent digits in a string where each digit's value
3 * equals its frequency count in the entire string.
4 *
5 * @param s - Input string containing digits
6 * @returns A string containing the first valid pair found, or empty string if none exists
7 */
8function findValidPair(s: string): string {
9 // Initialize frequency counter array for digits 0-9
10 const digitFrequency: number[] = Array(10).fill(0);
11
12 // Count the frequency of each digit in the string
13 for (const char of s) {
14 digitFrequency[Number(char)]++;
15 }
16
17 // Check each adjacent pair of digits
18 for (let i = 1; i < s.length; i++) {
19 // Get the numeric values of the current and previous digits
20 const previousDigit: number = Number(s[i - 1]);
21 const currentDigit: number = Number(s[i]);
22
23 // Check if the pair is valid:
24 // 1. Digits must be different
25 // 2. Each digit's value must equal its frequency in the string
26 if (previousDigit !== currentDigit &&
27 digitFrequency[previousDigit] === previousDigit &&
28 digitFrequency[currentDigit] === currentDigit) {
29 // Return the valid pair as a string
30 return `${previousDigit}${currentDigit}`;
31 }
32 }
33
34 // No valid pair found
35 return '';
36}
37
Time and Space Complexity
The time complexity is O(n)
, where n
is the length of the string s
. This is because:
- The first loop iterates through all characters in
s
to count digit frequencies:O(n)
- The second loop uses
pairwise
to iterate through consecutive pairs of digits ins
, which results inn-1
iterations:O(n)
- Inside the second loop, all operations (comparisons and dictionary lookups) are
O(1)
- Therefore, the overall time complexity is
O(n) + O(n) = O(n)
The space complexity is O(|Σ|)
, where Σ
is the character set of the string s
. In this problem, Σ = {0, 1, 2, ..., 9}
, so |Σ| = 10
. This is because:
- The
cnt
array has a fixed size of 10 to store the frequency of each digit:O(10) = O(1)
- The
pairwise
iterator andmap
functions useO(1)
additional space as they process elements one at a time - Since the size of the character set is constant (10 digits), the space complexity is
O(|Σ|)
or equivalentlyO(1)
for this specific problem
Learn more about how to find time and space complexity quickly.
Common Pitfalls
Pitfall 1: Misunderstanding the digit '0' requirement
A common mistake is not properly handling the digit '0'. According to the problem, if a digit's value is 0, it must appear exactly 0 times in the string. This means the digit '0' cannot exist in the string at all for it to be part of a valid pair.
Incorrect assumption: Some might think that having zero '0's in the string automatically satisfies the condition for '0'.
The issue: If '0' appears in a pair position (like "10" or "01"), the validation digit_count[0] == 0
would return True
if there are no '0's in the string. But this is contradictory - we're checking a '0' that exists in the pair while requiring it doesn't exist at all.
Solution: The current implementation actually handles this correctly! When we encounter a '0' in a pair during iteration, digit_count[0]
will be at least 1 (since we counted it), so the condition digit_count[0] == 0
will be False
, correctly rejecting any pair containing '0'.
Pitfall 2: Early termination without checking all pairs
Some might be tempted to optimize by stopping early once they find digits that individually satisfy their count requirements.
Example of incorrect optimization:
# WRONG: Don't do this
valid_digits = set()
for i in range(10):
if digit_count[i] == i:
valid_digits.add(i)
# Then trying to find pairs only from valid_digits
The issue: This approach misses the adjacency requirement. Even if digits '2' and '3' both appear the correct number of times, they might never be adjacent in the string.
Solution: Stick to the original approach of checking each adjacent pair in order. The validation must happen on actual adjacent pairs, not just on digits that meet the frequency requirement.
Pitfall 3: Using the wrong iteration method for pairs
Attempting to manually iterate through pairs using indices can lead to off-by-one errors.
Error-prone approach:
# Risky: Manual index management
for i in range(len(s) - 1):
x = int(s[i])
y = int(s[i + 1])
# ... validation logic
The issue: While this works, it's more error-prone. Forgetting the - 1
in the range would cause an index out of bounds error.
Solution: Use pairwise
from itertools as shown in the original solution. It's cleaner, more readable, and less prone to boundary errors. If pairwise
is not available (Python < 3.10), you can use zip(s, s[1:])
as an alternative:
# Alternative for older Python versions
for x, y in zip(map(int, s), map(int, s[1:])):
if x != y and digit_count[x] == x and digit_count[y] == y:
return f"{x}{y}"
Which of the following shows the order of node visit in a Breadth-first Search?
Recommended Readings
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
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!