[leetcode 81] Search in Rotated Sorted Array II

题目描述:

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

Write a function to determine if a given target is in the array.


The array may contain duplicates.


解题思路(1):题目要求我们找到具体的值,最简单的方法肯定是扫描一遍,然后就找到了,于是我们的事件复杂度是0(n),但是放在这里肯定有更好的方法。我们可以找到转折的那个点比如4,5,6,7,0,1,2转折点是7,7左边都比4(最左边)小,7的右边都比4小。二分可以找到,找到这个点之后,后面的就好办了,我们拆成了俩个有序的数组,每一个再用二分方法来查找,最后的结果时间复杂度为0(log^{n} ).下面我说一下如何二分找到那个关键点位置,当num[mid]对应的值比最左边值大的时候,转折点肯定在右边,那么将left改为mid+1,当num[mid]对应的值比最左边值小的时候,转折点肯定在左边,这时将right = mid-1,当等于的时候,left++,那么出来while循环,找到的就是转折点的位置.


解题思路(2):本题采用二分法实现,但是比较挠头的是边界问题,而且元素有重复,相比纯粹递增的数组难度要大得多,要解决这个问题,首先要对所有可能情况进行分类,然后对每种可能的类别进行相应的处理,本题的类别可以表示为下面的趋势图


暂且不考虑nums[mid] = nums[left]的情况,本题大致可以简化为上图两种情况,可能的情况划分出来,那么解决本题就比较容易了:

当 nums[mid] = nums[left] 时,这时由于很难判断 target 会落在哪,那么只能采取 left++

当 nums[mid] > nums[left] 时,这时可以分为两种情况,判断左半部比较简单(如果target不在左边这部分,那么我们是可以直接去掉左边这部分的)

当 nums[mid] < nums[left] 时,这时可以分为两种情况,判断右半部比较简单(如果target不在右边这部分,那么我们也是可以直接去掉右边这部分的)

C++代码如下:

作者:忆臻
链接:https://zhuanlan.zhihu.com/p/24973495
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {
public:
    bool search(vector<int>& nums, int target) {
        //扫描一遍肯定可以,那么放在这里不是这么简单的,是希望我们用log级别的
        //方法一我们先用师兄的做法,先二分找到那个边界,然后分开进行二分查找即可~
        //方法二用下面这种方法
        
        int len = nums.size();
        int left = 0,right = len-1;
        while(left<=right)
        {
            int mid = (left+right)/2;
            if(nums[mid] == target)
            {
                return true;
            }
            if(nums[mid]==nums[left])
                left++;
            else if(nums[mid]>=nums[left])        //砍掉的一半一定要是可以砍掉的
                {
                    if(target<=nums[mid]&&target>=nums[left])
                        right = mid-1;
                    else
                        left = mid+1;
                    
                }
            else
            {
                if(nums[mid]< target&&target<=nums[right])
                    left = mid+1;
                else
                    right = mid-1;
            }
        }
        return false;
    }
};
python代码:
作者:忆臻
链接:https://zhuanlan.zhihu.com/p/24973495
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: bool
        """
        left = 0
        right = len(nums)-1
        
        while left<=right:
            mid = (left + right)/2
            if nums[mid] == target:
                return True
            if nums[mid] == nums[left]:
                left +=1
            elif nums[mid] > nums[left]:                    #这样就是有序了
                if target<nums[mid] and target>=nums[left]:
                    right = mid-1
                else:
                    left = mid+1
            else:
                if target > nums[mid] and target<=nums[right]:
                    left = mid+1
                else:
                    right = mid-1
        return False

知乎主页:忆臻
专栏地址:机器学习算法
博客地址:忆臻博客




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值