#3540
Medium Algorithms Minimum time to visit all houses
Array Prefix Sum
69.0% acceptance
Mar 31, 2026
7
2
You are given two integer arrays forward and backward, both of size n. You are also given another integer array queries.
There are n houses arranged in a circle. The houses are connected via roads in a special arrangement:
For all 0 <= i <= n - 2, house i is connected to house i + 1 via a road with length forward[i] meters. Additionally, house n - 1 is connected back to house 0 via a road with length forward[n - 1] meters, completing the circle.
For all 1 <= i <= n - 1, house i is connected to house i - 1 via a road with length backward[i] meters. Additionally, house 0 is connected back to house n - 1 via a road with length backward[0] meters, completing the circle.
You can walk at a pace of one meter per second. Starting from house 0, find the minimum time taken to visit each house in the order specified by queries.
Return the minimum total time taken to visit the houses.
Solution
Rust
Time O(n)
Space O(n)
impl Solution {
pub fn min_total_time(forward: Vec<i32>, backward: Vec<i32>, queries: Vec<i32>) -> i64 {
// Houses in a circle. From house i, can go forward (i -> i+1) or backward (i -> i-1).
// Need to visit queries in order, starting from house 0.
// For each consecutive pair (from, to), find min distance going clockwise or counterclockwise.
let n = forward.len();
// Precompute prefix sums for forward and backward distances.
// forward_prefix[i] = sum of forward[0..i] = cost to go 0->1->...->i
let mut fwd_prefix = vec![0i64; n + 1];
for i in 0..n {
fwd_prefix[i + 1] = fwd_prefix[i] + forward[i] as i64;
}
// backward: backward[i] is cost to go from i to i-1.
// bwd_prefix[i] = sum of backward[i] + backward[i-1] + ... = cost to go i -> i-1 -> ...
// Actually, to go from house a to house b going backward (counterclockwise):
// a -> a-1 -> ... -> b: cost = backward[a] + backward[a-1] + ... + backward[b+1]
// Let's define bwd_prefix[i] = backward[i] + backward[i-1] + ... + backward[1]
// = cost to go from i to 0 backward.
// Actually for circular: backward[0] goes from 0 to n-1.
// Cost to go from a to b going forward (clockwise):
// If a < b: sum of forward[a..b]
// If a > b: sum of forward[a..n] + forward[0..b] (wrap around)
// If a == b: 0
// Cost to go from a to b going backward (counterclockwise):
// If a > b: sum of backward[a] + backward[a-1] + ... + backward[b+1]
// Actually backward[i] is cost from i to i-1.
// So a -> a-1 costs backward[a], a-1 -> a-2 costs backward[a-1], etc.
// a to b (a > b): backward[a] + backward[a-1] + ... + backward[b+1]
// If a < b: wrap around: backward[a] + backward[a-1] + ... + backward[1] + backward[0] + backward[n-1] + ... + backward[b+1]
// Let's compute forward cost from a to b (clockwise):
let fwd_total: i64 = fwd_prefix[n]; // total forward circle cost
let forward_cost = |a: usize, b: usize| -> i64 {
if a <= b {
fwd_prefix[b] - fwd_prefix[a]
} else {
fwd_total - fwd_prefix[a] + fwd_prefix[b]
}
};
// Backward prefix: cost to go from i to 0 going backward = backward[i] + backward[i-1] + ... + backward[1]
// Actually, backward[i] = cost from i to i-1.
// bwd_cumul[i] = backward[1] + backward[2] + ... + backward[i] = cost from i to 0 going backward
// Wait, backward[i] goes from i to i-1. So to go from i to 0:
// cost = backward[i] + backward[i-1] + ... + backward[1]
// And backward[0] goes from 0 to n-1.
let mut bwd_cumul = vec![0i64; n + 1]; // bwd_cumul[i] = sum backward[1..=i]
for i in 1..=n {
bwd_cumul[i] = bwd_cumul[i - 1] + backward[i % n] as i64;
}
// bwd_cumul[i] = backward[1] + backward[2] + ... + backward[i%n]... Hmm, need to be more careful.
// Let me just make it simple: bwd_cumul[i] represents cost to go backward from house i to house 0.
// Going backward from i: i -> i-1 costs backward[i], i-1 -> i-2 costs backward[i-1], etc.
// So cost(i -> 0) = backward[i] + backward[i-1] + ... + backward[1] = sum(backward[1..=i])
let mut bwd_sum = vec![0i64; n]; // bwd_sum[i] = backward[1] + ... + backward[i], for i in 0..n
// bwd_sum[0] = 0 (no cost to go from 0 to 0)
for i in 1..n {
bwd_sum[i] = bwd_sum[i - 1] + backward[i] as i64;
}
let bwd_total: i64 = bwd_sum[n - 1] + backward[0] as i64; // full circle backward
let backward_cost = |a: usize, b: usize| -> i64 {
if a >= b {
// a to b going backward: backward[a] + backward[a-1] + ... + backward[b+1]
bwd_sum[a] - bwd_sum[b]
} else {
// Wrap around: a -> a-1 -> ... -> 0 -> n-1 -> ... -> b
// Cost: bwd_sum[a] + backward[0] + (bwd_sum[n-1] - bwd_sum[b])
bwd_sum[a] + backward[0] as i64 + bwd_sum[n - 1] - bwd_sum[b]
}
};
let mut total_time = 0i64;
let mut current = 0usize;
for &q in &queries {
let target = q as usize;
if target == current { continue; }
let fwd = forward_cost(current, target);
let bwd = backward_cost(current, target);
total_time += fwd.min(bwd);
current = target;
}
total_time
}
}