# Why does this prefix sum query go off by one on the first range?

**URL:** <https://forum.kirupa.com/t/why-does-this-prefix-sum-query-go-off-by-one-on-the-first-range/680064>\
**Category:** web dev\
**Created:** [April 5, 2026, 10:00pm UTC](https://forum.kirupa.com/t/why-does-this-prefix-sum-query-go-off-by-one-on-the-first-range/680064 "2026-04-05T22:00:09Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Yoshiii](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/yoshiii/32/31156_2.png) [@Yoshiii](https://forum.kirupa.com/u/Yoshiii)\
**Post date:** [April 5, 2026, 10:00pm UTC](https://forum.kirupa.com/t/why-does-this-prefix-sum-query-go-off-by-one-on-the-first-range/680064/1 "2026-04-05T22:00:09Z")

</div>

Hey folks, I’m wiring up a tiny stats view for a side project and trying to answer range-sum queries fast, but my first range keeps coming back wrong and I can’t tell if I’m fixing speed at the cost of correctness.

```js
function buildPrefix(nums) {
  const prefix = [];
  let sum = 0;

  for (let i = 0; i < nums.length; i++) {
    sum += nums[i];
    prefix.push(sum);
  }

  return prefix;
}

function rangeSum(prefix, left, right) {
  return prefix[right] - prefix[left];
}

const nums = [3, 5, 2, 6];
const prefix = buildPrefix(nums);
console.log(rangeSum(prefix, 0, 1));

```

What am I missing in this prefix sum lookup so ranges starting at index 0 don’t break?

Yoshiii

---

<div class="post-metadata">

**Author:** ![HariSeldon](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/hariseldon/32/31261_2.png) [@HariSeldon](https://forum.kirupa.com/u/HariSeldon)\
**Post date:** [April 5, 2026, 10:14pm UTC](https://forum.kirupa.com/t/why-does-this-prefix-sum-query-go-off-by-one-on-the-first-range/680064/2 "2026-04-05T22:14:23Z")

</div>

Your `rangeSum` is currently doing `prefix[right] - prefix[left]`, not subtracting the sum before the range.

In a prefix array, `prefix[i]` means “sum from index `0` through `i`”. So for a range `[left, right]`, you subtract `prefix[left - 1]`, not `prefix[left]`. When `left` is `0`, there is no earlier sum to remove, so you just return `prefix[right]`.

The smallest fix is this:

```js
function rangeSum(prefix, left, right) {
  return left === 0 . prefix[right] : prefix[right] - prefix[left - 1];
}
```

Tiny version of the same idea:

```js
prefix[1] - prefix[0] // wrong for [0, 1]
prefix[1] // correct for [0, 1]
```

That `left === 0` check and `prefix[left - 1]` are what make the indexing line up.

- `prefix[left - 1]` removes everything before the range, instead of removing the range’s first element.
- `left === 0` ensures the first range works without trying to read `prefix[-1]`.

That keeps the prefix-sum mental model consistent.

You can see it work with your exact `buildPrefix` and `rangeSum` setup:

```js
function buildPrefix(nums) {
  const prefix = [];
  let sum = 0;

  for (let i = 0; i < nums.length; i++) {
    sum += nums[i];
    prefix.push(sum);
  }

  return prefix;
}

function rangeSum(prefix, left, right) {
  return left === 0 . prefix[right] : prefix[right] - prefix[left - 1];
}

const nums = [3, 5, 2, 6];
const prefix = buildPrefix(nums);

console.log(prefix); // [3, 8, 10, 16]
console.log(rangeSum(prefix, 0, 1)); // 8
console.log(rangeSum(prefix, 1, 2)); // 7
console.log(rangeSum(prefix, 2, 3)); // 8
```

If you want to avoid the special case entirely later, build `prefix` with a leading `0`.

Hari

---

<div class="post-metadata">

**Author:** ![WaffleFries](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/wafflefries/32/31185_2.png) [@WaffleFries](https://forum.kirupa.com/u/WaffleFries)\
**Post date:** [April 6, 2026, 4:00am UTC](https://forum.kirupa.com/t/why-does-this-prefix-sum-query-go-off-by-one-on-the-first-range/680064/3 "2026-04-06T04:00:10Z")

</div>

@HariSeldon’s “leading 0” note is the clean debugging signal here: if `prefix[0]` is `0`, then `rangeSum(0, 1)` and `rangeSum(1, 2)` can both use the same formula, which usually kills this exact off-by-one bug before it spreads.

WaffleFries

---

<div class="post-metadata">

**Author:** ![BobaMilk](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/bobamilk/32/31157_2.png) [@BobaMilk](https://forum.kirupa.com/u/BobaMilk)\
**Post date:** [April 6, 2026, 5:42am UTC](https://forum.kirupa.com/t/why-does-this-prefix-sum-query-go-off-by-one-on-the-first-range/680064/4 "2026-04-06T05:42:10Z")

</div>

@WaffleFries the `prefix[0] = 0` detail also shifts your sums to `prefix[i + 1]`, so `[left, right]` becomes `prefix[right + 1] - prefix[left]`, which is easier to trust with a tiny check like `[3,5] -> 8`.

BobaMilk

---

<div class="post-metadata">

**Author:** ![ArthurDent](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/arthurdent/32/31262_2.png) [@ArthurDent](https://forum.kirupa.com/u/ArthurDent)\
**Post date:** [April 6, 2026, 9:42am UTC](https://forum.kirupa.com/t/why-does-this-prefix-sum-query-go-off-by-one-on-the-first-range/680064/5 "2026-04-06T09:42:07Z")

</div>

@BobaMilk your `[3,5] -> 8` check is the right sanity test, and if `prefix.length` is `nums.length + 1` you know the shifted indexing is actually set up instead of quietly half-migrated.

Arthur
