二分查找刷题

本文提供了几种基于二分查找的算法实现,包括寻找目标值的位置,插入位置,搜索范围,找到数组中的峰值元素,以及使用归并排序计算逆序对和在旋转数组中找到最小元素的方法。此外,还涉及了一个比较版本号大小的函数。
摘要由CSDN通过智能技术生成

int search(vector<int>& nums, int target) {
        // write code here
        int i=0;int j=nums.size()-1;
        while(i<=j){
            int mid=(i+j)/2;
            if(nums[mid]>target){
                j=mid-1;
            }
            else if(nums[mid]<target){
                i=mid+1;
            }
            else{
                return mid;
            }
        }
        return -1;
    }

 

int searchInsert(vector<int>& nums, int target) {
        int i=0;int j=nums.size()-1;
        while(i<=j){
            int mid=(i+j)/2;
            if(nums[mid]>target){
                j=mid-1;
            }
            else if(nums[mid]<target){
                i=mid+1;
            }
            else{
                return mid;
            }
        }
        //例如1,3时找元素2,首先i,j会指向3,然后j指向1,跳出循环,所以返回i
        return i;
    }

 

vector<int> searchRange(vector<int>& nums, int target) {
        int i=0;int j=nums.size()-1;
        //先找右边界,方法为与目标值相等时移动左指针,右指针不动,使左指针逐步逼近右指针
        //如果0,0,0,0,1的话,最后一定是左指针0,右指针1.然后左指针也1,右指针0
        //0,0,0,0,0的情况,右指针不动,左指针会移出去
        while(i<=j){
            int mid=(i+j)/2;
            if(nums[mid]>target){
                j=mid-1;
            }
            else if(nums[mid]<target){
                i=mid+1;
            }
            else{
                i=mid+1;
            }
        }
        int right=j;
        //同理左边界
        i=0;j=nums.size()-1;
        while(i<=j){
            int mid=(i+j)/2;
            if(nums[mid]>target){
                j=mid-1;
            }
            else if(nums[mid]<target){
                i=mid+1;
            }
            else{
                j=mid-1;
            }
        }
        int left=i;
        //如果左右边界不重合
        if(right-left+1>0)return {left,right};
        else{
            return {-1,-1};
        }
    }

 

int findPeakElement(vector<int>& nums) {
        int left = 0;
        int right = nums.size() - 1;
        //二分法
        while(left < right){ //如果left==right了,那么此时一定是波峰了,不需要判断了
            int mid = (left + right) / 2;
            //右边是往下,不一定有坡峰
            if(nums[mid] > nums[mid + 1])
                right = mid;
            //右边是往上,一定能找到波峰
            else
                left = mid + 1;
        }
        //其中一个波峰
        return right; 
    }

 

int ret=0;
    void mergesort(vector<int>& data, vector<int>& tmp, int m, int n) {
        if (m == n)return;
        int k = (m + n) / 2;
        mergesort(data, tmp, m, k);
        mergesort(data, tmp, k + 1, n);
        merge_(data, tmp, m, k, n);
    }
    void merge_( vector<int>& data, vector<int>& tmp, int m, int k, int n) {
        int i = m;
        int j = k + 1;
        int t = 0;
        while (i != k + 1 && j != n + 1) {
            if (data[i] > data[j]) {
                tmp[t++] = data[j++];
                ret+=k-i+1;ret=ret%1000000007;
            } else {
                tmp[t++] = data[i++];
            }
        }
        while (i <= k) {
            tmp[t++] = data[i++];
        }
        while (j <= n) {
            tmp[t++] = data[j++];
        }
        for (int b = 0, i = m; i <= n; i++, b++) {
            data[i] = tmp[b];
        }
    }
    int InversePairs(vector<int> data) {
        vector<int>tmp(data.size(),0);
    mergesort(data, tmp, 0, data.size() - 1);
    return ret;
    }

 

int minNumberInRotateArray(vector<int> rotateArray) {
        int i=0;int j=rotateArray.size()-1;int mid=0;
        while(i<=j){
            mid=(i+j)/2;
            if(rotateArray[mid]<rotateArray[j]){//以j的值为比较,因为二分需要判断的值相同
                j=mid;//寻找到小的了,收缩区间,但不能为mid-1,因为不能确保mid不是最小的
            }
            else if(rotateArray[mid]>rotateArray[j]){
                i=mid+1;
            }
            else{
                j--;//如果相等了则收缩区间,收缩区间方式如果为j=mid的话跳不出循环
            }
        }
        return rotateArray[i];//最后肯定是j--后跳出循环,此时i是最小数字
    }

 

 int compare(string version1, string version2) {
        int n1 = version1.size();
        int n2 = version2.size();
        int i = 0, j = 0;
        //直到某个字符串结束
        while(i < n1 || j < n2){
            long long num1 = 0;
            //从下一个点前截取数字
            while(i < n1 && version1[i] != '.'){ 
                num1 = num1 * 10 + (version1[i] - '0');
                i++;
            }
            //version1[i] - '0'可以将字符型数字转换成整型数字,因为字符型数字和整型数字在ASCII码中是有对应关系的,'0'的ASCII码值是48,'1'的ASCII码值是49,以此类推,所以version1[i] - '0'实际上就是将字符型数字对应的ASCII码值减去'0'的ASCII码值得到整型数字。
            //跳过点
            i++; 
            long long num2 = 0;
            //从下一个点前截取数字
            while(j < n2 && version2[j] != '.'){ 
                num2 = num2 * 10 + (version2[j] - '0');
                j++;
            }
            //跳过点
            j++; 
            //比较数字大小
            if(num1 > num2) 
                return 1;
            if(num1 < num2)
                return -1;
        }
        //版本号相同
        return 0; 
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值