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.
Break down a hard problem into reliable checkpoints, edge-case handling, and complexity trade-offs.
Given two integers, n and k, an alternating permutation is a permutation of the first n positive integers such that no two adjacent elements are both odd or both even.
Return the k-th alternating permutation sorted in lexicographical order. If there are fewer than k valid alternating permutations, return an empty list.
Example 1:
Input: n = 4, k = 6
Output: [3,4,1,2]
Explanation:
The lexicographically-sorted alternating permutations of [1, 2, 3, 4] are:
[1, 2, 3, 4][1, 4, 3, 2][2, 1, 4, 3][2, 3, 4, 1][3, 2, 1, 4][3, 4, 1, 2] ← 6th permutation[4, 1, 2, 3][4, 3, 2, 1]Since k = 6, we return [3, 4, 1, 2].
Example 2:
Input: n = 3, k = 2
Output: [3,2,1]
Explanation:
The lexicographically-sorted alternating permutations of [1, 2, 3] are:
[1, 2, 3][3, 2, 1] ← 2nd permutationSince k = 2, we return [3, 2, 1].
Example 3:
Input: n = 2, k = 3
Output: []
Explanation:
The lexicographically-sorted alternating permutations of [1, 2] are:
[1, 2][2, 1]There are only 2 alternating permutations, but k = 3, which is out of range. Thus, we return an empty list [].
Constraints:
1 <= n <= 1001 <= k <= 1015Problem summary: Given two integers, n and k, an alternating permutation is a permutation of the first n positive integers such that no two adjacent elements are both odd or both even. Return the k-th alternating permutation sorted in lexicographical order. If there are fewer than k valid alternating permutations, return an empty list.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array · Math
4 6
3 2
2 3
permutations-iii)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #3470: Permutations IV
// Auto-generated Java example from go.
class Solution {
public void exampleSolution() {
}
}
// Reference (go):
// // Accepted solution for LeetCode #3470: Permutations IV
// package main
//
// import "slices"
//
// // https://space.bilibili.com/206214
// // 预处理交替排列的方案数
// var f = []int{1}
//
// func init() {
// for i := 1; f[len(f)-1] < 1e15; i++ {
// f = append(f, f[len(f)-1]*i)
// f = append(f, f[len(f)-1]*i)
// }
// }
//
// func permute(n int, K int64) []int {
// // k 改成从 0 开始,方便计算
// k := int(K - 1)
// if n < len(f) && k >= f[n]*(2-n%2) { // n 是偶数的时候,方案数乘以 2
// return nil
// }
//
// // cand 表示剩余未填入 ans 的数字
// // cand[0] 保存偶数,cand[1] 保存奇数
// cand := [2][]int{}
// for i := 2; i <= n; i += 2 {
// cand[0] = append(cand[0], i)
// }
// for i := 1; i <= n; i += 2 {
// cand[1] = append(cand[1], i)
// }
//
// ans := make([]int, n)
// parity := 1 // 当前要填入 ans[i] 的数的奇偶性
// for i := range n {
// j := 0
// if n-1-i < len(f) {
// // 比如示例 1,按照第一个数分组,每一组的大小都是 size=2
// // 知道 k 和 size 就知道我们要去哪一组
// size := f[n-1-i]
// j = k / size // 去第 j 组
// k %= size
// // n 是偶数的情况,第一个数既可以填奇数又可以填偶数,要特殊处理
// if n%2 == 0 && i == 0 {
// parity = 1 - j%2
// j /= 2
// }
// } // else n 很大的情况下,只能按照 1,2,3,... 的顺序填
// ans[i] = cand[parity][j]
// cand[parity] = slices.Delete(cand[parity], j, j+1)
// parity ^= 1 // 下一个数的奇偶性
// }
// return ans
// }
// Accepted solution for LeetCode #3470: Permutations IV
package main
import "slices"
// https://space.bilibili.com/206214
// 预处理交替排列的方案数
var f = []int{1}
func init() {
for i := 1; f[len(f)-1] < 1e15; i++ {
f = append(f, f[len(f)-1]*i)
f = append(f, f[len(f)-1]*i)
}
}
func permute(n int, K int64) []int {
// k 改成从 0 开始,方便计算
k := int(K - 1)
if n < len(f) && k >= f[n]*(2-n%2) { // n 是偶数的时候,方案数乘以 2
return nil
}
// cand 表示剩余未填入 ans 的数字
// cand[0] 保存偶数,cand[1] 保存奇数
cand := [2][]int{}
for i := 2; i <= n; i += 2 {
cand[0] = append(cand[0], i)
}
for i := 1; i <= n; i += 2 {
cand[1] = append(cand[1], i)
}
ans := make([]int, n)
parity := 1 // 当前要填入 ans[i] 的数的奇偶性
for i := range n {
j := 0
if n-1-i < len(f) {
// 比如示例 1,按照第一个数分组,每一组的大小都是 size=2
// 知道 k 和 size 就知道我们要去哪一组
size := f[n-1-i]
j = k / size // 去第 j 组
k %= size
// n 是偶数的情况,第一个数既可以填奇数又可以填偶数,要特殊处理
if n%2 == 0 && i == 0 {
parity = 1 - j%2
j /= 2
}
} // else n 很大的情况下,只能按照 1,2,3,... 的顺序填
ans[i] = cand[parity][j]
cand[parity] = slices.Delete(cand[parity], j, j+1)
parity ^= 1 // 下一个数的奇偶性
}
return ans
}
# Accepted solution for LeetCode #3470: Permutations IV
class Solution:
def permute(self, n: int, k: int) -> list[int]:
ans = []
isLookingForEven = True
remainingNumbers = list(range(1, n + 1))
for turn in range(n):
remainingPermutations = (math.factorial((n - 1 - turn) // 2) *
math.factorial((n - turn) // 2))
found = False
for index, number in enumerate(remainingNumbers):
if number % 2 != isLookingForEven and (turn > 0 or n % 2 == 1):
continue
if k <= remainingPermutations:
ans.append(remainingNumbers.pop(index))
isLookingForEven = ans[-1] % 2 == 0
found = True
break
k -= remainingPermutations
if not found:
return []
return ans
// Accepted solution for LeetCode #3470: Permutations IV
// Rust example auto-generated from go reference.
// Replace the signature and local types with the exact LeetCode harness for this problem.
impl Solution {
pub fn rust_example() {
// Port the logic from the reference block below.
}
}
// Reference (go):
// // Accepted solution for LeetCode #3470: Permutations IV
// package main
//
// import "slices"
//
// // https://space.bilibili.com/206214
// // 预处理交替排列的方案数
// var f = []int{1}
//
// func init() {
// for i := 1; f[len(f)-1] < 1e15; i++ {
// f = append(f, f[len(f)-1]*i)
// f = append(f, f[len(f)-1]*i)
// }
// }
//
// func permute(n int, K int64) []int {
// // k 改成从 0 开始,方便计算
// k := int(K - 1)
// if n < len(f) && k >= f[n]*(2-n%2) { // n 是偶数的时候,方案数乘以 2
// return nil
// }
//
// // cand 表示剩余未填入 ans 的数字
// // cand[0] 保存偶数,cand[1] 保存奇数
// cand := [2][]int{}
// for i := 2; i <= n; i += 2 {
// cand[0] = append(cand[0], i)
// }
// for i := 1; i <= n; i += 2 {
// cand[1] = append(cand[1], i)
// }
//
// ans := make([]int, n)
// parity := 1 // 当前要填入 ans[i] 的数的奇偶性
// for i := range n {
// j := 0
// if n-1-i < len(f) {
// // 比如示例 1,按照第一个数分组,每一组的大小都是 size=2
// // 知道 k 和 size 就知道我们要去哪一组
// size := f[n-1-i]
// j = k / size // 去第 j 组
// k %= size
// // n 是偶数的情况,第一个数既可以填奇数又可以填偶数,要特殊处理
// if n%2 == 0 && i == 0 {
// parity = 1 - j%2
// j /= 2
// }
// } // else n 很大的情况下,只能按照 1,2,3,... 的顺序填
// ans[i] = cand[parity][j]
// cand[parity] = slices.Delete(cand[parity], j, j+1)
// parity ^= 1 // 下一个数的奇偶性
// }
// return ans
// }
// Accepted solution for LeetCode #3470: Permutations IV
// Auto-generated TypeScript example from go.
function exampleSolution(): void {
}
// Reference (go):
// // Accepted solution for LeetCode #3470: Permutations IV
// package main
//
// import "slices"
//
// // https://space.bilibili.com/206214
// // 预处理交替排列的方案数
// var f = []int{1}
//
// func init() {
// for i := 1; f[len(f)-1] < 1e15; i++ {
// f = append(f, f[len(f)-1]*i)
// f = append(f, f[len(f)-1]*i)
// }
// }
//
// func permute(n int, K int64) []int {
// // k 改成从 0 开始,方便计算
// k := int(K - 1)
// if n < len(f) && k >= f[n]*(2-n%2) { // n 是偶数的时候,方案数乘以 2
// return nil
// }
//
// // cand 表示剩余未填入 ans 的数字
// // cand[0] 保存偶数,cand[1] 保存奇数
// cand := [2][]int{}
// for i := 2; i <= n; i += 2 {
// cand[0] = append(cand[0], i)
// }
// for i := 1; i <= n; i += 2 {
// cand[1] = append(cand[1], i)
// }
//
// ans := make([]int, n)
// parity := 1 // 当前要填入 ans[i] 的数的奇偶性
// for i := range n {
// j := 0
// if n-1-i < len(f) {
// // 比如示例 1,按照第一个数分组,每一组的大小都是 size=2
// // 知道 k 和 size 就知道我们要去哪一组
// size := f[n-1-i]
// j = k / size // 去第 j 组
// k %= size
// // n 是偶数的情况,第一个数既可以填奇数又可以填偶数,要特殊处理
// if n%2 == 0 && i == 0 {
// parity = 1 - j%2
// j /= 2
// }
// } // else n 很大的情况下,只能按照 1,2,3,... 的顺序填
// ans[i] = cand[parity][j]
// cand[parity] = slices.Delete(cand[parity], j, j+1)
// parity ^= 1 // 下一个数的奇偶性
// }
// return ans
// }
Use this to step through a reusable interview workflow for this problem.
Two nested loops check every pair or subarray. The outer loop fixes a starting point, the inner loop extends or searches. For n elements this gives up to n²/2 operations. No extra space, but the quadratic time is prohibitive for large inputs.
Most array problems have an O(n²) brute force (nested loops) and an O(n) optimal (single pass with clever state tracking). The key is identifying what information to maintain as you scan: a running max, a prefix sum, a hash map of seen values, or two pointers.
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: Temporary multiplications exceed integer bounds.
Usually fails on: Large inputs wrap around unexpectedly.
Fix: Use wider types, modular arithmetic, or rearranged operations.