zoukankan      html  css  js  c++  java
  • 二分查找法

    https://www.zhihu.com/search?q=%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE&utm_content=search_history&type=content

    C++ <algorithm>的四个二分查找函数:搜索区间为[first, last),左闭右开区间

    1.lower_bound(val) 返回第一个不小于val的位置,若不存在,返回last

    2.upper_bound(val) 返回第一个大于val的位置,若不存在,返回last

    3.equal_range(val) 返回[lower_bound(val), upper_bound(val)]

    4.binary_search(val) 在搜索区间内是否有元素==val(其实是调用lower_bound来判断)

    二分查找法可以分为求上下界两种:

    1.求下界,即找满足 x>= val 或 x > val 条件的最小x的位置,分别对应lower_bound 和 upper_bound

    2.求上界,即找满足x < val 或 x <= val 条件的最大x的位置,可以调用互补的求下界的函数再减一得到,如 x >= val 的下界再减一就是x < val的上界,x > val 的下界再减一就是x <= val 的上界

    int lowerBound(vector<int>& arr, int l, int r, int val){
        while(l < r){
            int m = l + (r - l) / 2;
            if(arr[m] < val) l = m + 1;
            else r = m;
        }
        return l;
    }
    
    int upperBound(vector<int>& arr, int l, int r, int val){
        while(l < r){
            int m = l + (r - l) / 2;
            if(arr[m] <= val) l = m + 1;
            else r = m;
        }
        return l;
    }

    Leetcode33. Search in Rotated Array

    class Solution {
    public:
        int search(vector<int>& nums, int target) {
            int n = nums.size();
            int l = 0, r = n - 1;
            while(l < r){
                int m = l + (r - l) / 2;
                if(nums[m] > nums[r]) l = m + 1;
                else r = m;
            }
            int rot = l;
            l = 0, r = n - 1;
            while(l <= r){
                int m = l + (r - l) / 2;
                int realmid = (m + rot) % n;
                if(nums[realmid] == target) return realmid;
                else if(nums[realmid] < target) l = m + 1;
                else r = m - 1;
            }
            return -1;
        }
    }

      mid 把区间分为两半,其中一半必然有序,另一半还是rotated,根据 target 是否在有序的那一半中,就可以更新 left 或 right 了。

    public:
        int search(vector<int>& nums, int target) {
            int n = nums.size();
            int l = 0, r = n - 1, mid;
            while (l <= r) {
                mid = l + ((r - l) >> 1);
                if (nums[mid] == target) return mid;
                if (nums[mid] >= nums[l]) {
                    if (target < nums[mid] && target >= nums[l]) {
                        r = mid - 1;
                    }
                    else {
                        l = mid + 1;
                    }
                }
                else {
                    if (target >nums[mid] && target <= nums[r]) {
                        l = mid + 1;
                    }
                    else {
                        r = mid - 1;
                    }
                }
            }
            return -1;
        }
    };

    Leetcode81. Search in Rotated Sorted Array II

     

    //方法1
    class Solution {
    public:
        bool search(vector<int>& nums, int target) {
            int l = 0, r = nums.size() - 1, m;
            while(l <= r){
                m = l + (r - l) / 2;
                if(nums[m] == target) return true;
                if((nums[l] == nums[m]) && (nums[m] == nums[r])) {
                    ++l;--r;
                }
                else if(nums[l] <= nums[m]){
                    if((nums[l] <= target) && (nums[m] > target)) r = m - 1;
                    else l = m + 1;
                }
                else{
                    if((nums[m] < target) && (nums[r] >= target)) l = m + 1;
                    else r = m - 1;
                }
            }
            return false;
        }
    };
    
    //方法2:先二分查找pivot,再二分查找target
    class Solution {
    public:
        bool search(vector<int>& nums, int target) {
            int n = nums.size();
            int l = 0, r = n - 1;
            while(l < r){
                int m = l + (r - l) / 2;
                if(nums[m] > nums[r]) l = m + 1;
                else if(nums[m] < nums[r]) r = m;
                else{
                    if(nums[r - 1] > nums[r]){
                        l = r;
                        break;
                    }
                    r--;
                }
            }
            int pivot = l;
            cout << pivot;
            l = 0, r = n;
            while(l < r){
                int m = l + (r - l) / 2;
                int realmid = (m + pivot) % n;
                if(nums[realmid] < target) l = m + 1;
                else r = m;
            }
            return l != n && nums[(l + pivot) % n] == target;
        }
    };

     Leetcode153. Find Minimum in Rotated Sorted Array

    class Solution {
    public:
        int findMin(vector<int>& nums) {
            int n = nums.size();
            int l = 0, r = n - 1, m;
            while(l < r){
                m = l + (r - l) / 2;
                if(nums[m] > nums[r]) l = m + 1;
                else r = m;
            }
            return nums[l];
        }
    };

    Leetcode154. Find Minimum in Rotated Array II

    class Solution {
    public:
        int findMin(vector<int>& nums) {
            int l = 0, r = nums.size() - 1;
            while(l < r){
                int m = l + (r - l) / 2;
                if(nums[m] > nums[r]) l = m + 1;
                else if(nums[m] < nums[r]) r = m;
                else{
                    if(nums[r - 1] > nums[r]){
                        l = r;
                        break;
                    }
                    r--;
                };
            };
            return nums[l];
        }
    };

    Leetcode34. Find First and Last Position of Element in Sorted Array

    class Solution {
    public:
        vector<int> searchRange(vector<int>& nums, int target) {
            int l = lowerBound(nums, 0, nums.size(), target);
            int r = lowerBound(nums, 0, nums.size(), target + 1);
            if(l == nums.size() || nums[l] != target) return {-1, -1};
            else return {l, r - 1};
        }
        
        int lowerBound(vector<int>& arr, int l, int r, int target){
            while(l < r){
                int m = l + (r - l) / 2;
                if(arr[m] < target) l = m + 1;
                else r = m;
            }
            return l;
        }
        
    };

    Leetcode69. Sqrt(x)

    class Solution {
    public:
        int mySqrt(int x) {
            if(x == 1) return 1; //寻找num * num <= x的num的最大值,相当于找x的upperbound
            int l = 1, r = x;
            while(l < r){
                int m = l + (r - l) / 2;
                if(m <= x / m) l = m + 1;
                else r = m;
            }
            return l - 1;
        }
    };
  • 相关阅读:
    商户编号前三位代码对应的收单机构大全
    使用邮件模板(freemarker.jar)发送邮件
    Struts2自定义拦截器
    如何在jsp页面显示存储在数据库的图片
    正则表达式 大于0的数字(包含小数)
    Linux的关机命令
    maven的下载和安装
    web.py的安装
    安装第三方插件BeautifulSoup
    myeclipse离线安装pydev插件
  • 原文地址:https://www.cnblogs.com/betaa/p/11530754.html
Copyright © 2011-2022 走看看