← Back

Binary Search on the Boundary

Find the first/last position with lower- and upper-bound search — the variant everyone gets wrong.

1 / 1
// lowerBound returns the first index i with nums[i] >= target
// (or len(nums) if every element is smaller). This is Go's sort.SearchInts.
func lowerBound(nums []int, target int) int {

}
// lowerBound returns the first index i with nums[i] >= target
// (or len(nums) if every element is smaller). This is Go's sort.SearchInts.
func lowerBound(nums []int, target int) int {
    // Half-open window [lo, hi). hi starts at len so "not found" can return it.
}
// lowerBound returns the first index i with nums[i] >= target
// (or len(nums) if every element is smaller). This is Go's sort.SearchInts.
func lowerBound(nums []int, target int) int {
    // Half-open window [lo, hi). hi starts at len so "not found" can return it.
    lo, hi := 0, len(nums)
}
// lowerBound returns the first index i with nums[i] >= target
// (or len(nums) if every element is smaller). This is Go's sort.SearchInts.
func lowerBound(nums []int, target int) int {
    // Half-open window [lo, hi). hi starts at len so "not found" can return it.
    lo, hi := 0, len(nums)

    // Note: lo < hi (not <=), because hi is exclusive.
}
// lowerBound returns the first index i with nums[i] >= target
// (or len(nums) if every element is smaller). This is Go's sort.SearchInts.
func lowerBound(nums []int, target int) int {
    // Half-open window [lo, hi). hi starts at len so "not found" can return it.
    lo, hi := 0, len(nums)

    // Note: lo < hi (not <=), because hi is exclusive.
    for lo < hi {
        mid := lo + (hi-lo)/2
    }
}
// lowerBound returns the first index i with nums[i] >= target
// (or len(nums) if every element is smaller). This is Go's sort.SearchInts.
func lowerBound(nums []int, target int) int {
    // Half-open window [lo, hi). hi starts at len so "not found" can return it.
    lo, hi := 0, len(nums)

    // Note: lo < hi (not <=), because hi is exclusive.
    for lo < hi {
        mid := lo + (hi-lo)/2

            // mid is too small, so the answer is strictly to its right.
            // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
    }
}
// lowerBound returns the first index i with nums[i] >= target
// (or len(nums) if every element is smaller). This is Go's sort.SearchInts.
func lowerBound(nums []int, target int) int {
    // Half-open window [lo, hi). hi starts at len so "not found" can return it.
    lo, hi := 0, len(nums)

    // Note: lo < hi (not <=), because hi is exclusive.
    for lo < hi {
        mid := lo + (hi-lo)/2

        if nums[mid] < target {
            // mid is too small, so the answer is strictly to its right.
            lo = mid + 1
        } else {
            // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
            hi = mid
        }
    }
}
// lowerBound returns the first index i with nums[i] >= target
// (or len(nums) if every element is smaller). This is Go's sort.SearchInts.
func lowerBound(nums []int, target int) int {
    // Half-open window [lo, hi). hi starts at len so "not found" can return it.
    lo, hi := 0, len(nums)

    // Note: lo < hi (not <=), because hi is exclusive.
    for lo < hi {
        mid := lo + (hi-lo)/2

        if nums[mid] < target {
            // mid is too small, so the answer is strictly to its right.
            lo = mid + 1
        } else {
            // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
            hi = mid
        }
    }

    // lo == hi: the first position where target could be inserted in order.
}
// lowerBound returns the first index i with nums[i] >= target
// (or len(nums) if every element is smaller). This is Go's sort.SearchInts.
func lowerBound(nums []int, target int) int {
    // Half-open window [lo, hi). hi starts at len so "not found" can return it.
    lo, hi := 0, len(nums)

    // Note: lo < hi (not <=), because hi is exclusive.
    for lo < hi {
        mid := lo + (hi-lo)/2

        if nums[mid] < target {
            // mid is too small, so the answer is strictly to its right.
            lo = mid + 1
        } else {
            // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
            hi = mid
        }
    }

    // lo == hi: the first position where target could be inserted in order.
    return lo
}
// lowerBound returns the first index i with nums[i] >= target
// (or len(nums) if every element is smaller). This is Go's sort.SearchInts.
func lowerBound(nums []int, target int) int {
    // Half-open window [lo, hi). hi starts at len so "not found" can return it.
    lo, hi := 0, len(nums)

    // Note: lo < hi (not <=), because hi is exclusive.
    for lo < hi {
        mid := lo + (hi-lo)/2

        if nums[mid] < target {
            // mid is too small, so the answer is strictly to its right.
            lo = mid + 1
        } else {
            // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
            hi = mid
        }
    }

    // lo == hi: the first position where target could be inserted in order.
    return lo
}

// upperBound returns the first index i with nums[i] > target. The ONLY change
// from lowerBound is <= instead of <, which steps past equal elements too.
// lowerBound returns the first index i with nums[i] >= target
// (or len(nums) if every element is smaller). This is Go's sort.SearchInts.
func lowerBound(nums []int, target int) int {
    // Half-open window [lo, hi). hi starts at len so "not found" can return it.
    lo, hi := 0, len(nums)

    // Note: lo < hi (not <=), because hi is exclusive.
    for lo < hi {
        mid := lo + (hi-lo)/2

        if nums[mid] < target {
            // mid is too small, so the answer is strictly to its right.
            lo = mid + 1
        } else {
            // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
            hi = mid
        }
    }

    // lo == hi: the first position where target could be inserted in order.
    return lo
}

