旋转数组最小数字
/*旋转数组最小数字(剑指offer、二分查找)
* 题目描述:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
* 输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。
* 解题思路:
* 题目要求找到最小元素,第一反应是排序,但数组基本有序直接排序浪费性能。
* 结合数据的特点前半部分递增,后半部分递减,从头开始遍历直到有元素小于前一个数.
* 上面一种思路的目的是要找到递增部分和递减部分的临界点该点的特性为大于前一个和后一个元素
* 二分查找:
* 声明p1指向查找区域的首元、p2指向查找区域的末元,mid指向当前查找元素。
* p1=1,p2=data.length,mid=(p1+p2)/2
* 如果mid指向的数的左边的元素小于mid右边的元素也小于mid,返回mid下一个元素的值
* 如果mid左边的元素小于mid右边的元素大于mid,p2=mid mid=(p2-p1)/2
* 如果mid左边的元素大于mid右边的元素小于mid,p1=mid mid=(p2-p1)/2
* !!!这种解法失败,原因:测试数据中包含不旋转的数据,即完全有序的数组,这种情况不再存在上面思路的特征点!!!
*题解思路:
* 维持两个指针p1指向搜索区域的左边,p2指向搜索区域的右边,mid指向搜索区域的中间
* 如果mid大于p1说明从p1到mid是递增的,最小值应该位于mid到p2,将p1指向mid。
* 如果mid小于p1说明p1到mid是递减的,最小值就位于p1到mid中,将p2指向mid。
* 当mid等于p1,无法判断p1到mid是增或减,遍历p1到p2取最小值
*
* */
public class XuanZhuanShuZuDeZuiXiaoShuZi {
public static void main(String[] args) {
XuanZhuanShuZuDeZuiXiaoShuZi_Solution2 solution = new XuanZhuanShuZuDeZuiXiaoShuZi_Solution2();
int[] numbers = {1,3,3};
System.out.println(solution.minArray(numbers));
}
}
class XuanZhuanShuZuDeZuiXiaoShuZi_Solution1 {
public int minArray(int[] numbers) {
int p1=0;
int p2=numbers.length-1;
int mid = (p1+p2)/2;
while(mid!=p1&&mid!=p2) {
//如果mid大于左边的且大于右边的,返回mid右边的
if(numbers[mid]>=numbers[mid-1]&&numbers[mid]>=numbers[mid+1]) {
return numbers[mid+1];
}
//如果mid小于左边的且小于右边的,返回mid
if(numbers[mid]<=numbers[mid-1]&&numbers[mid]<=numbers[mid+1]) {
return numbers[mid];
}
//如果mid大于左边的 小于右边的,p2=mid、mid=(p1+p2)/2
if(numbers[mid]>=numbers[mid-1]&&numbers[mid]<=numbers[mid+1]) {
p2 = mid;
mid = (p1+p2)/2;
continue;
}
}
return numbers[mid];
}
}
class XuanZhuanShuZuDeZuiXiaoShuZi_Solution2{
public int minArray(int[] numbers) {
int p1 = 0;
int p2 = numbers.length-1;
while(p1 != p2) {
// System.out.println(numbers[p1]+" "+numbers[(p1+p2)/2]+" "+numbers[p2]);
if(numbers[(p1+p2)/2] > numbers[p2]) {
// System.out.println("aa");
p1 = (p1+p2)/2+1;
continue;
}
if(numbers[(p1+p2)/2] < numbers[p2]) {
// System.out.println("bb");
p2 = (p1+p2)/2;
continue;
}
if(numbers[(p1+p2)/2] == numbers[p2]) {
if(numbers[(p1+p2)/2]>numbers[(p1+p2)/2+1]) {
// System.out.println("cc1");
p1 = (p1+p2)/2+1;
continue;
}else {
int temp = numbers[p1];
for(int i=p1;i<p2+1;i++) {
if(numbers[i]<temp) {
temp=numbers[i];
}
}
return temp;
}
}
}
return numbers[(p1+p2)/2];
}
}