二分查找c++

C++实现二分查找算法详解

二分查找基础概念

二分查找(Binary Search)是一种在有序数组中查找特定元素的高效算法,时间复杂度为O(log n)。其核心思想是通过不断将搜索范围减半来快速定位目标值。

二分查找的实现

标准二分查找的实现通常包括以下步骤:

  1. 初始化左右边界leftright,通常为数组的起始和结束索引。
  2. 计算中间索引mid = left + (right - left) / 2(避免溢出)。
  3. 比较中间元素与目标值,调整左右边界缩小搜索范围。
int binarySearch(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) return mid;
        if (nums[mid] < target) left = mid + 1;
        else right = mid - 1;
    }
    return -1; // 未找到
}

二分查找的变种

  1. 查找第一个等于目标值的索引
    适用于有重复元素的情况,需检查左侧元素是否仍等于目标值。

    int findFirst(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) right = mid - 1;
            else left = mid + 1;
        }
        return (left < nums.size() && nums[left] == target) ? left : -1;
    }
    

  2. 查找最后一个等于目标值的索引
    检查右侧元素是否仍等于目标值。

    int findLast(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 (right >= 0 && nums[right] == target) ? right : -1;
    }
    

  3. 查找第一个大于等于目标值的索引
    可用于插入位置问题。

    int lowerBound(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) right = mid - 1;
            else left = mid + 1;
        }
        return left;
    }
    

  4. 查找第一个大于目标值的索引

    int upperBound(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) right = mid - 1;
            else left = mid + 1;
        }
        return left;
    }
    

二分查找的边界条件

  1. 循环条件left <= right确保所有元素被检查。
  2. 中间值计算:使用mid = left + (right - left) / 2避免溢出。
  3. 边界更新:根据比较结果更新leftright

二分查找的例题

  1. 搜索插入位置
    给定有序数组和目标值,返回目标值应插入的索引。

    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) return mid;
            if (nums[mid] < target) left = mid + 1;
            else right = mid - 1;
        }
        return left;
    }
    

  2. 在旋转排序数组中搜索
    数组可能在某点旋转,但仍部分有序。

    int searchRotated(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) return mid;
            if (nums[left] <= nums[mid]) {
                if (nums[left] <= target && target < nums[mid]) right = mid - 1;
                else left = mid + 1;
            } else {
                if (nums[mid] < target && target <= nums[right]) left = mid + 1;
                else right = mid - 1;
            }
        }
        return -1;
    }
    

  3. 寻找峰值元素
    峰值元素大于其相邻元素。

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

  4. 在排序数组中查找元素的第一个和最后一个位置
    结合变种二分查找实现。

    vector<int> searchRange(vector<int>& nums, int target) {
        int first = findFirst(nums, target);
        int last = findLast(nums, target);
        return {first, last};
    }
    

  5. x的平方根
    使用二分法近似计算平方根。

    int mySqrt(int x) {
        if (x <= 1) return x;
        int left = 1, right = x;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (mid == x / mid) return mid;
            if (mid < x / mid) left = mid + 1;
            else right = mid - 1;
        }
        return right;
    }
    

二分查找的应用场景

  1. 有序或部分有序数组的查找。
  2. 需要快速定位边界或极值的问题。
  3. 数学近似计算(如平方根)。

注意事项

  1. 确保数组有序或部分有序。
  2. 注意边界条件的处理,避免死循环或越界。
  3. 根据问题需求选择合适的变种实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值