// upperBound returns the first index i with nums[i] > target. The ONLY change
// from lowerBound is <= instead of <, which steps past equal elements too.
func upperBound(nums []int, target int) int {
    lo, hi := 0, len(nums)
    for lo < hi {
        mid := lo + (hi-lo)/2
        if nums[mid] <= target {
            lo = mid + 1
        } else {
            hi = mid
        }
    }
    return lo
}
# lower_bound returns the first index i with nums[i] >= target
# (or len(nums) if every element is smaller). This is Python's bisect.bisect_left.
def lower_bound(nums, target):
    pass
# lower_bound returns the first index i with nums[i] >= target
# (or len(nums) if every element is smaller). This is Python's bisect.bisect_left.
def lower_bound(nums, target):
    # Half-open window [lo, hi). hi starts at len so "not found" can return it.
    pass
# lower_bound returns the first index i with nums[i] >= target
# (or len(nums) if every element is smaller). This is Python's bisect.bisect_left.
def lower_bound(nums, target):
    # Half-open window [lo, hi). hi starts at len so "not found" can return it.
    lo, hi = 0, len(nums)
# lower_bound returns the first index i with nums[i] >= target
# (or len(nums) if every element is smaller). This is Python's bisect.bisect_left.
def lower_bound(nums, target):
    # Half-open window [lo, hi). hi starts at len so "not found" can return it.
    lo, hi = 0, len(nums)

    # Note: lo < hi (not <=), because hi is exclusive.
# lower_bound returns the first index i with nums[i] >= target
# (or len(nums) if every element is smaller). This is Python's bisect.bisect_left.
def lower_bound(nums, target):
    # Half-open window [lo, hi). hi starts at len so "not found" can return it.
    lo, hi = 0, len(nums)

    # Note: lo < hi (not <=), because hi is exclusive.
    while lo < hi:
        mid = lo + (hi - lo) // 2
# lower_bound returns the first index i with nums[i] >= target
# (or len(nums) if every element is smaller). This is Python's bisect.bisect_left.
def lower_bound(nums, target):
    # Half-open window [lo, hi). hi starts at len so "not found" can return it.
    lo, hi = 0, len(nums)

    # Note: lo < hi (not <=), because hi is exclusive.
    while lo < hi:
        mid = lo + (hi - lo) // 2

            # mid is too small, so the answer is strictly to its right.
            # mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
# lower_bound returns the first index i with nums[i] >= target
# (or len(nums) if every element is smaller). This is Python's bisect.bisect_left.
def lower_bound(nums, target):
    # Half-open window [lo, hi). hi starts at len so "not found" can return it.
    lo, hi = 0, len(nums)

    # Note: lo < hi (not <=), because hi is exclusive.
    while lo < hi:
        mid = lo + (hi - lo) // 2

        if nums[mid] < target:
            # mid is too small, so the answer is strictly to its right.
            lo = mid + 1
        else:
            # mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
            hi = mid
# lower_bound returns the first index i with nums[i] >= target
# (or len(nums) if every element is smaller). This is Python's bisect.bisect_left.
def lower_bound(nums, target):
    # Half-open window [lo, hi). hi starts at len so "not found" can return it.
    lo, hi = 0, len(nums)

    # Note: lo < hi (not <=), because hi is exclusive.
    while lo < hi:
        mid = lo + (hi - lo) // 2

        if nums[mid] < target:
            # mid is too small, so the answer is strictly to its right.
            lo = mid + 1
        else:
            # mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
            hi = mid

    # lo == hi: the first position where target could be inserted in order.
# lower_bound returns the first index i with nums[i] >= target
# (or len(nums) if every element is smaller). This is Python's bisect.bisect_left.
def lower_bound(nums, target):
    # Half-open window [lo, hi). hi starts at len so "not found" can return it.
    lo, hi = 0, len(nums)

    # Note: lo < hi (not <=), because hi is exclusive.
    while lo < hi:
        mid = lo + (hi - lo) // 2

        if nums[mid] < target:
            # mid is too small, so the answer is strictly to its right.
            lo = mid + 1
        else:
            # mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
            hi = mid

    # lo == hi: the first position where target could be inserted in order.
    return lo
# lower_bound returns the first index i with nums[i] >= target
# (or len(nums) if every element is smaller). This is Python's bisect.bisect_left.
def lower_bound(nums, target):
    # Half-open window [lo, hi). hi starts at len so "not found" can return it.
    lo, hi = 0, len(nums)

    # Note: lo < hi (not <=), because hi is exclusive.
    while lo < hi:
        mid = lo + (hi - lo) // 2

        if nums[mid] < target:
            # mid is too small, so the answer is strictly to its right.
            lo = mid + 1
        else:
            # mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
            hi = mid

    # lo == hi: the first position where target could be inserted in order.
    return lo


# upper_bound returns the first index i with nums[i] > target. The ONLY change
# from lower_bound is <= instead of <, which steps past equal elements too.
# lower_bound returns the first index i with nums[i] >= target
# (or len(nums) if every element is smaller). This is Python's bisect.bisect_left.
def lower_bound(nums, target):
    # Half-open window [lo, hi). hi starts at len so "not found" can return it.
    lo, hi = 0, len(nums)

    # Note: lo < hi (not <=), because hi is exclusive.
    while lo < hi:
        mid = lo + (hi - lo) // 2

        if nums[mid] < target:
            # mid is too small, so the answer is strictly to its right.
            lo = mid + 1
        else:
            # mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
            hi = mid

    # lo == hi: the first position where target could be inserted in order.
    return lo


