1、第一题引至剑指offer
题目:把一个数组最开始的若干元素搬到数组的末尾,称其为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1.
解此题分两种情况
第一种情况:前后指针与中间指针所指向的元素不同时,
如果中间元素比前端元素大,最小值位于中间元素的右边;
如果中间元素比后端元素小,最小值位于中间元素的左边。
第二种情况:如果前后指针与中间指针所指向的元素不同时,只能采用顺序遍历,查打出最小值。
解题代码如下所示:
#include<iostream>
#include<vector>
using namespace std;
int commonSearch(vector<int>& nums) {
int minVal = nums[0];
for (int i = 1; i < nums.size(); ++i) {
if (nums[i] < minVal)
minVal = nums[i];
}
return minVal;
}
int minFromRotateArray(vector<int>& nums) {
if (nums.empty())
throw exception("Invalid parameters");
int first = 0;
int end = nums.size() - 1;
int mid = first;//如果求旋转时,可以直接返回起始元素
while (nums[first] >= nums[end]) {
if (end - first == 1) {
mid = end;
break;
}
mid = (first + end) / 2;
if (nums[first] == nums[end] &&//如果中间指针所指元素与两端元素相等,则只能顺序查找了
nums[first] == nums[mid])
return commonSearch(nums);
if (nums[mid] >= nums[first])//表明最小值位于中间元素的右边
first = mid;
else if (nums[mid] <= nums[end])//表明最小值位于中间元素的左边
end = mid;
}
return nums[end];
}
2、第二题引至leetcode
在旋转数组中寻找所给定的值。
解题思路:
//[12, 13, 14, 15, 16, 17, 18, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
//If target is let's say 14, then we adjust nums to this, where "inf" means infinity:
//[12, 13, 14, 15, 16, 17, 18, 19, inf, inf, inf, inf, inf, inf, inf, inf, inf, inf, inf, inf]
//If target is let's say 7, then we adjust nums to this:
//[-inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
需要注意的是在C中int的最大值为0x7FFFFFF,最小值为(int)0x80000000。
代码如下:
int search(vector<int>& nums, int target) {
int lo = 0, hi = nums.size();
//经过稍作修改的二分法
while (lo < hi) {
int mid = (lo + hi) / 2;
double num = (nums[mid] < nums[0] == (target < nums[0])) //此条件要是被满足,说明nums[mid]已经落入前半部分的有序区间或者后半部分的有序区间
? nums[mid]
: target < nums[0] ? -INFINITY : INFINITY;//此处若为真,说明target落入后半部分有序区间,若为假,target落入前半部分有序区间
if (num < target)
lo = mid + 1;
else if (num > target)
hi = mid; //此处为什么不可以是mid-1?????????????????????????
else
return mid;
}
return -1;
}