二分法写法总结(c++实现)

以LeetCode上这个题为例:34. 在排序数组中查找元素的第一个和最后一个位置

参考自这个解析.

主要是方便以后自己好复习

1. 搜索一个值

int binary_search(int[] nums, int target) {
    int left = 0, right = nums.length - 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 if(nums[mid] == target) {
            // 直接返回
            return mid;
        }
    }
    // 直接返回
    return -1;
}

2.搜索左右边界:

#include <iostream>
#include <vector>
#include "unistd.h"
using namespace std;

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
    	// 开区间写法
        // int l = searchLeft(nums, target);
        // int r = searchRight(nums, target);
        // return {l, r}; 

		// 闭区间写法
        int left = left_bound(nums, target);
        int right = right_bound(nums, target);
        return {left, right}; 
    }

    // 开区间写法 [left, right)
    int searchLeft(vector<int>& nums, int target){
        if(nums.size() == 0) return -1;
        int l = 0;
        int r = nums.size();
        while(l < r){
            int m = (l + r) >> 1;
            if(nums[m] >= target){
                r = m;
            }
            else if(nums[m] < target){
                l = m  + 1;
            }
        }
        // 边界检查
        // if(l == nums.size()) return -1;
        return (nums[l] == target)? l : -1;
    }
    
	// 开区间写法 [left, right)
    int searchRight(vector<int>& nums, int target){
        if(nums.size() == 0) return -1;
        int l = 0;
        int r = nums.size();
        while(l < r){
            int m = (l + r) >> 1;
            if(nums[m] <= target){
                l = m + 1;
            }
            else if(nums[m] > target){
                r = m;
            }
        }
        // 边界检查
        // if(l == 0) return -1; // 这里返回值代表比target小的数字个数
        return nums[l-1] == target? l - 1 : -1;
    }

    // 闭区间写法 [left, right]
    int left_bound(vector<int>& nums, int target){
        if(nums.size() == 0) return -1;
        int left = 0;
        int right = nums.size() - 1;
        while(left <= right){
            int mid = (left + right) >> 1;
            if(nums[mid] == target){
                right = mid - 1;
            }
            else if(nums[mid] < target){
                left = mid + 1;
            }
            else if(nums[mid] > target){
                right = mid - 1;
            }
        }

        // 边界检查
        if(left >= nums.size() || nums[left] != target) return -1;
        return left;
    }

    // 闭区间写法 [left, right]
    int right_bound(vector<int>& nums, int target){
        if(nums.size() == 0) return -1;
        int left = 0;
        int right = nums.size() - 1;
        while(left <= right){
            int mid = (left + right) >> 1;
            if(nums[mid] == target){
                left = mid + 1;
            }
            else if(nums[mid] < target){
                left = mid + 1;
            }
            else if(nums[mid] > target){
                right = mid - 1;
            }
        }

        // 边界检查 [left, right]
        if(right < 0 || nums[right] != target) return -1;
        return right;
    }
};

int main()
{
    Solution sol;
    vector<int> nums = {5,7,7,8,8,10};
    int target = 8;
    int target1 = 0;
    int target2 = 12;
    vector<int> res = sol.searchRange(nums, target);
    vector<int> res1 = sol.searchRange(nums, target1);
    vector<int> res2 = sol.searchRange(nums, target2);
    cout << res[0] << " " << res[1] << endl;
    cout << res1[0] << " " << res1[1] << endl;
    cout << res2[0] << " " << res2[1] << endl;

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值