# upper_bound returns the first index i with nums[i] > target. The ONLY change
# from lower_bound is <= instead of <, which steps past equal elements too.
def upper_bound(nums, target):
    lo, hi = 0, len(nums)
    while lo < hi:
        mid = lo + (hi - lo) // 2
        if nums[mid] <= target:
            lo = mid + 1
        else:
            hi = mid
    return lo
// lowerBound returns the first index i with nums[i] >= target
// (or nums.length if every element is smaller). The standard library has no equivalent.
function lowerBound(nums, target) {

}
// lowerBound returns the first index i with nums[i] >= target
// (or nums.length if every element is smaller). The standard library has no equivalent.
function lowerBound(nums, target) {
  // Half-open window [lo, hi). hi starts at len so "not found" can return it.
}
// lowerBound returns the first index i with nums[i] >= target
// (or nums.length if every element is smaller). The standard library has no equivalent.
function lowerBound(nums, target) {
  // Half-open window [lo, hi). hi starts at len so "not found" can return it.
  let lo = 0, hi = nums.length;
}
// lowerBound returns the first index i with nums[i] >= target
// (or nums.length if every element is smaller). The standard library has no equivalent.
function lowerBound(nums, target) {
  // Half-open window [lo, hi). hi starts at len so "not found" can return it.
  let lo = 0, hi = nums.length;

  // Note: lo < hi (not <=), because hi is exclusive.
}
// lowerBound returns the first index i with nums[i] >= target
// (or nums.length if every element is smaller). The standard library has no equivalent.
function lowerBound(nums, target) {
  // Half-open window [lo, hi). hi starts at len so "not found" can return it.
  let lo = 0, hi = nums.length;

  // Note: lo < hi (not <=), because hi is exclusive.
  while (lo < hi) {
    const mid = lo + Math.floor((hi - lo) / 2);
  }
}
// lowerBound returns the first index i with nums[i] >= target
// (or nums.length if every element is smaller). The standard library has no equivalent.
function lowerBound(nums, target) {
  // Half-open window [lo, hi). hi starts at len so "not found" can return it.
  let lo = 0, hi = nums.length;

  // Note: lo < hi (not <=), because hi is exclusive.
  while (lo < hi) {
    const mid = lo + Math.floor((hi - lo) / 2);

      // mid is too small, so the answer is strictly to its right.
      // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
  }
}
// lowerBound returns the first index i with nums[i] >= target
// (or nums.length if every element is smaller). The standard library has no equivalent.
function lowerBound(nums, target) {
  // Half-open window [lo, hi). hi starts at len so "not found" can return it.
  let lo = 0, hi = nums.length;

  // Note: lo < hi (not <=), because hi is exclusive.
  while (lo < hi) {
    const mid = lo + Math.floor((hi - lo) / 2);

    if (nums[mid] < target) {
      // mid is too small, so the answer is strictly to its right.
      lo = mid + 1;
    } else {
      // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
      hi = mid;
    }
  }
}
// lowerBound returns the first index i with nums[i] >= target
// (or nums.length if every element is smaller). The standard library has no equivalent.
function lowerBound(nums, target) {
  // Half-open window [lo, hi). hi starts at len so "not found" can return it.
  let lo = 0, hi = nums.length;

  // Note: lo < hi (not <=), because hi is exclusive.
  while (lo < hi) {
    const mid = lo + Math.floor((hi - lo) / 2);

    if (nums[mid] < target) {
      // mid is too small, so the answer is strictly to its right.
      lo = mid + 1;
    } else {
      // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
      hi = mid;
    }
  }

  // lo == hi: the first position where target could be inserted in order.
}
// lowerBound returns the first index i with nums[i] >= target
// (or nums.length if every element is smaller). The standard library has no equivalent.
function lowerBound(nums, target) {
  // Half-open window [lo, hi). hi starts at len so "not found" can return it.
  let lo = 0, hi = nums.length;

  // Note: lo < hi (not <=), because hi is exclusive.
  while (lo < hi) {
    const mid = lo + Math.floor((hi - lo) / 2);

    if (nums[mid] < target) {
      // mid is too small, so the answer is strictly to its right.
      lo = mid + 1;
    } else {
      // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
      hi = mid;
    }
  }

  // lo == hi: the first position where target could be inserted in order.
  return lo;
}
// lowerBound returns the first index i with nums[i] >= target
// (or nums.length if every element is smaller). The standard library has no equivalent.
function lowerBound(nums, target) {
  // Half-open window [lo, hi). hi starts at len so "not found" can return it.
  let lo = 0, hi = nums.length;

  // Note: lo < hi (not <=), because hi is exclusive.
  while (lo < hi) {
    const mid = lo + Math.floor((hi - lo) / 2);

    if (nums[mid] < target) {
      // mid is too small, so the answer is strictly to its right.
      lo = mid + 1;
    } else {
      // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
      hi = mid;
    }
  }

  // lo == hi: the first position where target could be inserted in order.
  return lo;
}

// upperBound returns the first index i with nums[i] > target. The ONLY change
// from lowerBound is <= instead of <, which steps past equal elements too.
// lowerBound returns the first index i with nums[i] >= target
// (or nums.length if every element is smaller). The standard library has no equivalent.
function lowerBound(nums, target) {
  // Half-open window [lo, hi). hi starts at len so "not found" can return it.
  let lo = 0, hi = nums.length;

  // Note: lo < hi (not <=), because hi is exclusive.
  while (lo < hi) {
    const mid = lo + Math.floor((hi - lo) / 2);

    if (nums[mid] < target) {
      // mid is too small, so the answer is strictly to its right.
      lo = mid + 1;
    } else {
      // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
      hi = mid;
    }
  }

  // lo == hi: the first position where target could be inserted in order.
  return lo;
}

