Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Move from brute-force thinking to an efficient approach using array strategy.
Given an integer n, find a sequence with elements in the range [1, n] that satisfies all of the following:
1 occurs once in the sequence.2 and n occurs twice in the sequence.i between 2 and n, the distance between the two occurrences of i is exactly i.The distance between two numbers on the sequence, a[i] and a[j], is the absolute difference of their indices, |j - i|.
Return the lexicographically largest sequence. It is guaranteed that under the given constraints, there is always a solution.
A sequence a is lexicographically larger than a sequence b (of the same length) if in the first position where a and b differ, sequence a has a number greater than the corresponding number in b. For example, [0,1,9,0] is lexicographically larger than [0,1,5,6] because the first position they differ is at the third number, and 9 is greater than 5.
Example 1:
Input: n = 3 Output: [3,1,2,3,2] Explanation: [2,3,2,1,3] is also a valid sequence, but [3,1,2,3,2] is the lexicographically largest valid sequence.
Example 2:
Input: n = 5 Output: [5,3,1,4,3,5,2,4,2]
Constraints:
1 <= n <= 20Problem summary: Given an integer n, find a sequence with elements in the range [1, n] that satisfies all of the following: The integer 1 occurs once in the sequence. Each integer between 2 and n occurs twice in the sequence. For every integer i between 2 and n, the distance between the two occurrences of i is exactly i. The distance between two numbers on the sequence, a[i] and a[j], is the absolute difference of their indices, |j - i|. Return the lexicographically largest sequence. It is guaranteed that under the given constraints, there is always a solution. A sequence a is lexicographically larger than a sequence b (of the same length) if in the first position where a and b differ, sequence a has a number greater than the corresponding number in b. For example, [0,1,9,0] is lexicographically larger than [0,1,5,6] because the first position they differ is at the third number, and 9 is greater than 5.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array · Backtracking
3
5
the-number-of-beautiful-subsets)find-the-lexicographically-largest-string-from-the-box-i)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #1718: Construct the Lexicographically Largest Valid Sequence
class Solution {
private int[] path;
private int[] cnt;
private int n;
public int[] constructDistancedSequence(int n) {
this.n = n;
path = new int[n * 2];
cnt = new int[n * 2];
Arrays.fill(cnt, 2);
cnt[1] = 1;
dfs(1);
int[] ans = new int[n * 2 - 1];
for (int i = 0; i < ans.length; ++i) {
ans[i] = path[i + 1];
}
return ans;
}
private boolean dfs(int u) {
if (u == n * 2) {
return true;
}
if (path[u] > 0) {
return dfs(u + 1);
}
for (int i = n; i > 1; --i) {
if (cnt[i] > 0 && u + i < n * 2 && path[u + i] == 0) {
cnt[i] = 0;
path[u] = i;
path[u + i] = i;
if (dfs(u + 1)) {
return true;
}
cnt[i] = 2;
path[u] = 0;
path[u + i] = 0;
}
}
if (cnt[1] > 0) {
path[u] = 1;
cnt[1] = 0;
if (dfs(u + 1)) {
return true;
}
cnt[1] = 1;
path[u] = 0;
}
return false;
}
}
// Accepted solution for LeetCode #1718: Construct the Lexicographically Largest Valid Sequence
func constructDistancedSequence(n int) []int {
path := make([]int, n*2)
cnt := make([]int, n*2)
for i := range cnt {
cnt[i] = 2
}
cnt[1] = 1
var dfs func(u int) bool
dfs = func(u int) bool {
if u == n*2 {
return true
}
if path[u] > 0 {
return dfs(u + 1)
}
for i := n; i > 1; i-- {
if cnt[i] > 0 && u+i < n*2 && path[u+i] == 0 {
cnt[i] = 0
path[u], path[u+i] = i, i
if dfs(u + 1) {
return true
}
cnt[i] = 2
path[u], path[u+i] = 0, 0
}
}
if cnt[1] > 0 {
cnt[1] = 0
path[u] = 1
if dfs(u + 1) {
return true
}
cnt[1] = 1
path[u] = 0
}
return false
}
dfs(1)
return path[1:]
}
# Accepted solution for LeetCode #1718: Construct the Lexicographically Largest Valid Sequence
class Solution:
def constructDistancedSequence(self, n: int) -> List[int]:
def dfs(u):
if u == n * 2:
return True
if path[u]:
return dfs(u + 1)
for i in range(n, 1, -1):
if cnt[i] and u + i < n * 2 and path[u + i] == 0:
cnt[i] = 0
path[u] = path[u + i] = i
if dfs(u + 1):
return True
path[u] = path[u + i] = 0
cnt[i] = 2
if cnt[1]:
cnt[1], path[u] = 0, 1
if dfs(u + 1):
return True
path[u], cnt[1] = 0, 1
return False
path = [0] * (n * 2)
cnt = [2] * (n * 2)
cnt[1] = 1
dfs(1)
return path[1:]
// Accepted solution for LeetCode #1718: Construct the Lexicographically Largest Valid Sequence
struct Solution;
impl Solution {
fn construct_distanced_sequence(n: i32) -> Vec<i32> {
let mut nums: Vec<i32> = vec![];
for i in (2..=n).rev() {
nums.push(i);
}
nums.push(1);
let n = n as usize;
let m = 2 * n - 1;
let mut cur = vec![0; m];
let mut visited: u32 = (1 << n) - 1;
Self::dfs(0, &mut cur, &mut visited, &nums, m, n);
cur
}
fn dfs(
start: usize,
cur: &mut Vec<i32>,
visited: &mut u32,
nums: &[i32],
m: usize,
n: usize,
) -> bool {
if start == m {
true
} else {
if cur[start] == 0 {
for i in 0..n {
if 1 << i & *visited != 0 {
let distance = nums[i] as usize;
if distance == 1 {
*visited &= !(1 << i);
cur[start] = nums[i];
let found = Self::dfs(start + 1, cur, visited, nums, m, n);
if found {
return true;
}
cur[start] = 0;
*visited |= 1 << i;
} else {
if start + distance < m && cur[start + distance] == 0 {
cur[start] = nums[i];
cur[start + distance] = nums[i];
*visited &= !(1 << i);
let found = Self::dfs(start + 1, cur, visited, nums, m, n);
if found {
return true;
}
cur[start + distance] = 0;
cur[start] = 0;
*visited |= 1 << i;
}
}
}
}
false
} else {
Self::dfs(start + 1, cur, visited, nums, m, n)
}
}
}
}
#[test]
fn test() {
let n = 3;
let res = vec![3, 1, 2, 3, 2];
assert_eq!(Solution::construct_distanced_sequence(n), res);
let n = 5;
let res = vec![5, 3, 1, 4, 3, 5, 2, 4, 2];
assert_eq!(Solution::construct_distanced_sequence(n), res);
}
// Accepted solution for LeetCode #1718: Construct the Lexicographically Largest Valid Sequence
// Auto-generated TypeScript example from java.
function exampleSolution(): void {
}
// Reference (java):
// // Accepted solution for LeetCode #1718: Construct the Lexicographically Largest Valid Sequence
// class Solution {
// private int[] path;
// private int[] cnt;
// private int n;
//
// public int[] constructDistancedSequence(int n) {
// this.n = n;
// path = new int[n * 2];
// cnt = new int[n * 2];
// Arrays.fill(cnt, 2);
// cnt[1] = 1;
// dfs(1);
// int[] ans = new int[n * 2 - 1];
// for (int i = 0; i < ans.length; ++i) {
// ans[i] = path[i + 1];
// }
// return ans;
// }
//
// private boolean dfs(int u) {
// if (u == n * 2) {
// return true;
// }
// if (path[u] > 0) {
// return dfs(u + 1);
// }
// for (int i = n; i > 1; --i) {
// if (cnt[i] > 0 && u + i < n * 2 && path[u + i] == 0) {
// cnt[i] = 0;
// path[u] = i;
// path[u + i] = i;
// if (dfs(u + 1)) {
// return true;
// }
// cnt[i] = 2;
// path[u] = 0;
// path[u + i] = 0;
// }
// }
// if (cnt[1] > 0) {
// path[u] = 1;
// cnt[1] = 0;
// if (dfs(u + 1)) {
// return true;
// }
// cnt[1] = 1;
// path[u] = 0;
// }
// return false;
// }
// }
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: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
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.