旋转数组中找值t
旋转数组对半分后,一半是有序数组、一半是旋转数组(两半都是有序数组的情况也符合讨论,因为有序数组是特殊的旋转数组)。这“一半是有序数组”的条件是该利用的。见ctci p399
怎么判断哪一半是有序数组?比较x[mi]和x[hi]。用mi和hi比较更健壮,因为mi一定!=hi(len>=2时)。若用lo和mi比较,因为mi向下取整,mi可能==lo,从而使判断if (x[lo]<x[mid])被绕过,会增加边界情况复杂度。
bool search(vector<int>& nums, int target) {
// 旋转数组对半分后,一半是有序数组、一半是旋转数组
int lo = 0, hi = (int)nums.size() - 1;
while (lo <= hi) {
int mi = lo + (hi - lo) / 2;
if (nums[mi] == target) return true;
if (nums[mi] < nums[hi]) { // 右半有序
if (nums[mi] < target && target <= nums[hi]) {
lo = mi + 1;
} else {
hi = mi - 1;
}
} else if (nums[mi] > nums[hi]) { // 左半有序
if (nums[lo] <= target && target < nums[mi]) {
hi = mi - 1;
} else {
lo = mi + 1;
}
} else { // nums[mi] == nums[hi]
hi--;
}
}
return false;
}
旋转数组的最小值
int findMin(vector<int>& nums) {
// 旋转数组对半分,一半旋转一半有序,最小值在旋转那一半
const int N = nums.size();
int lo = 0, hi = N - 1;
while (lo < hi) { // len([lo..hi])>=2
int mi = lo + (hi - lo) / 2;
// 由于mi向下取整,可能mi==lo,
// 若用if (nums[lo] < nums[mi]),当mi==lo时这个if将被绕过
// 用mi和hi就没这个问题,mi!=hi
if (nums[mi] > nums[hi]) { // 右半旋转,且m位置不是min
lo = mi + 1;
} else { // 左半旋转
hi--;
}
}
return nums[lo];
}