// upperBound returns the first index i with nums[i] > target. The ONLY change
// from lowerBound is <= instead of <, which steps past equal elements too.
function upperBound(nums, target) {
  let lo = 0, hi = nums.length;
  while (lo < hi) {
    const mid = lo + Math.floor((hi - lo) / 2);
    if (nums[mid] <= target) {
      lo = mid + 1;
    } else {
      hi = mid;
    }
  }
  return lo;
}
// lowerBound returns the first index i with nums[i] >= target
// (or nums.length if every element is smaller). The standard library has no equivalent.
function lowerBound(nums: number[], target: number): number {

}
// lowerBound returns the first index i with nums[i] >= target
// (or nums.length if every element is smaller). The standard library has no equivalent.
function lowerBound(nums: number[], target: number): number {
  // Half-open window [lo, hi). hi starts at len so "not found" can return it.
}
// lowerBound returns the first index i with nums[i] >= target
// (or nums.length if every element is smaller). The standard library has no equivalent.
function lowerBound(nums: number[], target: number): number {
  // Half-open window [lo, hi). hi starts at len so "not found" can return it.
  let lo = 0, hi = nums.length;
}
// lowerBound returns the first index i with nums[i] >= target
// (or nums.length if every element is smaller). The standard library has no equivalent.
function lowerBound(nums: number[], target: number): number {
  // Half-open window [lo, hi). hi starts at len so "not found" can return it.
  let lo = 0, hi = nums.length;

  // Note: lo < hi (not <=), because hi is exclusive.
}
// lowerBound returns the first index i with nums[i] >= target
// (or nums.length if every element is smaller). The standard library has no equivalent.
function lowerBound(nums: number[], target: number): number {
  // Half-open window [lo, hi). hi starts at len so "not found" can return it.
  let lo = 0, hi = nums.length;

  // Note: lo < hi (not <=), because hi is exclusive.
  while (lo < hi) {
    const mid = lo + Math.floor((hi - lo) / 2);
  }
}
// lowerBound returns the first index i with nums[i] >= target
// (or nums.length if every element is smaller). The standard library has no equivalent.
function lowerBound(nums: number[], target: number): number {
  // Half-open window [lo, hi). hi starts at len so "not found" can return it.
  let lo = 0, hi = nums.length;

  // Note: lo < hi (not <=), because hi is exclusive.
  while (lo < hi) {
    const mid = lo + Math.floor((hi - lo) / 2);

      // mid is too small, so the answer is strictly to its right.
      // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
  }
}
// lowerBound returns the first index i with nums[i] >= target
// (or nums.length if every element is smaller). The standard library has no equivalent.
function lowerBound(nums: number[], target: number): number {
  // Half-open window [lo, hi). hi starts at len so "not found" can return it.
  let lo = 0, hi = nums.length;

  // Note: lo < hi (not <=), because hi is exclusive.
  while (lo < hi) {
    const mid = lo + Math.floor((hi - lo) / 2);

    if (nums[mid] < target) {
      // mid is too small, so the answer is strictly to its right.
      lo = mid + 1;
    } else {
      // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
      hi = mid;
    }
  }
}
// lowerBound returns the first index i with nums[i] >= target
// (or nums.length if every element is smaller). The standard library has no equivalent.
function lowerBound(nums: number[], target: number): number {
  // Half-open window [lo, hi). hi starts at len so "not found" can return it.
  let lo = 0, hi = nums.length;

  // Note: lo < hi (not <=), because hi is exclusive.
  while (lo < hi) {
    const mid = lo + Math.floor((hi - lo) / 2);

    if (nums[mid] < target) {
      // mid is too small, so the answer is strictly to its right.
      lo = mid + 1;
    } else {
      // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
      hi = mid;
    }
  }

  // lo == hi: the first position where target could be inserted in order.
}
// lowerBound returns the first index i with nums[i] >= target
// (or nums.length if every element is smaller). The standard library has no equivalent.
function lowerBound(nums: number[], target: number): number {
  // Half-open window [lo, hi). hi starts at len so "not found" can return it.
  let lo = 0, hi = nums.length;

  // Note: lo < hi (not <=), because hi is exclusive.
  while (lo < hi) {
    const mid = lo + Math.floor((hi - lo) / 2);

    if (nums[mid] < target) {
      // mid is too small, so the answer is strictly to its right.
      lo = mid + 1;
    } else {
      // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
      hi = mid;
    }
  }

  // lo == hi: the first position where target could be inserted in order.
  return lo;
}
// lowerBound returns the first index i with nums[i] >= target
// (or nums.length if every element is smaller). The standard library has no equivalent.
function lowerBound(nums: number[], target: number): number {
  // Half-open window [lo, hi). hi starts at len so "not found" can return it.
  let lo = 0, hi = nums.length;

  // Note: lo < hi (not <=), because hi is exclusive.
  while (lo < hi) {
    const mid = lo + Math.floor((hi - lo) / 2);

    if (nums[mid] < target) {
      // mid is too small, so the answer is strictly to its right.
      lo = mid + 1;
    } else {
      // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
      hi = mid;
    }
  }

  // lo == hi: the first position where target could be inserted in order.
  return lo;
}

