题目描述
有一个排过序的数组,包含n个整数,但是这个数组向左进行了一定长度的移位,例如,原数组为[1,2,3,4,5,6],向左移位5个位置即变成了[6,1,2,3,4,5],现在对于移位后的数组,需要查找某个元素的位置。请设计一个复杂度为log级别的算法完成这个任务。
给定一个int数组A,为移位后的数组,同时给定数组大小n和需要查找的元素的值x,请返回x的位置(位置从零开始)。保证数组中元素互异。
题目链接
https://www.nowcoder.com/practice/72ff6503455c4a008675e79247ef2a3a?tpId=8&&tqId=11047&rp=1&ru=/activity/oj&qru=/ta/cracking-the-coding-interview/question-ranking
解题步骤
- 先通过二分查找, 找偏移后数组起始的下标,
- 根据新的下标, 再加上数组的长度, 在这两个区间再进行二分查找, 但是会越界, 故将下标取余即可
- 最后返回下标
代码如下
#include <iostream>
#include <cstdlib>
#include <vector>
using namespace std;
int main()
{
// test 1: vector<int> v = { 8, 9, 1, 2, 3 ,4, 5, 6, 7};
vector<int> v = { 4, 5, 6, 7, 8, 9, 1, 2, 3 };
// 先找最小的数, 即偏移后的起始位置
int left = 0, right = v.size() - 1;
int mid = right / 2;
while (left < right)
{
if (v[mid] < v[mid - 1])
{
break;
}
if (v[mid] < v[left])
{
// 在左边
right = mid - 1;
}
else
{
// 在右边
left = mid + 1;
}
mid = (right + left) / 2 ;
}
// 得到的 mid 就是新的起点
int val;
cin >> val;
// 之后可以 mid 为起点, size + mid 为结束
// 在上面这个区间进行查找
// 查找会越界, 则取余 size 即可
left = mid;
right = v.size() + mid - 1;
while (left <= right)
{
mid = (right + left) / 2;
if (val == v[mid % v.size()])
{
break;
}
if (val > v[mid % v.size()])
{
left = mid + 1;
}
else
{
right = mid - 1;
}
}
mid %= v.size();
if (v[mid] != val)
{
cout << "can't find \n" << endl;
system("pause");
return 0;
}
cout << "the position is: "<< mid << endl;
system("pause");
return 0;
}