The problem asks us to split a string into at least two parts where each consecutive part represents a number that is exactly one less than the previous. Since we need to explore all possible ways to split the string, backtracking is a natural choice. We try every possible split point, build numbers digit by digit, and check if they form a valid descending consecutive sequence.
isValid that checks if a list of numbers forms a descending consecutive sequence (each element is exactly one less than the previous) and contains at least two elements.0 with an empty list of splits.true.class Solution:
def splitString(self, s: str) -> bool:
n = len(s)
def isValid(splits):
for i in range(1, len(splits)):
if splits[i] != splits[i - 1] - 1:
return False
return len(splits) > 1
def dfs(i, splits):
if i == n:
return isValid(splits)
num = 0
for j in range(i, n):
num = num * 10 + int(s[j])
splits.append(num)
if dfs(j + 1, splits):
return True
splits.pop()
return False
return dfs(0, [])Instead of collecting all splits and validating at the end, we can optimize by passing the previous number directly. Once we fix the first number, we only need to find subsequent numbers that are exactly one less. This eliminates the need to store all splits and allows early termination when we find a valid sequence.
dfs with the remaining string and the first number as the previous value.dfs, try to form numbers from the current position. If a number equals prev - 1, recursively check the rest.true if any starting number leads to a valid sequence.class Solution:
def splitString(self, s: str) -> bool:
def dfs(index, prev):
if index == len(s):
return True
num = 0
for j in range(index, len(s)):
num = num * 10 + int(s[j])
if num + 1 == prev and dfs(j + 1, num):
return True
return False
val = 0
for i in range(len(s) - 1):
val = val * 10 + int(s[i])
if dfs(i + 1, val):
return True
return FalseBuilding on the previous approach, we add an important pruning optimization. Since we need descending consecutive values, once the current number we are building becomes greater than or equal to the previous number, there is no point continuing to add more digits. This early termination significantly reduces the search space.
dfs, build numbers digit by digit from the current position.prev - 1, recursively check the remaining string.prev, break out of the loop early since adding more digits will only make it larger.true when the end of string is reached with a valid sequence.class Solution:
def splitString(self, s: str) -> bool:
def dfs(index, prev):
if index == len(s):
return True
num = 0
for j in range(index, len(s)):
num = num * 10 + int(s[j])
if num + 1 == prev and dfs(j + 1, num):
return True
if num >= prev:
break
return False
val = 0
for i in range(len(s) - 1):
val = val * 10 + int(s[i])
if dfs(i + 1, val):
return True
return FalseInstead of using recursion with the call stack, we can simulate the same process with an explicit stack. This converts the recursive solution into an iterative one, which can be useful for avoiding stack overflow on very deep recursions and makes the state transitions more explicit.
prev - 1:true.prev, stop building.false.class Solution:
def splitString(self, s: str) -> bool:
n = len(s)
stack = []
val = 0
for i in range(n - 1):
val = val * 10 + int(s[i])
stack.append((i + 1, val))
while stack:
index, prev = stack.pop()
num = 0
for j in range(index, n):
num = num * 10 + int(s[j])
if num + 1 == prev:
if j + 1 == n:
return True
stack.append((j + 1, num))
elif num >= prev:
break
return FalseThe string can be up to 20 characters long, meaning numbers can exceed 64-bit integer limits. Using int or even standard long without considering overflow can produce incorrect comparisons. Use unsigned long long or language-specific big integer handling, and be cautious when building numbers digit by digit.
The problem requires splitting into at least two parts. A common mistake is returning true when the entire string forms a single number. Always ensure the loop for the first number excludes the last character, forcing at least one more part to exist.
Without early termination when the current number exceeds or equals the previous number, the solution explores many unnecessary branches. Since we need strictly descending consecutive values, once num >= prev, no valid sequence can be formed by adding more digits, so breaking out of the loop is essential for efficiency.