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.
You are given an integer array nums of length n.
You start at index 0, and your goal is to reach index n - 1.
From any index i, you may perform one of the following operations:
i + 1 or i - 1, if the index is within bounds.nums[i] is a prime number p, you may instantly jump to any index j != i such that nums[j] % p == 0.Return the minimum number of jumps required to reach index n - 1.
Example 1:
Input: nums = [1,2,4,6]
Output: 2
Explanation:
One optimal sequence of jumps is:
i = 0. Take an adjacent step to index 1.i = 1, nums[1] = 2 is a prime number. Therefore, we teleport to index i = 3 as nums[3] = 6 is divisible by 2.Thus, the answer is 2.
Example 2:
Input: nums = [2,3,4,7,9]
Output: 2
Explanation:
One optimal sequence of jumps is:
i = 0. Take an adjacent step to index i = 1.i = 1, nums[1] = 3 is a prime number. Therefore, we teleport to index i = 4 since nums[4] = 9 is divisible by 3.Thus, the answer is 2.
Example 3:
Input: nums = [4,6,5,8]
Output: 3
Explanation:
0 → 1 → 2 → 3. Thus, the answer is 3.Constraints:
1 <= n == nums.length <= 1051 <= nums[i] <= 106Problem summary: You are given an integer array nums of length n. You start at index 0, and your goal is to reach index n - 1. From any index i, you may perform one of the following operations: Adjacent Step: Jump to index i + 1 or i - 1, if the index is within bounds. Prime Teleportation: If nums[i] is a prime number p, you may instantly jump to any index j != i such that nums[j] % p == 0. Return the minimum number of jumps required to reach index n - 1.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array · Hash Map · Math
[1,2,4,6]
[2,3,4,7,9]
[4,6,5,8]
Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #3629: Minimum Jumps to Reach End via Prime Teleportation
// Auto-generated Java example from go.
class Solution {
public void exampleSolution() {
}
}
// Reference (go):
// // Accepted solution for LeetCode #3629: Minimum Jumps to Reach End via Prime Teleportation
// package main
//
// // https://space.bilibili.com/206214
// const mx = 1_000_001
//
// var primeFactors = [mx][]int{}
//
// func init() {
// // 预处理每个数的质因子列表,思路同埃氏筛
// for i := 2; i < mx; i++ {
// if primeFactors[i] == nil { // i 是质数
// for j := i; j < mx; j += i { // i 的倍数有质因子 i
// primeFactors[j] = append(primeFactors[j], i)
// }
// }
// }
// }
//
// func minJumps(nums []int) (ans int) {
// n := len(nums)
// groups := map[int][]int{}
// for i, x := range nums {
// if len(primeFactors[x]) == 1 { // x 是质数
// groups[x] = append(groups[x], i)
// }
// }
//
// vis := make([]bool, n)
// vis[n-1] = true
// q := []int{n - 1}
// for {
// tmp := q
// q = nil
// for _, i := range tmp {
// if i == 0 {
// return
// }
// if !vis[i-1] {
// vis[i-1] = true
// q = append(q, i-1)
// }
// if i < n-1 && !vis[i+1] {
// vis[i+1] = true
// q = append(q, i+1)
// }
// // 逆向思维:从 i 倒着跳到 nums[i] 的质因子 p 的下标 j
// for _, p := range primeFactors[nums[i]] {
// for _, j := range groups[p] {
// if !vis[j] {
// vis[j] = true
// q = append(q, j)
// }
// }
// delete(groups, p) // 避免重复访问下标列表
// }
// }
// ans++
// }
// }
//
// func minJumps1(nums []int) (ans int) {
// n := len(nums)
// groups := map[int][]int{}
// for i, x := range nums {
// for _, p := range primeFactors[x] {
// groups[p] = append(groups[p], i) // 对于质数 p,可以跳到下标 i
// }
// }
//
// vis := make([]bool, n)
// vis[0] = true
// q := []int{0}
// for {
// tmp := q
// q = nil
// for _, i := range tmp {
// if i == n-1 {
// return
// }
// idx := groups[nums[i]]
// idx = append(idx, i+1)
// if i > 0 {
// idx = append(idx, i-1)
// }
// for _, j := range idx { // 可以从 i 跳到 j
// if !vis[j] {
// vis[j] = true
// q = append(q, j)
// }
// }
// delete(groups, nums[i]) // 避免重复访问下标列表
// }
// ans++
// }
// }
// Accepted solution for LeetCode #3629: Minimum Jumps to Reach End via Prime Teleportation
package main
// https://space.bilibili.com/206214
const mx = 1_000_001
var primeFactors = [mx][]int{}
func init() {
// 预处理每个数的质因子列表,思路同埃氏筛
for i := 2; i < mx; i++ {
if primeFactors[i] == nil { // i 是质数
for j := i; j < mx; j += i { // i 的倍数有质因子 i
primeFactors[j] = append(primeFactors[j], i)
}
}
}
}
func minJumps(nums []int) (ans int) {
n := len(nums)
groups := map[int][]int{}
for i, x := range nums {
if len(primeFactors[x]) == 1 { // x 是质数
groups[x] = append(groups[x], i)
}
}
vis := make([]bool, n)
vis[n-1] = true
q := []int{n - 1}
for {
tmp := q
q = nil
for _, i := range tmp {
if i == 0 {
return
}
if !vis[i-1] {
vis[i-1] = true
q = append(q, i-1)
}
if i < n-1 && !vis[i+1] {
vis[i+1] = true
q = append(q, i+1)
}
// 逆向思维:从 i 倒着跳到 nums[i] 的质因子 p 的下标 j
for _, p := range primeFactors[nums[i]] {
for _, j := range groups[p] {
if !vis[j] {
vis[j] = true
q = append(q, j)
}
}
delete(groups, p) // 避免重复访问下标列表
}
}
ans++
}
}
func minJumps1(nums []int) (ans int) {
n := len(nums)
groups := map[int][]int{}
for i, x := range nums {
for _, p := range primeFactors[x] {
groups[p] = append(groups[p], i) // 对于质数 p,可以跳到下标 i
}
}
vis := make([]bool, n)
vis[0] = true
q := []int{0}
for {
tmp := q
q = nil
for _, i := range tmp {
if i == n-1 {
return
}
idx := groups[nums[i]]
idx = append(idx, i+1)
if i > 0 {
idx = append(idx, i-1)
}
for _, j := range idx { // 可以从 i 跳到 j
if !vis[j] {
vis[j] = true
q = append(q, j)
}
}
delete(groups, nums[i]) // 避免重复访问下标列表
}
ans++
}
}
# Accepted solution for LeetCode #3629: Minimum Jumps to Reach End via Prime Teleportation
# Time: precompute: O(r)
# runtime: O(nlogr)
# Space: O(r + nlogr)
import collections
# number theory, bfs
def linear_sieve_of_eratosthenes(n): # Time: O(n), Space: O(n)
primes = []
spf = [-1]*(n+1) # the smallest prime factor
for i in xrange(2, n+1):
if spf[i] == -1:
spf[i] = i
primes.append(i)
for p in primes:
if i*p > n or p > spf[i]:
break
spf[i*p] = p
return spf
MAX_NUM = 10**6
SPF = linear_sieve_of_eratosthenes(MAX_NUM)
class Solution(object):
def minJumps(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
adj = collections.defaultdict(list)
for i, x in enumerate(nums):
while x != 1:
p = SPF[x]
while x%p == 0:
x //= p
adj[p].append(i)
dist = [-1]*len(nums)
dist[0] = 0
q = [0]
while q:
new_q = []
for i in q:
if i == len(nums)-1:
return dist[-1]
for di in (-1, +1):
ni = i+di
if 0 <= ni < len(nums) and dist[ni] == -1:
dist[ni] = dist[i]+1
new_q.append(ni)
p = nums[i]
if SPF[p] != p or p not in adj:
continue
for ni in adj[p]:
if dist[ni] != -1:
continue
dist[ni] = dist[i]+1
new_q.append(ni)
del adj[p]
q = new_q
return -1
// Accepted solution for LeetCode #3629: Minimum Jumps to Reach End via Prime Teleportation
// 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 #3629: Minimum Jumps to Reach End via Prime Teleportation
// package main
//
// // https://space.bilibili.com/206214
// const mx = 1_000_001
//
// var primeFactors = [mx][]int{}
//
// func init() {
// // 预处理每个数的质因子列表,思路同埃氏筛
// for i := 2; i < mx; i++ {
// if primeFactors[i] == nil { // i 是质数
// for j := i; j < mx; j += i { // i 的倍数有质因子 i
// primeFactors[j] = append(primeFactors[j], i)
// }
// }
// }
// }
//
// func minJumps(nums []int) (ans int) {
// n := len(nums)
// groups := map[int][]int{}
// for i, x := range nums {
// if len(primeFactors[x]) == 1 { // x 是质数
// groups[x] = append(groups[x], i)
// }
// }
//
// vis := make([]bool, n)
// vis[n-1] = true
// q := []int{n - 1}
// for {
// tmp := q
// q = nil
// for _, i := range tmp {
// if i == 0 {
// return
// }
// if !vis[i-1] {
// vis[i-1] = true
// q = append(q, i-1)
// }
// if i < n-1 && !vis[i+1] {
// vis[i+1] = true
// q = append(q, i+1)
// }
// // 逆向思维:从 i 倒着跳到 nums[i] 的质因子 p 的下标 j
// for _, p := range primeFactors[nums[i]] {
// for _, j := range groups[p] {
// if !vis[j] {
// vis[j] = true
// q = append(q, j)
// }
// }
// delete(groups, p) // 避免重复访问下标列表
// }
// }
// ans++
// }
// }
//
// func minJumps1(nums []int) (ans int) {
// n := len(nums)
// groups := map[int][]int{}
// for i, x := range nums {
// for _, p := range primeFactors[x] {
// groups[p] = append(groups[p], i) // 对于质数 p,可以跳到下标 i
// }
// }
//
// vis := make([]bool, n)
// vis[0] = true
// q := []int{0}
// for {
// tmp := q
// q = nil
// for _, i := range tmp {
// if i == n-1 {
// return
// }
// idx := groups[nums[i]]
// idx = append(idx, i+1)
// if i > 0 {
// idx = append(idx, i-1)
// }
// for _, j := range idx { // 可以从 i 跳到 j
// if !vis[j] {
// vis[j] = true
// q = append(q, j)
// }
// }
// delete(groups, nums[i]) // 避免重复访问下标列表
// }
// ans++
// }
// }
// Accepted solution for LeetCode #3629: Minimum Jumps to Reach End via Prime Teleportation
// Auto-generated TypeScript example from go.
function exampleSolution(): void {
}
// Reference (go):
// // Accepted solution for LeetCode #3629: Minimum Jumps to Reach End via Prime Teleportation
// package main
//
// // https://space.bilibili.com/206214
// const mx = 1_000_001
//
// var primeFactors = [mx][]int{}
//
// func init() {
// // 预处理每个数的质因子列表,思路同埃氏筛
// for i := 2; i < mx; i++ {
// if primeFactors[i] == nil { // i 是质数
// for j := i; j < mx; j += i { // i 的倍数有质因子 i
// primeFactors[j] = append(primeFactors[j], i)
// }
// }
// }
// }
//
// func minJumps(nums []int) (ans int) {
// n := len(nums)
// groups := map[int][]int{}
// for i, x := range nums {
// if len(primeFactors[x]) == 1 { // x 是质数
// groups[x] = append(groups[x], i)
// }
// }
//
// vis := make([]bool, n)
// vis[n-1] = true
// q := []int{n - 1}
// for {
// tmp := q
// q = nil
// for _, i := range tmp {
// if i == 0 {
// return
// }
// if !vis[i-1] {
// vis[i-1] = true
// q = append(q, i-1)
// }
// if i < n-1 && !vis[i+1] {
// vis[i+1] = true
// q = append(q, i+1)
// }
// // 逆向思维:从 i 倒着跳到 nums[i] 的质因子 p 的下标 j
// for _, p := range primeFactors[nums[i]] {
// for _, j := range groups[p] {
// if !vis[j] {
// vis[j] = true
// q = append(q, j)
// }
// }
// delete(groups, p) // 避免重复访问下标列表
// }
// }
// ans++
// }
// }
//
// func minJumps1(nums []int) (ans int) {
// n := len(nums)
// groups := map[int][]int{}
// for i, x := range nums {
// for _, p := range primeFactors[x] {
// groups[p] = append(groups[p], i) // 对于质数 p,可以跳到下标 i
// }
// }
//
// vis := make([]bool, n)
// vis[0] = true
// q := []int{0}
// for {
// tmp := q
// q = nil
// for _, i := range tmp {
// if i == n-1 {
// return
// }
// idx := groups[nums[i]]
// idx = append(idx, i+1)
// if i > 0 {
// idx = append(idx, i-1)
// }
// for _, j := range idx { // 可以从 i 跳到 j
// if !vis[j] {
// vis[j] = true
// q = append(q, j)
// }
// }
// delete(groups, nums[i]) // 避免重复访问下标列表
// }
// 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: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.
Wrong move: Temporary multiplications exceed integer bounds.
Usually fails on: Large inputs wrap around unexpectedly.
Fix: Use wider types, modular arithmetic, or rearranged operations.