// upperBound returns the first index i with nums[i] > target. The ONLY change
// from lowerBound is <= instead of <, which steps past equal elements too.
// lowerBound returns the first index i with nums[i] >= target
// (or nums.length if every element is smaller). The standard library has no equivalent.
function lowerBound(nums: number[], target: number): number {
  // Half-open window [lo, hi). hi starts at len so "not found" can return it.
  let lo = 0, hi = nums.length;

  // Note: lo < hi (not <=), because hi is exclusive.
  while (lo < hi) {
    const mid = lo + Math.floor((hi - lo) / 2);

    if (nums[mid] < target) {
      // mid is too small, so the answer is strictly to its right.
      lo = mid + 1;
    } else {
      // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
      hi = mid;
    }
  }

  // lo == hi: the first position where target could be inserted in order.
  return lo;
}

// upperBound returns the first index i with nums[i] > target. The ONLY change
// from lowerBound is <= instead of <, which steps past equal elements too.
function upperBound(nums: number[], target: number): number {
  let lo = 0, hi = nums.length;
  while (lo < hi) {
    const mid = lo + Math.floor((hi - lo) / 2);
    if (nums[mid] <= target) {
      lo = mid + 1;
    } else {
      hi = mid;
    }
  }
  return lo;
}
class Solution {
    // lowerBound returns the first index i with nums[i] >= target
    // (or nums.length if every element is smaller). Arrays.binarySearch is not a lower bound.
    public int lowerBound(int[] nums, int target) {

    }
}
class Solution {
    // lowerBound returns the first index i with nums[i] >= target
    // (or nums.length if every element is smaller). Arrays.binarySearch is not a lower bound.
    public int lowerBound(int[] nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
    }
}
class Solution {
    // lowerBound returns the first index i with nums[i] >= target
    // (or nums.length if every element is smaller). Arrays.binarySearch is not a lower bound.
    public int lowerBound(int[] nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = nums.length;
    }
}
class Solution {
    // lowerBound returns the first index i with nums[i] >= target
    // (or nums.length if every element is smaller). Arrays.binarySearch is not a lower bound.
    public int lowerBound(int[] nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = nums.length;

        // Note: lo < hi (not <=), because hi is exclusive.
    }
}
class Solution {
    // lowerBound returns the first index i with nums[i] >= target
    // (or nums.length if every element is smaller). Arrays.binarySearch is not a lower bound.
    public int lowerBound(int[] nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = nums.length;

        // Note: lo < hi (not <=), because hi is exclusive.
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;
        }
    }
}
class Solution {
    // lowerBound returns the first index i with nums[i] >= target
    // (or nums.length if every element is smaller). Arrays.binarySearch is not a lower bound.
    public int lowerBound(int[] nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = nums.length;

        // Note: lo < hi (not <=), because hi is exclusive.
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;

                // mid is too small, so the answer is strictly to its right.
                // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
        }
    }
}
class Solution {
    // lowerBound returns the first index i with nums[i] >= target
    // (or nums.length if every element is smaller). Arrays.binarySearch is not a lower bound.
    public int lowerBound(int[] nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = nums.length;

        // Note: lo < hi (not <=), because hi is exclusive.
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;

            if (nums[mid] < target) {
                // mid is too small, so the answer is strictly to its right.
                lo = mid + 1;
            } else {
                // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
                hi = mid;
            }
        }
    }
}
class Solution {
    // lowerBound returns the first index i with nums[i] >= target
    // (or nums.length if every element is smaller). Arrays.binarySearch is not a lower bound.
    public int lowerBound(int[] nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = nums.length;

        // Note: lo < hi (not <=), because hi is exclusive.
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;

            if (nums[mid] < target) {
                // mid is too small, so the answer is strictly to its right.
                lo = mid + 1;
            } else {
                // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
                hi = mid;
            }
        }

        // lo == hi: the first position where target could be inserted in order.
    }
}
class Solution {
    // lowerBound returns the first index i with nums[i] >= target
    // (or nums.length if every element is smaller). Arrays.binarySearch is not a lower bound.
    public int lowerBound(int[] nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = nums.length;

        // Note: lo < hi (not <=), because hi is exclusive.
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;

            if (nums[mid] < target) {
                // mid is too small, so the answer is strictly to its right.
                lo = mid + 1;
            } else {
                // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
                hi = mid;
            }
        }

        // lo == hi: the first position where target could be inserted in order.
        return lo;
    }
}
class Solution {
    // lowerBound returns the first index i with nums[i] >= target
    // (or nums.length if every element is smaller). Arrays.binarySearch is not a lower bound.
    public int lowerBound(int[] nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = nums.length;

        // Note: lo < hi (not <=), because hi is exclusive.
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;

            if (nums[mid] < target) {
                // mid is too small, so the answer is strictly to its right.
                lo = mid + 1;
            } else {
                // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
                hi = mid;
            }
        }

        // lo == hi: the first position where target could be inserted in order.
        return lo;
    }

    // upperBound returns the first index i with nums[i] > target. The ONLY change
    // from lowerBound is <= instead of <, which steps past equal elements too.
}
class Solution {
    // lowerBound returns the first index i with nums[i] >= target
    // (or nums.length if every element is smaller). Arrays.binarySearch is not a lower bound.
    public int lowerBound(int[] nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = nums.length;

        // Note: lo < hi (not <=), because hi is exclusive.
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;

            if (nums[mid] < target) {
                // mid is too small, so the answer is strictly to its right.
                lo = mid + 1;
            } else {
                // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
                hi = mid;
            }
        }

