前提
将数组循环右移k位
k=0 1 2 3 4 5
k=1 5 1 2 3 4
k=2 4 5 1 2 3
...
问题一
给一正常数组和数字k,返回循环右移k位的数组
方法很多,请看这篇文章。
问题二
有一升序数组,现循环右移了k位(k未知),求k的值。
方法一
暴力法,升序数组,找到不符合升序的位置即可。
int Fun(vector<int> &nums){
for(int i=1;i<nums.size();++i)
if(nums[i]<nums[i-1]){
return i;
}
return 0;
}
方法二
运用二分查找。高效,当然是最好了解法了。
int Fun(vector<int> &nums){
if(nums.size() == 0 || nums[0]<nums.back())
return 0;
int left = 0;
int right = nums.size()-1;
while (left<right){
int mid = (left+right)/2;
if(mid == left){
break;
}
if(nums[mid]>nums[left]){
left = mid;
}else if(nums[mid]<nums[right]){
right = mid;
}
}
return left+1;
}
问题三
有一升序数组,循环右移了k位(k未知),现在给一个值target,求在数组中找到target的下标,如果没有则返回-1。
解这道题之前我们先看看正常升序数组的解法(即k=0时),同样运用的是二分查找:
int Fun(vector<int> &nums,int target){
int left=0;
int right = nums.size()-1;
while(left<right){
int mid = (left+right)/2;
if(mid == left){
break;
}
if(nums[mid] == target){
return mid;
}else if(nums[mid]<target){
left = mid;
}else{
right = mid;
}
}
return -1;
}
再来考虑右移k位的情况:
int Fun(vector<int> &nums,int target){
int left = 0;
int right = nums.size()-1;
while(left<right){
int mid = (left + right) / 2;
if(mid == left){
break;
}
if(target == nums[mid]){
return mid;
}else if(target>=nums[left]){
if(nums[mid]>target){
right = mid;
}else{
if(nums[mid] >nums[left]){
left = mid;
}else{
right = mid;
}
}
}else{
if(nums[mid]<target){
left = mid;
}else{
if(nums[mid] > nums[right]){
left = mid;
}else{
right = mid;
}
}
}
}
if(target == nums[left])
return left;
else if(target == nums[right])
return right;
return -1;
}
代码看起来比较繁琐,简化版本:
int Fun(vector<int> &nums,int target){
int left = 0;
int right = nums.size()-1;
while(left<right){
int mid = (left + right) / 2;
if(mid == left){
break;
}
if(target == nums[mid]){
return mid;
}else if((nums[0] > target) ^ (nums[0] > nums[mid])^ (target > nums[mid])){
left = mid + 1;
}else{
right = mid;
}
}
if(target == nums[left])
return left;
else if(target == nums[right])
return right;
cout<<left<<","<<right<<endl;
return -1;
}