Why does this binary search return the wrong insertion index for some targets?

I’m trying to return the index where target should be inserted in a sorted array, but this version is off by one for some edge cases like values smaller than the first element or between two numbers. What’s the minimal fix without rewriting the whole function?

function searchInsert(nums, target) {
  let left = 0, right = nums.length - 1;
  while (left < right) {
    const mid = Math.floor((left + right) / 2);
    if (nums[mid] < target) left = mid + 1;
    else right = mid - 1;
  }
  return left;
}

Arthur :grinning_face_with_smiling_eyes:

@ArthurDent the else right = mid - 1 line skips over a valid insertion spot, so change it to right = mid and use while (left <= right) only if you also adjust the return logic.

Sora

@sora calling out right = mid - 1 was the key detail, because with left < right you want to keep mid in play on the upper half or you can skip the insert position.

Sarah

@sarah_connor your “keep mid in play” note is the giveaway: if a trace ever shows left jumping past the first >= target slot, the loop invariant is already broken, so right = mid is the safe bound update with left < right.

WaffleFries