LeetCode81-搜索旋转排序数组 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 可能包含重复元素。
  • 这会影响到程序的时间复杂度吗?会有怎样的影响,为什么?

一、思路

假设原来升序的数组是nums,当其经过一次旋转后,得到两个升序数组nums1和nums2,由这两个升序数组构成一个旋转数组nums_rotate,假设nums1在前

那么有: n u m s 1 [ 0 ] > = n u m s 2 [ n u m s 2. s i z e ( ) 1 ] nums1[0] >= nums2[nums2.size() - 1]

在前面的那个数组nums1,其所有元素都大于或等于后面的数组nums2

利用这个性质可以对数组进行快速检索

(一)从target的位置开始考虑

我们知道target一定在两个数组中的一个,那么可以通过确定target的位置,来决定两边指针的移动方向。

设两个指针为lo与hi,中间的指针为mid

将数组划分为两个前一个大的数组为nums1,后一个小的数组为nums2

(1)假设target在nums1中

那么必然有: n u m s [ h i ] < = t a r g e t nums[hi]<=target

(2)假设target在nums2中

那么必然有: n u m s [ l o ] > = t a r g e t nums[lo]>=target

相比较于无重复的数组,有重复的最大问题是无法根据 n u m s [ l o ] nums[lo] n u m s [ h i ] nums[hi] 来确定 n u m s [ m i d ] nums[mid] 处在哪个数组,因此也无法制定移动策略

例如:

[1,1,5,1,1,1,1,1,1,1,1,1,1,1,1]
5

在这个例子中,我们只知道 n u m s [ m i d ] = 1 nums[mid]=1 ,但是无法找出mid处于哪个有序数组

如果mid在前一个数组,那么应该改变lo

如果mid在后面的数组,那么应该改变hi

因为不知道是哪一种情况,所以同时改变lo与hi,向mid逼近

C++代码:

class Solution {
public:
	bool search(vector<int>& nums, int target) {
		if (nums.empty())
			return false;
		int lo = 0, hi = nums.size() - 1;
		int mid;
		while (lo <= hi) {
			mid = lo + ((hi - lo) >> 1);
			if (nums[mid] == target || nums[lo] == target || nums[hi] == target)
				return true;
			// 在前一个数组的情况
			if (target > nums[lo]) {
				if (target < nums[mid])	//target 在lo与mid之间
					hi = mid - 1;
				else {
					if (nums[mid] > nums[lo])	//target 在mid与hi之间
						lo = mid + 1;
					else if (nums[mid] < nums[lo])	//target 在lo与mid之间
						hi = mid - 1;
					else {
						if (nums[lo] == nums[hi]) {	//target 在lo与mid之间 或者是 mid与hi之间
							hi--;
							lo++;
						}
						else
							lo = mid + 1;			//target 在mid与hi之间
					}
				}
			}	// 在后一个数组的情况
			else if (target < nums[hi]) {
				if (target > nums[mid])	//target 在mid与hi之间
					lo = mid + 1;
				else {
					if (nums[mid] > nums[hi])	//target 在mid与hi之间
						lo = mid + 1;
					else if (nums[mid] < nums[hi])	//target 在lo与mid之间
						hi = mid - 1;
					else {
						if (nums[lo] == nums[hi]) {	//target 在lo与mid之间 或者是 mid与hi之间
							hi--;
							lo++;
						}
						else
							hi = mid - 1;			//target 在mid与hi之间
					}
				}
			}
			else
				return false;
		}
		return false;
	}
};

执行效率:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/lyd1995/article/details/89220949
今日推荐