leetcode原题:搜索旋转数组

题目:

给定一个排序后的数组,包含n个整数,但这个数组已被旋转过很多次了,次数不详。请编写代码找出数组中的某个元素,假设数组元素原先是按升序排列的。若有多个相同元素,返回索引值最小的一个。

这道题是旋转次数不祥,但至少一次,前面发过一篇只旋转一次的旋转排序数组,可参考:

搜索旋转排序数组_蛋堡\的博客-CSDN博客

示例:

 输入: arr = [15, 16, 19, 20, 25, 1, 3, 4, 5, 7, 10, 14], target = 5
 输出: 8(元素5在该数组中的索引)


 输入:arr = [5,5,5,1,2,3,4,5], target = 5
 输出:0

解题思路:

本题我们采用二分法来解决。

1.确定左区间(left,mid)是升序的,如果目标值在左区间里,说明目标值就在左边序列,否则在右边

2.不确定左区间是升序的,(arr[left]<=target||target<=arr[mid]),这两个任意满足一个,都说明目标值在左区间里,不满足,则说明在右区间

3.遇到arr[left]==arr[mid]的情况,有可能是已经找到了目标值,还有可能是遇到重复值了,如果遇到了重复值,就要清除重复值。

code:

class Solution {
public:
    int search(vector<int>& arr, int target) {
        int n=arr.size();
        if(n==1 && arr[0]!=target) return -1;
        int left=0;
        int right=n-1;
        while(left<right)
        {
            int mid=left+(right-left)/2;
            //左边区间是升序的
            if(arr[left]<arr[mid])
            {
                //目标值处于arr[left]和arr[mid]之间,一定是在左边序列
                if(target<=arr[mid]&&target>=arr[left])
                {
                    right=mid;
                }
                //目标值在右边序列
                else
                {
                    left=mid+1;
                }
            }
            //左边区间不是升序
            else if(arr[left]>arr[mid])
            {
                //目标值在左边序列
                if(arr[left]<=target||target<=arr[mid])
                {
                    right=mid;
                }
                //目标值在右边序列
                else
                {
                    left=mid+1;
                }
            }
            //遇到重复值,或者是已经找到了目标
            else if(arr[left]==arr[mid])
            {
                //不等于target,说明还没找到
                if(arr[left]!=target)
                {
                    left++;//清除重复值
                }
                //找到了,直接将left赋值给right,将会结束循环
                else
                {
                    right=left;
                }
            }
        }
        //如果arr[left]等于目标值,说明找到了,直接返回下标
        //否则,说明没找到,返回-1
        return (arr[left]==target)?left:-1;
    }
};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值