问题描述
循环有序数组
假设一个旋转排序的数组其起始位置是未知的(比如0 1 2 4 5 6 7 可能变成是4 5 6 7 0 1 2)。
你需要找到其中最小的元素。
你可以假设数组中不存在重复的元素。
笔记
还是要用二分查找。再加一点细节处理。参考《剑指offer》
我们用两个指针分别指向数组的第一个元素和最后一个元素。按照题目中旋转的规则,第一个元素应该是大于或者等于最后一个元素的(这其实不完全对,还有特例,后面再加以讨论)
接着我们可以找到数组中间的元素。如果该中间元素位于前面的递增子数组,那么它应该大于或者等于第一个指针指向的元素。此时数组中最小的元素应该位于该中间元素的后面。我们可以把第一个指针指向该中间元素,这样可以缩小寻找的范围。移动之后的第一个指针仍然位于前面的递增子数组之中。
同样,如果中间元素位于后面的递增子数组,那么它应该小于或者等于第二个指针指向的元素。我们可以把第二个指针指向该中间元素。这样也可以缩小寻找的范围。移动之后的第二个指针仍然位于后面的递增子数组之中。
不管是移动第一个指针还是第二个指针,查找范围都会缩小到原来的一半。接下来我们再用更新之后的两个指针,重复做新一轮的查找。
代码
class Solution {
public:
/**
* @param num: a rotated sorted array
* @return: the minimum number in the array
*/
int findMin(vector<int> &num) {
// write your code here
int start = 0;
int end = num.size() - 1;
int res = 0;
while (num[start] >= num[end])
{
if (start == end - 1)
{
res = end;
break;
}
int mid = (start + end) / 2;
if (num[start] == num[mid] && num[mid] == num[end])
{
int tmp = num[start];
for (int i = start + 1; i <= end; i++)
{
if (num[i] < tmp)
return num[i];
}
}
if (num[mid] >= num[start])
start = mid;
if (num[mid] <= num[end])
end = mid;
}
return num[res];
}
};
相关题目
在循环有序数组中寻找某个数
代码
//
// main.cpp
// rotate_array
//
// Created by SteveWong on 26/09/2016.
// Copyright © 2016 SteveWong. All rights reserved.
//
#include <iostream>
#include <vector>
using namespace std;
int binsearch(vector<int> a, int tar, int lo, int hi)
{
while (lo <= hi)
{
int mid = (lo + hi) / 2;
if (a[mid] == tar)
{
return mid;
}
else if (a[mid] < tar)
{
lo = mid + 1;
}
else
{
hi = mid - 1;
}
}
return -1;
}
int find(vector<int> a, int tar, int lo, int hi)
{
while (a[lo] > a[hi])
{
int mid = (lo + hi) / 2;
if (a[mid] == tar)
return mid;
if (a[lo] < a[mid])//前一半是正常有序,后一半是循环有序
{
if (a[lo] <= tar && tar < a[mid])//目标在前一半,可以直接二分
{
return binsearch(a, tar, lo, mid-1);
}
else//在后一半循环有序数组中查找
{
lo = mid + 1;
}
}
else if (a[mid] < a[hi])//后一半正常有序,前一半循环有序
{
if (a[mid] < tar && tar <= a[hi])
{
return binsearch(a, tar, mid+1, hi);
}
else
{
hi = mid - 1;
}
}
}
//跳出循环,代表a[lo] < a[hi]
return binsearch(a, tar, lo, hi);
}
int main(int argc, const char * argv[]) {
// insert code here...
std::cout << "Hello, World!\n";
vector<int> a = {4, 5, 6, 7, 1, 2, 3};
// int tar = 2;
cout << find(a, 2, 0, 6) << endl;
cout << find(a, 3, 0, 6) << endl;
cout << find(a, 4, 0, 6) << endl;
cout << find(a, 5, 0, 6) << endl;
cout << find(a, 6, 0, 6) << endl;
cout << find(a, 7, 0, 6) << endl;
cout << find(a, 1, 0, 6) << endl;
cout << find(a, -8, 0, 6) << endl;
cout << find(a, 9, 0, 6) << endl;
return 0;
}