首先什么叫旋转数组,把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转。对于这样的数组,我们可以画一下的一个图来表示。
对于 Rotated Sorted Array 来说,主要有两类问题:
- 寻找Rotated Sorted Array的最小值。
- 在Rotated Sorted Array里面查找给定的数。
对于第一类问题又分为以下两种问题:
- 数组中没有重复元素,找最小值
- 数组中有重复元素,找最小值
对于第二类问题,又分为以下两种问题:
- 数组中没有重复元素,找给定的值
- 数组中有重复元素, 找给定的值
下面看:
第一类问题,找Rotated Sorted Array中最小值,对于已经排好序的数组来说,查找问题我们首先应该想到的是二分查找。
那么在数组中
没有重复元素时候查找的代码为(重点需要注意的是,需要先从end开始比较):
// 在没有重复元素时候,查找Rotated Sorted Array中的最小值
public int findMin(int[] nums) {
if (nums == null || nums.length == 0) {
return -1;
}
int start = 0;
int end = nums.length - 1;
int mid;
while (start + 1 < end) {
mid = start + ((end - start) >> 1);
//为了防止rotated array 蜕化成这种
//1 2 3 4 5 6
//需要先和end 比较
if (nums[mid] <= nums[end]) {
end = mid;
} else {
start = mid;
}
}
if (nums[start] < nums[end]) {
return nums[start];
}
return nums[end];
}
数组中
有重复元素时查找最小值的代码为:
// Rotated Sorted Array有重复元素时查找最小值
public int findMin(int[] nums) {
if (nums == null || nums.length == 0) {
return -1;
}
int start = 0;
int end = nums.length - 1;
int mid;
while (start + 1 < end) {
mid = start + ((end -start) >> 1);
if (nums[mid] < nums[end]) {
end = mid;
} else if (nums[mid] > nums[end]) {
start = mid;
} else {
//如果相等则 end 往前一步
--end;
}
}
if (nums[start] < nums[end]) {
return nums[start];
}
return nums[end];
}
数组中
没有重复元素时,代码为:
// 数组中没有重复元素时,查找给定的元素
public int search(int[] nums, int target) {
if (nums == null || nums.length == 0) {
return -1;
}
int start = 0;
int end = nums.length - 1;
int mid;
while (start + 1 < end) {
mid = start + ((end - start) >> 1);
if (nums[mid] == target) {
return mid;
} else if (nums[mid] > nums[start]) {
// 属于 上图中第二象限的区段
if (target >= nums[start] && target <= nums[mid]) {
end = mid;
} else {
start = mid;
}
} else {
//属于上图中第四象限的区段
if (target >= nums[mid] && target <= nums[end]) {
start = mid;
} else {
end = mid;
}
}
}
if (nums[start] == target) {
return start;
}
if (nums[end] == target) {
return end;
}
return -1;
}
// 旋转数组中有重复时查找给定元素
public int search(int[] nums, int target) {
if (nums == null || nums.length == 0) {
return -1;
}
int start = 0;
int end = nums.length - 1;
int mid;
// 先从end开始比较
while (start + 1 < end) {
mid = start + ((end - start) >> 1);
if (nums[mid] == target) {
return mid;
} else if (nums[mid] > nums[end]) { // 在上图中第二象限的线段上
if (target >= nums[start] && target <= nums[mid]) {
end = mid;
} else {
start = mid;
}
} else if (nums[mid] < nums[end]) { //在上图中第四象限的线段上
if (target >= nums[mid] && target <= nums[end]) {
start = mid;
} else {
end = mid;
}
} else {
--end; //end向前跨一步
}
}
if (nums[start] == target) {
return start;
}
if (nums[end] == target) {
return end;
}
return -1;
}
-------------EOF------------