Splitting a String Into Descending Consecutive Values — Medium Problem & Solution
s is a string of digits. Decide whether it can be cut into two or more non-empty consecutive pieces such that, reading each piece as a number, the values…
- Difficulty: Medium
- Topics: Strings, Backtracking, Enumeration
- Asked at: Amazon, Google
- Time limit: 2 s
- Memory limit: 256 MB
- Languages: JavaScript, TypeScript, Python, Java, C++, C, C#, Go, Kotlin, Swift, Rust, PHP and Ruby
Problem statement
s is a string of digits. Decide whether it can be cut into two or more non-empty consecutive pieces such that, reading each piece as a number, the values strictly decrease by exactly 1 from one piece to the next.
Pieces may have leading zeros — "004" is read as 4. Return true if such a split exists.
Example 1
Input: s = "050043"
Output: true
Explanation: `"05"`, `"004"`, `"3"` read as 5, 4, 3.
Example 2
Input: s = "1234"
Output: false
Explanation: The values would have to decrease, but every split increases.
Example 3
Input: s = "10009998"
Output: true
Explanation: `"100"`, `"099"`, `"98"`.
Constraints
1 <= s.length <= 20s consists only of digits
How to solve Splitting a String Into Descending Consecutive Values
The first value determines the whole sequence. For each choice of first piece, scan the remainder and match the next expected value; prefixes only grow, so each check stops early.
Approach
- For every end
iof the first piece withi < n - 1, accumulate its valuefirst(stop once it reaches 10^10). dfs(start, prev): ifstart == n, succeed. Otherwise extend a piececurfromstartdigit by digit; ifcur >= prev, stop; ifcur == prev - 1, trydfs(j + 1, cur).- Return true when any first piece leads to success.
Why it works
A valid split is fully described by its first piece, and the pruning only discards pieces whose value is already at least prev — adding digits never decreases a value, so those can never equal prev - 1. If the first value has d significant digits, the next one needs at least d - 1, so 2d - 1 <= 20 and the first value is below 10^10, which keeps every quantity inside 64 bits.
Complexity
- Time —
O(n^2) per first piece, O(n^3) overall (n ≤ 20) - Space —
O(n) recursion depth
Pitfalls
- At least two pieces are required: the whole string on its own does not count.
- Leading zeros are allowed, so
"0090089"-style pieces are legal; do not reject them. - Parsing a 20-digit piece into a 64-bit integer overflows — prune by value before it gets that large.
Reference solution
Python
def splitString(s: str) -> bool:
n = len(s)
limit = 10 ** 10
def dfs(start, prev):
if start == n:
return True
cur = 0
for j in range(start, n):
cur = cur * 10 + ord(s[j]) - 48
if cur >= prev:
break
if cur == prev - 1 and dfs(j + 1, cur):
return True
return False
first = 0
for i in range(n - 1):
first = first * 10 + ord(s[i]) - 48
if first >= limit:
break
if dfs(i + 1, first):
return True
return FalseJavaScript
var splitString = function(s) {
var n = s.length;
var LIMIT = 10000000000;
var dfs = function(start, prev) {
if (start === n) return true;
var cur = 0;
for (var j = start; j < n; j++) {
cur = cur * 10 + (s.charCodeAt(j) - 48);
if (cur >= prev) break;
if (cur === prev - 1 && dfs(j + 1, cur)) return true;
}
return false;
};
var first = 0;
for (var i = 0; i < n - 1; i++) {
first = first * 10 + (s.charCodeAt(i) - 48);
if (first >= LIMIT) break;
if (dfs(i + 1, first)) return true;
}
return false;
};Also on the editorial tab: C, C#, C++, Go, Java, Kotlin, PHP, Ruby, Rust, Swift, TypeScript.
All 424 strings problems · the whole catalogue
Learn the technique: Strings · Backtracking