        // lo == hi: the first position where target could be inserted in order.
        return lo;
    }

    // upperBound returns the first index i with nums[i] > target. The ONLY change
    // from lowerBound is <= instead of <, which steps past equal elements too.
    public int upperBound(int[] nums, int target) {
        int lo = 0, hi = nums.length;
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;
            if (nums[mid] <= target) {
                lo = mid + 1;
            } else {
                hi = mid;
            }
        }
        return lo;
    }
}
public class Solution {
    // LowerBound returns the first index i with nums[i] >= target
    // (or nums.Length if every element is smaller). Array.BinarySearch is not a lower bound.
    public int LowerBound(int[] nums, int target) {

    }
}
public class Solution {
    // LowerBound returns the first index i with nums[i] >= target
    // (or nums.Length if every element is smaller). Array.BinarySearch is not a lower bound.
    public int LowerBound(int[] nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
    }
}
public class Solution {
    // LowerBound returns the first index i with nums[i] >= target
    // (or nums.Length if every element is smaller). Array.BinarySearch is not a lower bound.
    public int LowerBound(int[] nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = nums.Length;
    }
}
public class Solution {
    // LowerBound returns the first index i with nums[i] >= target
    // (or nums.Length if every element is smaller). Array.BinarySearch is not a lower bound.
    public int LowerBound(int[] nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = nums.Length;

        // Note: lo < hi (not <=), because hi is exclusive.
    }
}
public class Solution {
    // LowerBound returns the first index i with nums[i] >= target
    // (or nums.Length if every element is smaller). Array.BinarySearch is not a lower bound.
    public int LowerBound(int[] nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = nums.Length;

        // Note: lo < hi (not <=), because hi is exclusive.
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;
        }
    }
}
public class Solution {
    // LowerBound returns the first index i with nums[i] >= target
    // (or nums.Length if every element is smaller). Array.BinarySearch is not a lower bound.
    public int LowerBound(int[] nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = nums.Length;

        // Note: lo < hi (not <=), because hi is exclusive.
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;

                // mid is too small, so the answer is strictly to its right.
                // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
        }
    }
}
public class Solution {
    // LowerBound returns the first index i with nums[i] >= target
    // (or nums.Length if every element is smaller). Array.BinarySearch is not a lower bound.
    public int LowerBound(int[] nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = nums.Length;

        // Note: lo < hi (not <=), because hi is exclusive.
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;

            if (nums[mid] < target) {
                // mid is too small, so the answer is strictly to its right.
                lo = mid + 1;
            } else {
                // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
                hi = mid;
            }
        }
    }
}
public class Solution {
    // LowerBound returns the first index i with nums[i] >= target
    // (or nums.Length if every element is smaller). Array.BinarySearch is not a lower bound.
    public int LowerBound(int[] nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = nums.Length;

        // Note: lo < hi (not <=), because hi is exclusive.
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;

            if (nums[mid] < target) {
                // mid is too small, so the answer is strictly to its right.
                lo = mid + 1;
            } else {
                // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
                hi = mid;
            }
        }

        // lo == hi: the first position where target could be inserted in order.
    }
}
public class Solution {
    // LowerBound returns the first index i with nums[i] >= target
    // (or nums.Length if every element is smaller). Array.BinarySearch is not a lower bound.
    public int LowerBound(int[] nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = nums.Length;

        // Note: lo < hi (not <=), because hi is exclusive.
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;

            if (nums[mid] < target) {
                // mid is too small, so the answer is strictly to its right.
                lo = mid + 1;
            } else {
                // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
                hi = mid;
            }
        }

        // lo == hi: the first position where target could be inserted in order.
        return lo;
    }
}
public class Solution {
    // LowerBound returns the first index i with nums[i] >= target
    // (or nums.Length if every element is smaller). Array.BinarySearch is not a lower bound.
    public int LowerBound(int[] nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = nums.Length;

        // Note: lo < hi (not <=), because hi is exclusive.
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;

            if (nums[mid] < target) {
                // mid is too small, so the answer is strictly to its right.
                lo = mid + 1;
            } else {
                // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
                hi = mid;
            }
        }

        // lo == hi: the first position where target could be inserted in order.
        return lo;
    }

    // UpperBound returns the first index i with nums[i] > target. The ONLY change
    // from LowerBound is <= instead of <, which steps past equal elements too.
}
public class Solution {
    // LowerBound returns the first index i with nums[i] >= target
    // (or nums.Length if every element is smaller). Array.BinarySearch is not a lower bound.
    public int LowerBound(int[] nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = nums.Length;

        // Note: lo < hi (not <=), because hi is exclusive.
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;

            if (nums[mid] < target) {
                // mid is too small, so the answer is strictly to its right.
                lo = mid + 1;
            } else {
                // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
                hi = mid;
            }
        }

