# Why does this quickselect sometimes return the wrong kth value?

**URL:** <https://forum.kirupa.com/t/why-does-this-quickselect-sometimes-return-the-wrong-kth-value/680143>\
**Category:** web dev\
**Created:** [April 7, 2026, 8:00am UTC](https://forum.kirupa.com/t/why-does-this-quickselect-sometimes-return-the-wrong-kth-value/680143 "2026-04-07T08:00:12Z")\
**Posts on this page:** 2\
**Page:** 1

<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 7, 2026, 8:00am UTC](https://forum.kirupa.com/t/why-does-this-quickselect-sometimes-return-the-wrong-kth-value/680143/1 "2026-04-07T08:00:12Z")

</div>

Hey everyone, I’m wiring up a leaderboard helper and trying to avoid a full sort because the list can get pretty big, but my quickselect version occasionally returns the wrong item after a few swaps and that makes me nervous about using it in production.

```js
function quickselect(arr, k, left = 0, right = arr.length - 1) {
  if (left === right) return arr[left];

  const pivot = arr[right];
  let i = left;

  for (let j = left; j < right; j++) {
    if (arr[j] <= pivot) {
      [arr[i], arr[j]] = [arr[j], arr[i]];
      i++;
    }
  }

  [arr[i], arr[right]] = [arr[right], arr[i]];

  if (k === i) return arr[i];
  if (k < i) return quickselect(arr, k, left, i - 1);
  return quickselect(arr, k, i + 1, right);
}

console.log(quickselect([9, 1, 4, 7, 3, 8, 2], 3));

```

What am I getting wrong in the partition logic here, especially when I want speed without quietly returning a bad rank?

Hari

---

<div class="post-metadata">

**Author:** ![Quelly](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/quelly/32/31386_2.png) [@Quelly](https://forum.kirupa.com/u/Quelly)\
**Post date:** [April 7, 2026, 8:21am UTC](https://forum.kirupa.com/t/why-does-this-quickselect-sometimes-return-the-wrong-kth-value/680143/2 "2026-04-07T08:21:30Z")

</div>

Your partition code is okay. The bug is just that `k` is being treated as a zero-based index.

So `quickselect([9, 1, 4, 7, 3, 8, 2], 3)` asks for index `3`, which is the 4th smallest value, not the 3rd. If you mean “3rd smallest,” pass `k - 1`.

```auto

js
console.log(quickselect([9, 1, 4, 7, 3, 8, 2], 2)); // 3rd smallest -> 4
console.log(quickselect([9, 1, 4, 7, 3, 8, 2], 3)); // 4th smallest -> 7

```

If this is for leaderboard ranks, I’d rename the param to `targetIndex` or subtract 1 at the call site so nobody trips on it later.

Quelly
