Missing undo step on backtrack
Wrong move: Mutable state leaks between branches.
Usually fails on: Later branches inherit selections from earlier branches.
Fix: Always revert state changes immediately after recursive call.
Move from brute-force thinking to an efficient approach using backtracking strategy.
You are given a string s that consists of only digits.
Check if we can split s into two or more non-empty substrings such that the numerical values of the substrings are in descending order and the difference between numerical values of every two adjacent substrings is equal to 1.
s = "0090089" can be split into ["0090", "089"] with numerical values [90,89]. The values are in descending order and adjacent values differ by 1, so this way is valid.s = "001" can be split into ["0", "01"], ["00", "1"], or ["0", "0", "1"]. However all the ways are invalid because they have numerical values [0,1], [0,1], and [0,0,1] respectively, all of which are not in descending order.Return true if it is possible to split s as described above, or false otherwise.
A substring is a contiguous sequence of characters in a string.
Example 1:
Input: s = "1234" Output: false Explanation: There is no valid way to split s.
Example 2:
Input: s = "050043" Output: true Explanation: s can be split into ["05", "004", "3"] with numerical values [5,4,3]. The values are in descending order with adjacent values differing by 1.
Example 3:
Input: s = "9080701" Output: false Explanation: There is no valid way to split s.
Constraints:
1 <= s.length <= 20s only consists of digits.Problem summary: You are given a string s that consists of only digits. Check if we can split s into two or more non-empty substrings such that the numerical values of the substrings are in descending order and the difference between numerical values of every two adjacent substrings is equal to 1. For example, the string s = "0090089" can be split into ["0090", "089"] with numerical values [90,89]. The values are in descending order and adjacent values differ by 1, so this way is valid. Another example, the string s = "001" can be split into ["0", "01"], ["00", "1"], or ["0", "0", "1"]. However all the ways are invalid because they have numerical values [0,1], [0,1], and [0,0,1] respectively, all of which are not in descending order. Return true if it is possible to split s as described above, or false otherwise. A substring is a contiguous sequence of characters in a string.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Backtracking
"1234"
"050043"
"9080701"
Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #1849: Splitting a String Into Descending Consecutive Values
class Solution {
private char[] s;
public boolean splitString(String s) {
this.s = s.toCharArray();
return dfs(0, -1);
}
private boolean dfs(int i, long x) {
if (i >= s.length) {
return true;
}
long y = 0;
int r = x < 0 ? s.length - 1 : s.length;
for (int j = i; j < r; ++j) {
y = y * 10 + s[j] - '0';
if ((x < 0 || x - y == 1) && dfs(j + 1, y)) {
return true;
}
}
return false;
}
}
// Accepted solution for LeetCode #1849: Splitting a String Into Descending Consecutive Values
func splitString(s string) bool {
var dfs func(i, x int) bool
dfs = func(i, x int) bool {
if i >= len(s) {
return true
}
y := 0
r := len(s)
if x < 0 {
r--
}
for j := i; j < r; j++ {
y = y*10 + int(s[j]-'0')
if (x < 0 || x-y == 1) && dfs(j+1, y) {
return true
}
}
return false
}
return dfs(0, -1)
}
# Accepted solution for LeetCode #1849: Splitting a String Into Descending Consecutive Values
class Solution:
def splitString(self, s: str) -> bool:
def dfs(i: int, x: int) -> bool:
if i >= len(s):
return True
y = 0
r = len(s) - 1 if x < 0 else len(s)
for j in range(i, r):
y = y * 10 + int(s[j])
if (x < 0 or x - y == 1) and dfs(j + 1, y):
return True
return False
return dfs(0, -1)
// Accepted solution for LeetCode #1849: Splitting a String Into Descending Consecutive Values
/**
* [1849] Splitting a String Into Descending Consecutive Values
*
* You are given a string s that consists of only digits.
* Check if we can split s into two or more non-empty substrings such that the numerical values of the substrings are in descending order and the difference between numerical values of every two adjacent substrings is equal to 1.
*
* For example, the string s = "0090089" can be split into ["0090", "089"] with numerical values [90,89]. The values are in descending order and adjacent values differ by 1, so this way is valid.
* Another example, the string s = "001" can be split into ["0", "01"], ["00", "1"], or ["0", "0", "1"]. However all the ways are invalid because they have numerical values [0,1], [0,1], and [0,0,1] respectively, all of which are not in descending order.
*
* Return true if it is possible to split s as described above, or false otherwise.
* A substring is a contiguous sequence of characters in a string.
*
* Example 1:
*
* Input: s = "1234"
* Output: false
* Explanation: There is no valid way to split s.
*
* Example 2:
*
* Input: s = "050043"
* Output: true
* Explanation: s can be split into ["05", "004", "3"] with numerical values [5,4,3].
* The values are in descending order with adjacent values differing by 1.
*
* Example 3:
*
* Input: s = "9080701"
* Output: false
* Explanation: There is no valid way to split s.
*
*
* Constraints:
*
* 1 <= s.length <= 20
* s only consists of digits.
*
*/
pub struct Solution {}
// problem: https://leetcode.com/problems/splitting-a-string-into-descending-consecutive-values/
// discuss: https://leetcode.com/problems/splitting-a-string-into-descending-consecutive-values/discuss/?currentPage=1&orderBy=most_votes&query=
// submission codes start here
impl Solution {
pub fn split_string(s: String) -> bool {
false
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[ignore]
fn test_1849_example_1() {
let s = "1234".to_string();
let result = false;
assert_eq!(Solution::split_string(s), result);
}
#[test]
#[ignore]
fn test_1849_example_2() {
let s = "050043".to_string();
let result = true;
assert_eq!(Solution::split_string(s), result);
}
#[test]
#[ignore]
fn test_1849_example_3() {
let s = "9080701".to_string();
let result = false;
assert_eq!(Solution::split_string(s), result);
}
}
// Accepted solution for LeetCode #1849: Splitting a String Into Descending Consecutive Values
function splitString(s: string): boolean {
const dfs = (i: number, x: number): boolean => {
if (i >= s.length) {
return true;
}
let y = 0;
const r = x < 0 ? s.length - 1 : s.length;
for (let j = i; j < r; ++j) {
y = y * 10 + +s[j];
if ((x < 0 || x - y === 1) && dfs(j + 1, y)) {
return true;
}
}
return false;
};
return dfs(0, -1);
}
Use this to step through a reusable interview workflow for this problem.
Generate every possible combination without any filtering. At each of n positions we choose from up to n options, giving nⁿ total candidates. Each candidate takes O(n) to validate. No pruning means we waste time on clearly invalid partial solutions.
Backtracking explores a decision tree, but prunes branches that violate constraints early. Worst case is still factorial or exponential, but pruning dramatically reduces the constant factor in practice. Space is the recursion depth (usually O(n) for n-level decisions).
Review these before coding to avoid predictable interview regressions.
Wrong move: Mutable state leaks between branches.
Usually fails on: Later branches inherit selections from earlier branches.
Fix: Always revert state changes immediately after recursive call.