        // lo == hi: the first position where target could be inserted in order.
        return lo;
    }

    // UpperBound returns the first index i with nums[i] > target. The ONLY change
    // from LowerBound is <= instead of <, which steps past equal elements too.
    public int UpperBound(int[] nums, int target) {
        int lo = 0, hi = nums.Length;
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;
            if (nums[mid] <= target) {
                lo = mid + 1;
            } else {
                hi = mid;
            }
        }
        return lo;
    }
}
// lowerBound returns the first index i with nums[i] >= target
// (or numsSize if every element is smaller). bsearch is not a lower bound.
int lowerBound(int* nums, int numsSize, int target) {

}
// lowerBound returns the first index i with nums[i] >= target
// (or numsSize if every element is smaller). bsearch is not a lower bound.
int lowerBound(int* nums, int numsSize, int target) {
    // Half-open window [lo, hi). hi starts at len so "not found" can return it.
}
// lowerBound returns the first index i with nums[i] >= target
// (or numsSize if every element is smaller). bsearch is not a lower bound.
int lowerBound(int* nums, int numsSize, int target) {
    // Half-open window [lo, hi). hi starts at len so "not found" can return it.
    int lo = 0, hi = numsSize;
}
// lowerBound returns the first index i with nums[i] >= target
// (or numsSize if every element is smaller). bsearch is not a lower bound.
int lowerBound(int* nums, int numsSize, int target) {
    // Half-open window [lo, hi). hi starts at len so "not found" can return it.
    int lo = 0, hi = numsSize;

    // Note: lo < hi (not <=), because hi is exclusive.
}
// lowerBound returns the first index i with nums[i] >= target
// (or numsSize if every element is smaller). bsearch is not a lower bound.
int lowerBound(int* nums, int numsSize, int target) {
    // Half-open window [lo, hi). hi starts at len so "not found" can return it.
    int lo = 0, hi = numsSize;

    // Note: lo < hi (not <=), because hi is exclusive.
    while (lo < hi) {
        int mid = lo + (hi - lo) / 2;
    }
}
// lowerBound returns the first index i with nums[i] >= target
// (or numsSize if every element is smaller). bsearch is not a lower bound.
int lowerBound(int* nums, int numsSize, int target) {
    // Half-open window [lo, hi). hi starts at len so "not found" can return it.
    int lo = 0, hi = numsSize;

    // Note: lo < hi (not <=), because hi is exclusive.
    while (lo < hi) {
        int mid = lo + (hi - lo) / 2;

            // mid is too small, so the answer is strictly to its right.
            // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
    }
}
// lowerBound returns the first index i with nums[i] >= target
// (or numsSize if every element is smaller). bsearch is not a lower bound.
int lowerBound(int* nums, int numsSize, int target) {
    // Half-open window [lo, hi). hi starts at len so "not found" can return it.
    int lo = 0, hi = numsSize;

    // Note: lo < hi (not <=), because hi is exclusive.
    while (lo < hi) {
        int mid = lo + (hi - lo) / 2;

        if (nums[mid] < target) {
            // mid is too small, so the answer is strictly to its right.
            lo = mid + 1;
        } else {
            // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
            hi = mid;
        }
    }
}
// lowerBound returns the first index i with nums[i] >= target
// (or numsSize if every element is smaller). bsearch is not a lower bound.
int lowerBound(int* nums, int numsSize, int target) {
    // Half-open window [lo, hi). hi starts at len so "not found" can return it.
    int lo = 0, hi = numsSize;

    // Note: lo < hi (not <=), because hi is exclusive.
    while (lo < hi) {
        int mid = lo + (hi - lo) / 2;

        if (nums[mid] < target) {
            // mid is too small, so the answer is strictly to its right.
            lo = mid + 1;
        } else {
            // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
            hi = mid;
        }
    }

    // lo == hi: the first position where target could be inserted in order.
}
// lowerBound returns the first index i with nums[i] >= target
// (or numsSize if every element is smaller). bsearch is not a lower bound.
int lowerBound(int* nums, int numsSize, int target) {
    // Half-open window [lo, hi). hi starts at len so "not found" can return it.
    int lo = 0, hi = numsSize;

    // Note: lo < hi (not <=), because hi is exclusive.
    while (lo < hi) {
        int mid = lo + (hi - lo) / 2;

        if (nums[mid] < target) {
            // mid is too small, so the answer is strictly to its right.
            lo = mid + 1;
        } else {
            // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
            hi = mid;
        }
    }

    // lo == hi: the first position where target could be inserted in order.
    return lo;
}
// lowerBound returns the first index i with nums[i] >= target
// (or numsSize if every element is smaller). bsearch is not a lower bound.
int lowerBound(int* nums, int numsSize, int target) {
    // Half-open window [lo, hi). hi starts at len so "not found" can return it.
    int lo = 0, hi = numsSize;

    // Note: lo < hi (not <=), because hi is exclusive.
    while (lo < hi) {
        int mid = lo + (hi - lo) / 2;

        if (nums[mid] < target) {
            // mid is too small, so the answer is strictly to its right.
            lo = mid + 1;
        } else {
            // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
            hi = mid;
        }
    }

    // lo == hi: the first position where target could be inserted in order.
    return lo;
}

// upperBound returns the first index i with nums[i] > target. The ONLY change
// from lowerBound is <= instead of <, which steps past equal elements too.
// lowerBound returns the first index i with nums[i] >= target
// (or numsSize if every element is smaller). bsearch is not a lower bound.
int lowerBound(int* nums, int numsSize, int target) {
    // Half-open window [lo, hi). hi starts at len so "not found" can return it.
    int lo = 0, hi = numsSize;

    // Note: lo < hi (not <=), because hi is exclusive.
    while (lo < hi) {
        int mid = lo + (hi - lo) / 2;

        if (nums[mid] < target) {
            // mid is too small, so the answer is strictly to its right.
            lo = mid + 1;
        } else {
            // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
            hi = mid;
        }
    }

    // lo == hi: the first position where target could be inserted in order.
    return lo;
}

// upperBound returns the first index i with nums[i] > target. The ONLY change
// from lowerBound is <= instead of <, which steps past equal elements too.
int upperBound(int* nums, int numsSize, int target) {
    int lo = 0, hi = numsSize;
    while (lo < hi) {
        int mid = lo + (hi - lo) / 2;
        if (nums[mid] <= target) {
            lo = mid + 1;
        } else {
            hi = mid;
        }
    }
    return lo;
}
#include <vector>
using namespace std;

