二分法_ Half half

无法找到一个条件形成OOXX模型

但是可以根据判断,每次只保留有解的一半,去掉无解的一半

1. Find Peak Element

你给出一个整数数组(size为n),其具有以下特点:

  • 相邻位置的数字是不同的
  • A[0] < A[1] 并且 A[n - 2] > A[n - 1]

假定P是峰值的位置则满足A[P] > A[P-1]A[P] > A[P+1],返回数组中任意一个峰值的位置。

 注意事项
  • It's guaranteed the array has at least one peak.
  • The array may contain multiple peeks, find any of them.
  • The array has at least 3 numbers in it.
样例

给出数组[1, 2, 1, 3, 4, 5, 7, 6]返回1, 即数值 2 所在位置, 或者6, 即数值 7 所在位置.

寻找峰值。


mid在数据中的分布可能有以下几种情况


当mid值在第一种情况,那么峰值一定在右侧,将start = mid即可

当mid值在第二种情况,那么峰值一定在左侧,将end = mid即可

当mid在第三种情况,那么就找到峰值。

当mid在第四种情况,那么峰值可能出现在左侧,也可能出现在右侧。

public class findPeak {
    public int findPeak(int[] A) {
        if (A == null || A.length == 0) {
        	return -1;
        }
        int results = 0;
        int start = 1;
        int end = A.length - 2;
        while (start + 1 < end) {
        	int mid = start + (end -start) / 2;
        	if (A[mid - 1] < A[mid] && A[mid] > A[mid + 1]) {
        		results = mid;
        		break;
        	} else if (A[mid - 1] < A[mid] && A[mid] < A[mid + 1]) {
        		start = mid;
        	} else if (A[mid] < A[mid - 1] && A[mid + 1] < A[mid] ) {
        		end = mid;
        	}
        }
        if (A[start - 1] < A[start] && A[start] > A[start + 1]) {
        	results = start;
        } else {
        	results = end;
        }
        return results;
    }
}


if (A == null || A.length == 0) {
    		return -1;
    	}
    	int start = 1;
    	int end = A.length - 2;
    	while (start + 1 < end) {
    		int mid = start + (end - start) / 2;
    		if (A[mid] < A[mid + 1]) {
    			start = mid;
    		} else if (A[mid] < A[mid - 1]) {
    			end = mid;
    		} else {
    			start = mid;
    		}
    	}
    	if (A[start] < A[end]) {
    		return end;
    	} else {
    		return start;
    	}
OOOXXX形式是升序的形式。

找寻找数组中的最小值

讲数组转化为OOOXXX的形式,让找到数组中第一个或最后一个满足条件的位置,OOOXXXX 前面是升序的,后面也是升序的。

旋转排序数组包括排序数组([1,2,3,4,5])

为什么以最后一个值作为参考?因为可能包含[1,2,3,4,5]这种旋转排序数组,最小值在左侧。

以最后一个值作为参考值,找到最小值的位置,如果mid大于最后一个值,那么肯定是在右侧,否则肯定在左侧。


 public int findMin(int[] nums) {
        if (nums == null || nums.length == 0) {
        	return -1;
        }
        
        int start = 0;
        int end = nums.length - 1;
        
        int target = nums[end];
        while (start + 1 < end) {
        	int mid = start + (end - start) / 2;
        	if (nums[mid] > target) {
        		start = mid;
        	} else {
        		end = mid;
        	}
        }
        return Math.min(nums[start], nums[end]);
    }

搜索旋转排序数组

在一个旋转数组中搜索目标值

记住在while 循环中不是为了找目标值,而是为了每次都能将目标值的范围缩小一半。

旋转的排序数组包含排序数组。(Rotated Sorted Array 包含 Sorted Array)

现在需要思考的是如何每次取到一个mid值就缩小一次范围?

mid会出现在上部或者在下部。

这样可以将mid出现在上部或者下部分别讨论。

当mid出现在上部时(A[mid] >= A[start]),target可能出现在两边, 当  start<=target<=mid ,那么end = mid

或者   target>=mid || target <=start  那么start = mid

当mid出现在下部时,target也可能在两边,当 mid<=target<=end ,那么start = mid

当target <= mid || target >=start 那么end = mid

public int search(int[] A, int target) {
        if(A == null || A.length == 0) {
            return -1;
        }
        int start = 0;
        int end = A.length - 1;
        int mid;
        while (start + 1 < end) {
            mid = start + (end - start) / 2;
            if (A[mid] == target) {
                return mid;
            }
            if (A[mid] >= A[start]) {
            	if (target <= A[mid] && target >= A[start]) {
            		end = mid;
            	} else {
            		start =mid;
            	}
            } else {
            	if (target >= A[mid] && target <= A[end]) {
            		start = mid;
            	} else {
            		end = mid;
            	}
            }
        }
        if (A[start] == target) {
        	return start;
        } else if (A[end] == target){
        	return end;
        } else {
            return  -1;
        }
    }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值