33. 搜索旋转排序数组

33. 搜索旋转排序数组

二分法

将数组一分为二,则一定有 一部分是有序的,一部分是无序的 4 5 6 7 0 1 2

  1. 如果nums[r] > nums[mid] 则右边一定有序 0 1 2 (7_mid 0 1 2_r)
  2. 如果 nums[l] < nums[mid] 则左边一定有序 4 5 6 7 4_l 5 6 7 0_mid
  • 对有序部分的首尾元素进行判断,nums[mid] < target && nums[r] >= target 右边有序,且目标值大于队首 小于队尾,则一定在 有序部分中。 否则在无序部分中,

思路:如果中间的数小于最右边的数,则右半段是有序的,若中间数大于最右边数,则左半段是有序的,我们只要在有序的半段里用首尾两个数组来判断目标值是否在这一区域内,这样就可以确定保留哪半边了

class Solution {
public:
    int bis(const vector<int>& nums,int l,int r,int target){
        if(l>r) return -1;
        int mid = l+(r-l)/2;
        if(nums[mid] == target) return mid;
        if(nums[r] > nums[mid]){ //right 
            if(nums[mid] < target && nums[r] >= target)
                return bis(nums,mid+1,r,target);
            else
                return bis(nums,l,mid-1,target);
        }else{
            if(nums[mid] > target && nums[l] <= target )
                return bis(nums,l,mid-1,target);
            else
                return bis(nums,mid+1,r,target);
        }
    }

    int search(vector<int>& nums, int target) {
        int len = nums.size();
        if(!len) return -1;
        int index = bis(nums,0,len-1,target);
        return index;
    }
};



// 非递归 写法
 int search(vector<int>& nums, int target) {
        int len = nums.size();
        if(!len) return -1;
        int l=0,r=len-1;

        while(l<=r){
            int mid = (l+r)/2;
            if(nums[mid] == target) return mid;
            if(nums[r] > nums[mid]){
                if(nums[mid] < target && nums[r] >= target){
                    l = mid+1;
                }else
                    r = mid-1;
            }else{
                if(nums[mid] > target && nums[l] <=target ) r = mid-1;
                else l = mid+1;
            }
        }
        return -1;
    }

11.旋转数组的最小数字

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2][1,2,3,4,5]的一个旋转,该数组的最小值为1。

  • 如果中间的数小于右边的数,则右边有序 在左半段 继续查找
  • 如果中间数 大于 左边的数,则左边有序 在右边段 继续查找
  • 如果相等,则缩小搜索区间(去重) 2 2 2 0 1
class Solution {
public:
    int minArray(vector<int>& numbers) {
        // for(int j=numbers.size()-1;j>=1;j--){
        //     if(numbers[j-1] > numbers[j] ) return numbers[j];
        // }
        // return numbers[0];
        int l=0,r=numbers.size()-1;
        while(l<r){
            int mid = (r+l)/2;
            if(numbers[r] > numbers[mid])
                r = mid;
            else if(numbers[r] < numbers[mid])
                l = mid+1;
            else r--;
        }
        return numbers[l];
    }
};

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值