- 解题思路
原始数组是个升序数组,这道题其实就是在一个数组上查找某个元素是否存在,如果存在返回索引值;但是难点在于已知的数组B是在数组A的基础上变换而来,题目又要求我们返回target在数组A
中的位置;
通过得到数组A的某位置在数组B中的位置,就可以在数组A上完成二分查找;因为二分查找需要根据区间左右值于target的大小关系来更新区间;所以找到数组A与数组B的元素对应关系,就可以知道数组A中某位置的元素大小;
- code
三部分
-
寻找数组A的首元素在数组B中的位置,为计算两个位置的映射做准备
trick
使用二分法来查找起始元素,当mid大于数组B的末尾元素是,选择左半区间 -
根据元素m在数组A中的位置,得到在数组B的位置;转换关系如下:
3)二分查找
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
#include<map>
using namespace std;
class Solution {
public:
int search(vector<int>& nums, int target) {
int Len = nums.size();
int start = find_start(nums, 0, Len - 1);
//根据原始数组索引二分法查找target
int L = 0;
int R = nums.size() - 1;
while (L <= R)
{
int old_mid = (L + R) >> 1;//原始数组中的位置
int mid = change_idx(Len, start, (L + R) >> 1);//现在数组中的位置
if (nums[mid] == target)
return mid;
else if (nums[mid] > target)
R = old_mid - 1;//更新在原来数组中位置
else
L = old_mid + 1;
}
return -1;
}
//start表示原始数组中的起始元素在转换后数组的那个位置
//比如[5,1,3]原始数组为[1,3,5],那么原始数组的首元素在现在数组的位置1
//old_mid表示数组中的索引,在原始数组中使用二分法查找目标值
//原始数组中元素位置与输入数组中的位置变换
//输入数组[2,3,5,1],原始数组[1,2,3,5],那么原始数组的索引2在输入数组中为索引1
int change_idx(int Len, int start, int old_mid)
{
if (old_mid < Len - start)
{
return old_mid + start;
}
else
{
return old_mid - (Len - start);
}
}
//返回变换数组中代表原始数组首元素的索引
int find_start(vector<int>& nums, int L, int R)
{
while (L <= R)
{
int mid = (L + R) >> 1;
if (mid >= 1 && mid + 1 < nums.size() && nums[mid] < nums[mid + 1] && nums[mid] < nums[mid - 1] || nums[mid] == nums[nums.size() - 1])
{
return mid;
}
//重点
//与最后一个元素比较
else
{
if (nums[mid] > nums[nums.size() - 1])
L = mid + 1;
else
R = mid - 1;
}
}
return 0;
}
};
int main()
{
vector<int> Arr = {3,1 };
int target = 0;
Solution S;
cout<<S.search(Arr, target)<<endl;
return 0;
}