【leetcode】81. Search in Rotated Sorted Array II

题目:
在这里插入图片描述


思路:

  1. 利用剑指offer第11题的代码(稍作修改),找到数组旋转之前的起始元素。
  2. 通过步骤1,我们就可以将旋转数组分成两个升序序列。通过将target与旋转数组第一个元素比较,判断target是在哪一部分,然后用二分法查找即可。Runtime 4ms,还是比较快的。

另一思路:找到旋转的那个位置,然后错位进行二分查找。


代码实现:

class Solution {
public:
    int MinInOrder(const vector<int>& numbers, int index1, int index2) {
    
        for (int i = 1; i < numbers.size(); i++) {
            if (numbers[i - 1] > numbers[i]) {
                return i;
            }
        }

        return 0;
    }

    int IndOfMin(const vector<int> &numbers, int length) {
        if (length <= 0) {
            assert(0);
        }

        int index1 = 0;
        int index2 = length - 1;
        int indexMid = index1;

        while (numbers[index1] >= numbers[index2]) {
            if (index2 - index1 == 1) {
                indexMid = index2;
                break;
            }

            indexMid = (index1 + index2) / 2;

            if (numbers[index1] == numbers[index2] && numbers[index2] == numbers[indexMid]) { //我的分析:只要第一次三者不全相等,则就没问题
                return MinInOrder(numbers, index1, index2);
            }

            if (numbers[indexMid] >= numbers[index1]) {	//等号是必须的,否则可能会不进行任何更新,陷入死循环。
                index1 = indexMid; //因为这个if在前,所以在index1,index2,indexMid的元素值相等时,搜寻空间倾向于右面,所以可能出错。
            }
            else if (numbers[indexMid] <= numbers[index2]) {
                index2 = indexMid;
            }
        }

        return indexMid;
    }
    
    bool binaryFind(vector<int>& nums, int begin, int end, int target){
        int mid;
        while (begin <= end){
            mid = begin + (end - begin) / 2;
            if (nums[mid] == target){
                return true;
            }else if (nums[mid] > target){
                end = mid - 1;
            }else{
                begin = mid + 1;
            }
        }
        return false;
    }
    
    bool search(vector<int>& nums, int target) {
        if (nums.size() <= 0){
            return false;
        }
        
        int ind = IndOfMin(nums, nums.size());
        bool ans;
        if (target == nums[0]){
            return true;
        }else if (target > nums[0]){
            if (ind - 1 >= 0){
                ans = binaryFind(nums, 0, ind-1, target);
            }else{
                ans = binaryFind(nums, 0, nums.size()-1, target);
            }
        }else{
            ans = binaryFind(nums, ind, nums.size()-1, target);
        }
        
        return ans;
    }
};

discuss:

class Solution {
public:
    bool search(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size() - 1;
        int mid;
        
        while (left <= right){
            mid = (left + right) >> 1;
            
            if (nums[mid] == target) return true;
            
            if ((nums[left] == nums[mid]) && (nums[right] == nums[mid])) { // 如果三者相等,两头向内缩小
                ++left;
                --right;
            }else if (nums[left] <= nums[mid]){ // 在高区
                if ((nums[left] <= target) && (nums[mid] > target))  // 此处没有剖析细节,死记硬背吧
                    right = mid - 1;
                else
                    left = mid + 1;
            }else { // 在低区
                if ((nums[mid] < target) && (nums[right] >= target)) // 此处没有剖析细节,死记硬背吧
                    left = mid + 1;
                else
                    right = mid - 1;
            }
        }
        
        return false;
    }
};

在这里插入图片描述

错位进行二分查找:

class Solution {
public:
    bool search(vector<int>& nums, int target) {
        if (nums.size() == 0) return false;
        
        int r_len = 0;
        for (int i = 1; i < nums.size(); ++i){
            if (nums[i-1] > nums[i]){
                r_len = i;
                break;
            }
        }
        
        int left = 0;
        int right = nums.size()-1;
        
        while (left <= right){
            int mid = (left + right) / 2;
            if (nums[(mid+r_len)%nums.size()] == target){
                return true;
            }else if (nums[(mid+r_len)%nums.size()] > target){
                right = mid - 1;
            }else{
                left = mid + 1;
            }
        }
        
        return false;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值