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 positive integer n.
A binary string x is valid if all substrings of x of length 2 contain at least one "1".
Return all valid strings with length n, in any order.
Example 1:
Input: n = 3
Output: ["010","011","101","110","111"]
Explanation:
The valid strings of length 3 are: "010", "011", "101", "110", and "111".
Example 2:
Input: n = 1
Output: ["0","1"]
Explanation:
The valid strings of length 1 are: "0" and "1".
Constraints:
1 <= n <= 18Problem summary: You are given a positive integer n. A binary string x is valid if all substrings of x of length 2 contain at least one "1". Return all valid strings with length n, in any order.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Backtracking · Bit Manipulation
3
1
non-negative-integers-without-consecutive-ones)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #3211: Generate Binary Strings Without Adjacent Zeros
class Solution {
private List<String> ans = new ArrayList<>();
private StringBuilder t = new StringBuilder();
private int n;
public List<String> validStrings(int n) {
this.n = n;
dfs(0);
return ans;
}
private void dfs(int i) {
if (i >= n) {
ans.add(t.toString());
return;
}
for (int j = 0; j < 2; ++j) {
if ((j == 0 && (i == 0 || t.charAt(i - 1) == '1')) || j == 1) {
t.append(j);
dfs(i + 1);
t.deleteCharAt(t.length() - 1);
}
}
}
}
// Accepted solution for LeetCode #3211: Generate Binary Strings Without Adjacent Zeros
func validStrings(n int) (ans []string) {
t := []byte{}
var dfs func(int)
dfs = func(i int) {
if i >= n {
ans = append(ans, string(t))
return
}
for j := 0; j < 2; j++ {
if (j == 0 && (i == 0 || t[i-1] == '1')) || j == 1 {
t = append(t, byte('0'+j))
dfs(i + 1)
t = t[:len(t)-1]
}
}
}
dfs(0)
return
}
# Accepted solution for LeetCode #3211: Generate Binary Strings Without Adjacent Zeros
class Solution:
def validStrings(self, n: int) -> List[str]:
def dfs(i: int):
if i >= n:
ans.append("".join(t))
return
for j in range(2):
if (j == 0 and (i == 0 or t[i - 1] == "1")) or j == 1:
t.append(str(j))
dfs(i + 1)
t.pop()
ans = []
t = []
dfs(0)
return ans
// Accepted solution for LeetCode #3211: Generate Binary Strings Without Adjacent Zeros
/**
* [3211] Generate Binary Strings Without Adjacent Zeros
*/
pub struct Solution {}
// submission codes start here
impl Solution {
pub fn valid_strings(n: i32) -> Vec<String> {
let n = n as usize;
let mut result = Vec::new();
let mut str = vec!['0'; n];
Self::dfs(0, false, &mut str, &mut result);
result
}
fn dfs(i: usize, last_zero: bool, str: &mut Vec<char>, result: &mut Vec<String>) {
if i >= str.len() {
result.push(str.iter().collect());
return;
}
if !last_zero {
str[i] = '0';
Self::dfs(i + 1, true, str, result);
}
str[i] = '1';
Self::dfs(i + 1, false, str, result);
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_3211() {
assert_eq!(
vec_string!("010", "011", "101", "110", "111"),
Solution::valid_strings(3)
);
assert_eq!(vec_string!("0", "1"), Solution::valid_strings(1));
}
}
// Accepted solution for LeetCode #3211: Generate Binary Strings Without Adjacent Zeros
function validStrings(n: number): string[] {
const ans: string[] = [];
const t: string[] = [];
const dfs = (i: number) => {
if (i >= n) {
ans.push(t.join(''));
return;
}
for (let j = 0; j < 2; ++j) {
if ((j == 0 && (i == 0 || t[i - 1] == '1')) || j == 1) {
t.push(j.toString());
dfs(i + 1);
t.pop();
}
}
};
dfs(0);
return ans;
}
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.