classSolution{ publicintfindMin(int[] nums){ int start = 0; int end = nums.length-1; while(start+1<end){ int mid = start + (end-start)/2; //none-rotated if(nums[start]<nums[end]){ return nums[start]; } if(nums[start]<nums[mid]){//pivot on left part start = mid; } else {//pivot on right part end = mid; } } if(nums[start]<nums[end]) return nums[start]; else return nums[end]; } }
classSolution{ publicintfindMin(int[] nums){ int start = 0; int end = nums.length-1; while(start+1<end){ int mid = start + (end-start)/2; //none-rotated if(nums[start]<nums[end]){ return nums[start]; } if(nums[start]<nums[mid]){//pivot on left part start = mid; } elseif((nums[start]>nums[mid])) {//pivot on right part end = mid; } else { start++; } } if(nums[start]<nums[end]) return nums[start]; else return nums[end]; } }
classSolution{ publicbooleansearchMatrix(int[][] matrix, int target){ int m = matrix.length; if(m==0) returnfalse; int n = matrix[0].length; if(n==0) returnfalse; int start = 0; int end = m*n-1; while(start+1<end){ int mid = start+ (end-start)/2; int row = mid/n; int column = mid%n; if(matrix[row][column]==target){ returntrue; } elseif(matrix[row][column]<target){ start = mid; } else{ end = mid; }
Find the Duplicate Number:这道题有两个做法,第一个做法是LinkedList Cycle II的思想(见LinkedList Cycle类型题)。第二个做法就是Binary Search By Range。这道题我们最大的number是数组的长度减一,也就是说重复的数一定在这个范围内,我们使用binary search,start是1,end是最大number,然后我们每次search都遍历数组并统计小于等于mid的数量,如果这个数量大于mid,由鸽巢原理我们确认这个重复的数一定在左半部分,否则在右半部分,这就相当于每次减少了搜索域。 We know that the whole range is “too crowded” and thus that the first half or the second half of the range is too crowded (if both weren’t, then neither would be the whole range). So you check to know whether the first half is too crowded, and if it isn’t, you know that the second half is.
想这种问题的时候不要去想为什么我们这样by range search最后的结果会在array中呢?这样想很容易就会绕进去出不来了!我们要明确这时候我们是search by range而不再是search by index,search by index的时候我们当然知道元素一定在array中,而search by range的时候我们需要知道的就是:已知结果在这个range中,我们确保结果一直在搜索域,经过不断收敛那么最后一定会找到结果,那这个结果也就自然而然一定在array中了。 有一个点需要注意:与普通的binary search不同,我们的判断条件没有count==K,因为即使等于也不代表找到的是那个number,有可能略大于,但也正好有K个count,所以一定要等到最后收敛完成
classSolution{ publicintfindDuplicate(int[] nums){ int start = 1; int end = nums.length-1; while(start<end){ int mid = start + (end-start)/2; int count = 0; for(int num:nums){ if(num<=mid) count++; } if(count>mid){ end = mid; } else { start = mid+1; } } return start; } }
Kth Smallest Element in a Sorted Matrix:首先拿到这道题,我们看到Kth这个关键词就要往top k问题去想,topK问题的解决方法无外乎PriorityQueue, Quick Select两种办法。所以我们最简单可以想到的就是使用PriorityQueue(见Top K总结)。 另一个想法是binary search,但是按照普通的binary search的search by index我们发现并不能解决这个问题,所以应该采用的是search by range(也就是根据number的range进行搜索)。By range搜索会有一个count,这里就是K,我们每次进行binary search,然后统计小于等于mid的count,然后和K进行比较进行搜索域的减小。
Median of Two Sorted Arrays:很难的题目,告诉了我们binary search不仅局限在可以search index/range,也可以search index与index之间的split点。这道题的核心思想是median的作用是把数组分成两部分,左半部分的值一定小于右半部分,所以我们在第一个array中找到一个split点,第二个array的split点也就随之确定了,我们需要确保第一个array split点的左侧的number小于第二个array split点的右侧的number以及第二个array split点的左侧的number小于第一个array split点的右侧的number,对于split点的选择,自然而然可以选择binary search。 ps.1 Why n >= m? Because I have to make sure j is non-nagative since 0 <= i <= m and j = (m + n + 1)/2 - i. If n < m , then j may be nagative, that will lead to wrong result. https://leetcode.com/problems/median-of-two-sorted-arrays/discuss/2481/Share-my-O(log(min(mn)))-solution-with-explanation