【LeetCode】33. Search in Rotated Sorted Array

题目:

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]).

You are given a target value to search. If found in the array return its index, otherwise return -1.

You may assume no duplicate exists in the array.

Your algorithm's runtime complexity must be in the order of O(log n).

Example 1:

Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4

Example 2:

Input: nums = [4,5,6,7,0,1,2], target = 3
Output: -1

 

描述:

在一个由升序数组循环左移未知单位所形成的数组中查找目标值,要求算法的复杂度为log ( n )

 

分析:

如果没有循环移动的操作,那么只需要使用二分搜索既能解决问题,

但是目前的数组并非整体有序,而是部分有序,而题目给出的复杂度,不难想象出,还是要采用二分的方法,但是需要对原始的二分进行修改,具体的策略见下面分析:

 

由于所给的数组是经过翻转之后的结果,可知,有序段最多有两个,而且关键是,某个段的所有值均大于另一个段的所有值,不妨命名为较大段和较小段,具体步骤如下:

 

若中间值等于目标值,则返回查找成功的下标

如果中间值小于目标值,则分两种情况:

1,中间值所在的有序段是较大段,则只需要在右半侧寻找

2,中间值所在的有序段是较小段,则需要再分情况讨论

1)若目标值小于较小段的最大值,则只需要在右半侧寻找

2)若目标值大于较小段的最大值,则只需要在左半侧寻找

如果中间值大于目标值,也分两种情况:

1,中间值所在的有序段是较大段,则需要分两种情况:

1)如果目标值不大于较大段的最小值,则只需要在左半段寻找

2)如果目标值大于较大段的最小值,则只需要在右半段寻找

2,中间值所在的有序段是较小段,则只需要在左半段寻找

 

对于以上情况不够清楚的,可以尝试画图理解。

 

提供一部分样例,边界比较难控制

[3,1]
1
[3,1]
3
[4,5,6,7,8,1,2,3]
8
[5,1,3]
5
[5,1,3]
1
[5,1,3]
3
[4,5,6,7,0,1,2]
4
[]
1
[1]
1
[1]
2
[4,5,6,7,0,1,2]
4
[4,5,6,7,0,1,2]
5
[4,5,6,7,0,1,2]
6
[4,5,6,7,0,1,2]
7
[4,5,6,7,0,1,2]
0
[4,5,6,7,0,1,2]
1
[4,5,6,7,0,1,2]
2
[4,5,6,7,0,1,2]
3
[4,5,6,7,0,1,2]
8

 

代码:

class Solution {
public:
	int search(vector<int>& nums, int target) {
		if (!nums.size()) {
			return -1;
		}
		int left = 0, right = nums.size() - 1;
		while (left <= right) {
			int mid = (left + right) >> 1;
			
			if (nums[mid] == target) {
				return mid;
			} else if (nums[mid] < target) {
				if (nums[left] <= nums[mid]) {
					left = mid + 1;
				} else {
					if (target == nums[right]) {
						return right;
					} else if (target < nums[right]) {
						left = mid +1;
					} else {
						right = mid - 1;
					}
				}
			} else {
				if (nums[left] <= nums[mid]) {
					if (target == nums[left]) {
						return left;
					} else if (nums[left] < target) {
						right = mid - 1;
					} else {
						left = mid + 1;
					}
				} else {
					right = mid - 1;
				}
			}
		}
		return -1;
	}
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值