在旋转后有序数组中查找指定数(Search in Rotated Sorted Array)

本文介绍了一种在旋转过的有序数组中进行目标值搜索的方法,通过分析旋转数组的特点,提出使用改进的二分查找算法,实现了O(logn)的时间复杂度。文章提供了两种实现方式:递归调用和迭代循环,并通过代码示例展示了具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

 Suppose a sorted array 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.

给定一个从某个位置做了旋转后的有序数组,(比如0 1 2 4 5 6 7,旋转后变成4 5 6 7 0 1 2)。给定一个值,在这个数组里面做搜索,找到就返回对应的位置,否则返回-1。

可以假定没有重复数据存在。

分析

正常情况下,我们拿到的是一个有序数组,然后用二分查找就可以了,时间复杂度可以达到O(logn)。但是这个题目说的是有序数组还做了旋转,那能不能还用二分查找呢?答案是肯定的,我们可以看到旋转后的二维数组,从某个位置往左和往右都是有序的。

可以简单的先判断搜到中间节点和起始节点及终止节点的关系,之后再进行搜索。

可以分别采用递归调用和迭代循环进行解决。

代码

/**************************************
* Suppose a sorted array 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.
**************************************/
#include <iostream>
#include <vector>
using namespace std;

class Solution {
private:
	int search2Aux(const vector<int> &nums, int target, int first, int last) {
		if (first <= last) {
			int middle = (first + last) / 2;
			if (nums[middle] == target) {
				return middle;
			} else if (nums[first] <= nums[middle]) {
				if (nums[first] <= target && target < nums[middle]) {
					return search2Aux(nums, target, first, middle - 1);
				} else {
					return search2Aux(nums, target, middle + 1, last);
				}
			} else {
				if (nums[middle] < target && target <= nums[last]) {
					return search2Aux(nums, target, middle + 1, last);
				} else {
					return search2Aux(nums, target, first, middle - 1);
				}
			}
		} else {
			return -1;
		}
	}
public:
	/* Time: O(logn), Space: O(1) */
	int search1(const vector<int> &nums, int target) {
		int first = 0;
		int last = nums.size() - 1;
		while (first <= last) {
			int middle = (first + last) / 2;
			
			if (nums[middle] == target) {
				return middle;
			} else if (nums[first] <= nums[middle]) {
				if (nums[first] <= target && target < nums[middle]) {
					last = middle - 1;
				} else {
					first = middle + 1;
				}
			} else {
				if (nums[middle] < target && target <= nums[last]) {
					first = middle + 1;
				} else {
					last = middle - 1;
				}
			}
		}
		
		return -1;
	}
	
	/* Time: O(lgn), Space: O(1) */
	int search2(const vector<int> &nums, int target) {
		return search2Aux(nums, target, 0, nums.size() - 1);
	}
};

int main(void) {
	Solution* s = new Solution();
	vector<int> nums;
	nums.push_back(7);
	nums.push_back(9);
	nums.push_back(10);
	nums.push_back(0);
	nums.push_back(1);
	nums.push_back(2);
	nums.push_back(3);
	nums.push_back(5);
	
	cout << "Solution 1: " << s->search1(nums, 6) << endl;
	cout << "Solution 1: " << s->search1(nums, 4) << endl;
	cout << "Solution 1: " << s->search1(nums, 8) << endl;
	cout << "Solution 1: " << s->search1(nums, 9) << endl;
	cout << "Solution 1: " << s->search1(nums, 3) << endl;
	
	cout << "Solution 2: " << s->search2(nums, 6) << endl;
	cout << "Solution 2: " << s->search2(nums, 4) << endl;
	cout << "Solution 2: " << s->search2(nums, 8) << endl;
	cout << "Solution 2: " << s->search2(nums, 9) << endl;
	cout << "Solution 2: " << s->search2(nums, 3) << endl;
	
	delete s;
	return 0;
}

参考文章:LiveToolkit

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值