0
点赞
收藏
分享

微信扫一扫

牛客题霸面试真题——二分:BM17 二分查找-I BM18 二维数组中的查找 BM19 寻找峰值 BM20 数组中的逆序对 BM21 旋转数组的最小数字 BM22 比较版本号

绪风 2022-04-03 阅读 48

文章目录

BM17 二分查找-I

二分使用的前提:数组中无重复元素、且有序。

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param nums int整型vector 
     * @param target int整型 
     * @return int整型
     */
    int search(vector<int>& nums, int target) {
        // write code here
        int l = 0, r = nums.size() - 1;
        while(l <= r){
            int mid = l + (r - l) / 2;
            if(nums[mid] > target) r = mid - 1;
            else if(nums[mid] < target ) l = mid + 1;
            else return mid;
        }
        return -1;
    }
};

BM18 二维数组中的查找

https://www.nowcoder.com/practice/abc3fe2ce8e146608e868a70efebf62e
在这里插入图片描述
请添加图片描述

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        //行或列为空时数组为空,返回false
        if(array.size()==0||array[0].size()==0) return false;
        int i = 0, j = array[0].size()-1;
        while(i<array.size()&&j>=0){
            if(target<array[i][j]) j--;
            else if(target>array[i][j]) i++;
            else return true;
        }
        return false;
    }
};

BM19 寻找峰值

https://www.nowcoder.com/practice/fcf87540c4f347bcb4cf720b5b350c76
在这里插入图片描述
请添加图片描述

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param nums int整型vector 
     * @return int整型
     */
    
    int findPeakElement(vector<int>& nums) {
        // write code here
        int l = 0, r = nums.size() - 1;
        while(l<r){
            int mid = l + (r - l) / 2;
            // 右边是下坡路,不一定有波峰,所以r=mid
            if(nums[mid] > nums[mid + 1]) r = mid;
            // 右边是上坡路,一定有波峰,所以r=mid+1
            else l = mid + 1;
        }
        //跳出循环时l>=r,l肯定是因为多跳了一步导致超过r或者与r重合
        //此时结果区间不能继续更新,所以跳出时就找到了波峰,返回r
        return r;
    }
};

此题一个隐含做法就是找最大值,最大值一定是波峰。

BM20 数组中的逆序对

https://www.nowcoder.com/practice/96bd6684e04a44eb80e6a68efc0ec6c5
在这里插入图片描述
可以使用归并排序的思想解,当右序列与左序列合并时且右序列的值<左序列才出现逆序对,逆序对的数量res += i - mid + 1(因为左序列是有序的所以在i右侧的都比j大,都会形成逆序对)。
具体细节参见本人这篇文章:https://blog.csdn.net/qq_46126258/article/details/119893952#3_105

class Solution {
public:
    int mergeSort(vector<int> &a,int l,int r){
        if(l>=r) return 0;
        int mid = (l + r) >> 1;
        int res = (mergeSort(a,l,mid) + mergeSort(a,mid+1,r))%1000000007;
        int i=l,j=mid+1;
        vector<int> tmp;//用于合并左右序列的临时数组
        while(i<=mid && j<=r){
            if(a[i]<=a[j]){
                tmp.push_back(a[i++]);
            }else{
                tmp.push_back(a[j++]);
                res += mid - i + 1;
            }
        }
        //将剩下的放在tmp后面
        while(i<=mid) tmp.push_back(a[i++]);
        while(j<=r) tmp.push_back(a[j++]);
        
        //更新a
        for(int i=l,j=0;i<=r;i++,j++) a[i]=tmp[j];
        return res%1000000007;
    }
    int InversePairs(vector<int> data) {
        return  mergeSort(data,0, data.size()-1);
    }
};

BM21 旋转数组的最小数字

https://www.nowcoder.com/practice/9f3231a991af4f55b95579b44b7a01ba
在这里插入图片描述
思想参考自:https://blog.nowcoder.net/n/770b93c590f149af876b34dcf252c009
根据mid位置的值和右端的值判断旋转点的位置:

  • a[mid] > a[r] :旋转点在 [ mid + 1, r ] 之间,所以左端 l 更新为 mid + 1
  • a[mid] < a[r] :旋转点在 [ l, mid ] 之间,所以右端 r 更新为 mid
  • a[mid] = a[r] :不能确定旋转点在左半段还是右半段,所以右端 r 更新为 r - 1 缩小判断区间

跳出循环时 l==r 此时返回二者位置之一都可以

class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {
        int l = 0, r = rotateArray.size()-1;
        while(l<r){
            int mid = (l + r) >> 1;
            if(rotateArray[mid]>rotateArray[r]) l = mid + 1;
            else if(rotateArray[mid]<rotateArray[r]) r = mid;
            else r--;
        }
        return rotateArray[l];
    }
};

BM22 比较版本号

https://www.nowcoder.com/practice/2b317e02f14247a49ffdbdba315459e7
在这里插入图片描述
在这里插入图片描述
此题需要注意的是,比较的是相同位置的字符串对应的数字的大小,单个比较对应位置的字符是不对的。由示例5就可知只比较对应位置的字符的ASCII得出的结果是226<36但实际上数字226>36,所以一定要将字符串化为数字才能进行比较.

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 比较版本号
     * @param version1 string字符串 
     * @param version2 string字符串 
     * @return int整型
     */
    int compare(string version1, string version2) {
        // write code here
        int length1 = version1.size(),length2 = version2.size();
        int i = 0, j = 0;//i指向v1,j指向v2
        while(i < length1 || j < length2){
            int num1 = 0, num2 = 0;
            //求当前的num1
            while(i < length1 && version1[i]!='.'){
                num1 = num1 * 10 + (version1[i]-'0');
                i++;
            }
            //求当前的num2
            while(j < length2 && version2[j]!='.'){
                num2 = num2 * 10 + (version2[j]-'0');
                j++;
            }
            //cout<<num1<<" "<<num2<<endl;
            if(num1 > num2) return 1;
            else if(num1 < num2) return -1;
            //指针都后移,指向下一个数字的开始
            i++;
            j++;
        }
        return 0;
    }
};
举报

相关推荐

0 条评论