Binary Search Techniques and Applications

This week's practice focuses on mastering binary search algorithms through LeetCode problems.

The first problem is Binary Search. Below is the implementation:

int search(int* nums, int numsSize, int target) {
    int left = 0;
    int right = numsSize - 1;

    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] == target)
            return mid;
        else if (nums[mid] < target)
            left = mid + 1;
        else
            right = mid - 1;
    }

    return -1;
}

Another variant of this problem is Search Insert Position. Here's an alternative solusion using a linear scan:

int searchInsert(int* nums, int numsSize, int target) {
    for (int i = 0; i < numsSize; i++) {
        if (nums[i] >= target)
            return i;
    }
    return numsSize;
}

A more optimized version using binary search is shown below:

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int left = 0, right = nums.size() - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] < target)
                left = mid + 1;
            else
                right = mid - 1;
        }
        return left;
    }
};

For Find First and Last Position of Element in Sorted Array, we can use two binary searches to locate the boundaries:

int searchBoundary(int* nums, int numsSize, int target, bool isLeft) {
    int left = 0, right = numsSize - 1, ans = numsSize;

    while (left <= right) {
        int mid = (left + right) / 2;
        if (nums[mid] > target || (isLeft && nums[mid] >= target)) {
            right = mid - 1;
            ans = mid;
        } else {
            left = mid + 1;
        }
    }

    return ans;
}

int* searchRange(int* nums, int numsSize, int target, int* returnSize) {
    int* ret = malloc(sizeof(int) * 2);
    memset(ret, -1, sizeof(ret));
    *returnSize = 2;

    int l = searchBoundary(nums, numsSize, target, true),
        r = searchBoundary(nums, numsSize, target, false) - 1;

    if (l != numsSize && nums[l] == target)
        ret[0] = l, ret[1] = r;

    return ret;
}

An efficient approach involves separate functions for finding left and right boundaries:

int findLeftBound(int* nums, int numsSize, int target) {
    int left = 0, right = numsSize - 1;

    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] < target)
            left = mid + 1;
        else if (nums[mid] > target)
            right = mid - 1;
        else
            right = mid - 1;
    }

    if (left < 0 || left >= numsSize)
        return -1;

    return nums[left] == target ? left : -1;
}

int findRightBound(int* nums, int numsSize, int target) {
    int left = 0, right = numsSize - 1;

    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] < target)
            left = mid + 1;
        else if (nums[mid] > target)
            right = mid - 1;
        else
            left = mid + 1;
    }

    if (right < 0 || right >= numsSize)
        return -1;

    return nums[right] == target ? right : -1;
}

int* searchRange(int* nums, int numsSize, int target, int* returnSize) {
    int* res = (int*)malloc(sizeof(int) * 2);
    res[0] = findLeftBound(nums, numsSize, target);
    res[1] = findRightBound(nums, numsSize, target);
    *returnSize = 2;
    return res;
}

In Sqrt(x), binary search is used to find the integer square root:

int mySqrt(int x) {
    int left = 0, right = x, ans = -1;

    while (left <= right) {
        int mid = left + (right - left) / 2;
        if ((long long)mid * mid <= x) {
            ans = mid;
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }

    return ans;
}

For Valid Perfect Square, one can also use a mathematical property involving odd numbers:

bool isPerfectSquare(int num) {
    int odd = 1;
    while (num > 0) {
        num -= odd;
        odd += 2;
    }
    return num == 0;
}

Alternatively, a binary search approach can be applied:

bool isPerfectSquare(int num) {
    int left = 0, right = num;
    while (left <= right) {
        int mid = (right - left) / 2 + left;
        long square = (long)mid * mid;
        if (square < num)
            left = mid + 1;
        else if (square > num)
            right = mid - 1;
        else
            return true;
    }
    return false;
}

It's crucial to memorize the binary search framework and distinguish between closed intervals [left, right] and half-open intervals [left, right). Exploring variations of binary search will further enhance understanding.

Tags: Binary Search algorithm LeetCode programming search algorithm

Posted on Mon, 08 Jun 2026 18:45:49 +0000 by canabatz