class Solution {
public:
    // lowerBound returns the first index i with nums[i] >= target
    // (or nums.size() if every element is smaller). This is std::lower_bound.
    int lowerBound(vector<int>& nums, int target) {

    }
};
#include <vector>
using namespace std;

class Solution {
public:
    // lowerBound returns the first index i with nums[i] >= target
    // (or nums.size() if every element is smaller). This is std::lower_bound.
    int lowerBound(vector<int>& nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
    }
};
#include <vector>
using namespace std;

class Solution {
public:
    // lowerBound returns the first index i with nums[i] >= target
    // (or nums.size() if every element is smaller). This is std::lower_bound.
    int lowerBound(vector<int>& nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = (int)nums.size();
    }
};
#include <vector>
using namespace std;

class Solution {
public:
    // lowerBound returns the first index i with nums[i] >= target
    // (or nums.size() if every element is smaller). This is std::lower_bound.
    int lowerBound(vector<int>& nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = (int)nums.size();

        // Note: lo < hi (not <=), because hi is exclusive.
    }
};
#include <vector>
using namespace std;

class Solution {
public:
    // lowerBound returns the first index i with nums[i] >= target
    // (or nums.size() if every element is smaller). This is std::lower_bound.
    int lowerBound(vector<int>& nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = (int)nums.size();

        // Note: lo < hi (not <=), because hi is exclusive.
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;
        }
    }
};
#include <vector>
using namespace std;

class Solution {
public:
    // lowerBound returns the first index i with nums[i] >= target
    // (or nums.size() if every element is smaller). This is std::lower_bound.
    int lowerBound(vector<int>& nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = (int)nums.size();

        // Note: lo < hi (not <=), because hi is exclusive.
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;

                // mid is too small, so the answer is strictly to its right.
                // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
        }
    }
};
#include <vector>
using namespace std;

class Solution {
public:
    // lowerBound returns the first index i with nums[i] >= target
    // (or nums.size() if every element is smaller). This is std::lower_bound.
    int lowerBound(vector<int>& nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = (int)nums.size();

        // Note: lo < hi (not <=), because hi is exclusive.
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;

            if (nums[mid] < target) {
                // mid is too small, so the answer is strictly to its right.
                lo = mid + 1;
            } else {
                // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
                hi = mid;
            }
        }
    }
};
#include <vector>
using namespace std;

class Solution {
public:
    // lowerBound returns the first index i with nums[i] >= target
    // (or nums.size() if every element is smaller). This is std::lower_bound.
    int lowerBound(vector<int>& nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = (int)nums.size();

        // Note: lo < hi (not <=), because hi is exclusive.
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;

            if (nums[mid] < target) {
                // mid is too small, so the answer is strictly to its right.
                lo = mid + 1;
            } else {
                // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
                hi = mid;
            }
        }

        // lo == hi: the first position where target could be inserted in order.
    }
};
#include <vector>
using namespace std;

class Solution {
public:
    // lowerBound returns the first index i with nums[i] >= target
    // (or nums.size() if every element is smaller). This is std::lower_bound.
    int lowerBound(vector<int>& nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = (int)nums.size();

        // Note: lo < hi (not <=), because hi is exclusive.
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;

            if (nums[mid] < target) {
                // mid is too small, so the answer is strictly to its right.
                lo = mid + 1;
            } else {
                // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
                hi = mid;
            }
        }

        // lo == hi: the first position where target could be inserted in order.
        return lo;
    }
};
#include <vector>
using namespace std;

class Solution {
public:
    // lowerBound returns the first index i with nums[i] >= target
    // (or nums.size() if every element is smaller). This is std::lower_bound.
    int lowerBound(vector<int>& nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = (int)nums.size();

        // Note: lo < hi (not <=), because hi is exclusive.
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;

            if (nums[mid] < target) {
                // mid is too small, so the answer is strictly to its right.
                lo = mid + 1;
            } else {
                // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
                hi = mid;
            }
        }

        // lo == hi: the first position where target could be inserted in order.
        return lo;
    }

    // upperBound returns the first index i with nums[i] > target. The ONLY change
    // from lowerBound is <= instead of <, which steps past equal elements too.
};
#include <vector>
using namespace std;

class Solution {
public:
    // lowerBound returns the first index i with nums[i] >= target
    // (or nums.size() if every element is smaller). This is std::lower_bound.
    int lowerBound(vector<int>& nums, int target) {
        // Half-open window [lo, hi). hi starts at len so "not found" can return it.
        int lo = 0, hi = (int)nums.size();

        // Note: lo < hi (not <=), because hi is exclusive.
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;

            if (nums[mid] < target) {
                // mid is too small, so the answer is strictly to its right.
                lo = mid + 1;
            } else {
                // mid might BE the boundary, so keep it in range (hi = mid, not mid-1).
                hi = mid;
            }
        }

        // lo == hi: the first position where target could be inserted in order.
        return lo;
    }

    // upperBound returns the first index i with nums[i] > target. The ONLY change
    // from lowerBound is <= instead of <, which steps past equal elements too.
    int upperBound(vector<int>& nums, int target) {
        int lo = 0, hi = (int)nums.size();
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;
            if (nums[mid] <= target) {
                lo = mid + 1;
            } else {
                hi = mid;
            }
        }
        return lo;
    }
};

Tap the left half to go back, the right half to go forward.

Arrow keys or space to navigate · Esc to exit.