LeetCode 81. Search in Rotated Sorted Array II 搜索旋转排序数组 II

题目描述

假设按照升序排序的数组在预先未知的某个点上进行了旋转。

( 例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2] )。

编写一个函数来判断给定的目标值是否存在于数组中。若存在返回 true,否则返回 false。

示例 1:

输入: nums = [2,5,6,0,0,1,2], target = 0
输出: true
示例 2:

输入: nums = [2,5,6,0,0,1,2], target = 3
输出: false
进阶:

这是 搜索旋转排序数组 的延伸题目,本题中的 nums 可能包含重复元素。
这会影响到程序的时间复杂度吗?会有怎样的影响,为什么?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array-ii

思路

在一个经过了循环移位的有序数组(可能有重复元素)里进行查找,在有序数组里进行查找,肯定二分。
这题和33. Search in Rotated Sorted Array其实是类似的,唯一不同就是此题可能有重复元素。
但是基本思路不变,参考33题题解思路二
我们得到一个重要的想法:二分后左右两半至少有一半是有序的。所以我们可以判断target是否在这有序的一半,若在则丢弃掉另一半进入下一次循环,若不在则丢弃掉有序的这一半进入下一次循环。
那么如何判断哪一半是有序的呢?分为以下几种情况:

  1. nums[mid] == target,则返回true即可。
  2. nums[low] < nums[mid],则左半边一定有序;
  3. nums[low] > nums[mid],则右半边一定有序;
  4. 否则,我们无法判断到底哪一边有序,但是可以肯定的是nums[low] != target,所以此时我们直接low++然后进入下一循环。

最坏的情况就是数组中元素全相等且不等于target,此时时间复杂度为O(n)
空间复杂度O(1)

C++
class Solution {
public:
    bool search(vector<int>& nums, int target) {
        int mid, low = 0, high = nums.size() - 1;
        while(low <= high){
            mid = (high - low) / 2 + low;
            if(nums[mid] == target) return true;
            if(nums[low] < nums[mid]){
                if(nums[low] <= target && target < nums[mid]) high = mid - 1;
                else low = mid + 1;
            }
            else if(nums[low] > nums[mid]) {
                if(nums[mid] < target && target <= nums[high]) low = mid + 1;
                else high = mid - 1;
            }
            else low++;
        }
        return false;
    }
};
class Solution {
public:
    bool search(vector<int>& nums, int target) {
        int first = 0, last = nums.size();
        while(first != last){
        	const int mid = first + (last - first)/2;
        	if(target == nums[mid]) return true;
			if(nums[first] < nums[mid]){
	        	if(nums[first] <= target &&  target < nums[mid]) 
	        		last = mid; // [first, mid)
	        	else
	        		first = mid + 1; // [mid + 1, last)
			}else if(nums[first] > nums[mid]){
				if(nums[mid] < target && target <= nums[last-1])
					first = mid + 1; //[mid + 1, last)
				else
					last = mid; //[first, mid)
			}else{
				// skip duplicate one  极端形式[1,1,1,1,1] 中寻找2 
				first ++;
			}
		} 
        return false;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值