算法13--旋转数组二分查找

旋转数组   将一个有序数组前一部分移到后端 例如  12345---34512

1.求旋转数组的最小值

数组基本有序可以考虑二分查找来解决,考虑旋转数组的特点前半部分递增后半部分递减,使用两个指针,第一个index1指向递增部分,第二个index2指向递减部分,不断逼近,当两者距离之差index2-index1等于1,可以得到最小值为第二个指针index2位置的数值。

求出中点值  mid

四种情况,

1.index2-index1==1 此时最小值即为arr[index2].

2.mid在前半部分  3,4,5,6,7,8,9,0,1,2  判断特征为  arr[mid]>arr[index1] && arr[mid]>arr[index2],此时最小值肯定在mid右边  即index1=mid;

3.mid在后半部分  7,8,9,0,1,2,3,4,5,6   判断特征为  arr[mid]<arr[index1] && arr[mid]<arr[index2]此时最小值在mid左边  index2=mid;

4.如果arr[index1]==arr[mid]==arr[index2]  此时无法判断最小值在mid两边位置,只能遍历查找最小值。

public static int minNum(int[] arr){
		int index1 = 0;
		int index2 = arr.length-1;
		int min = arr[index2];
		while(index1 < index2){
			System.out.println(index1 + " " + index2);
			if(index2 - index1==1){
				min = arr[index2];
				break;
			}
			int mid = (index1 + index2) >> 1;
		    if(arr[mid]>arr[index1] && arr[mid]>arr[index2])
		    	index1 = mid;
		    else if(arr[mid]<arr[index1] && arr[mid]<arr[index2])
		    	index2 = mid;
		    else{
		    	for(int i=index1; i<index2; i++){
		    		if(arr[i]<min)
		    			min = arr[i];
		    	}
		    }
		}
		return min;	
	}

2.旋转数组查找某一个数字

数组基本有序,考虑二分查找  lo  hi   mid指针

1.如果arr[mid]==num  直接返回mid

2.  mid值在前半部分   如 3,4,5,6,7,8,9,0,1,2  判断特征: arr[mid]>arr[lo] && arr[mid]>arr[hi] 

     比较arr[mid]与num关系:

               在mid左边  arr[lo]<=num<arr[mid](注意等号取值,否则端点处值查找不到)   mid左边此时完全有序,可以利用二分查找

                在mid右边   mid右边数组为先增后减,即为一个旋转数组的查找的递归问题

3.  mid值在后半部分    如7,8,9,0,1,2,3,4,5,6   判断特征   arr[mid]<arr[lo] && arr[mid]<arr[hi]

     比较arr[mid]与num关系:

                在mid右边   arr[mid]<num<=arr[hi  ]mid右边数组为完全有序,二分查找

                在mid左边   mid左边数组也是一个旋转数组  原来问题的递归问题

public static int findNum(int[] arr, int num, int lo, int hi){
		int mid = (lo + hi) >> 1;	
		if(arr[mid]==num)
			return mid;
		else if(arr[mid]>arr[lo] && arr[mid]>arr[hi]){
			//  arr[lo]<=num  num<=arr[hi] 取值等号为了处理边界情况,确定目标值所在范围然后执行二分查找
			if(arr[lo]<=num && num<arr[mid])
				return binaryFind(arr, num, lo, mid);
			else 
				return findNum(arr, num, mid, hi);
		}else{
			if(arr[mid]<num && num<=arr[hi])
				return binaryFind(arr, num, mid, hi);
			else 
				return findNum(arr, num, lo, mid);
		}
	}
	
	public static int binaryFind(int[] arr, int num, int lo, int hi){
		while(lo<=hi){
			int mid = (lo+hi)>>1;		   
		    if(arr[mid]==num)
		    	return mid;
		    else if(arr[mid]<num)
		    	lo = mid + 1;
		    else	
		    	hi = mid - 1;
		}
		return -1;
	}

对于旋转数组基本有序,查找时可以考虑二分查找。由于数组特点是先增后减,前半部分与后半部分长度未定,因此首先需要判断mid中点值的位置,在前半部分还是后半部分,根据中点值可以将原数组划分为  一个旋转数组以及一个完全有序的数字,因此可以递归来解决问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值