LeetCode二分查找总结

对3道二分查找题的总结,来源于:soulmachine,code_ganker

Search Insert Position

Search in Rotated Sorted Array

Search in Rotated Sorted Array II


1.最基本的二分查找:

思路就是每次取中间,如果等于目标即返回;否则根据大小关系切去一半。

因此算法复杂度是O(logn),空间复杂度O(1)。  

public class Solution {  
    public int searchInsert(int[] A, int target) {  
        int left=0;  
        int right=A.length-1;  
        while(left<=right){//【注意1】
            int mid=(left+right)/2;  
            if(target==A[mid]) //find it!
                return mid;  
            if (target

【注意1】while条件为left<=right,若找不到目标,最后一次操作是left和right指向同一index,执行一次循环体;结束时left>right,左右指针位置颠倒。  
【注意2】先写leftHalf,再写rightHalf
【注意3】"以上实现有一个好处:循环结束时,如果没找到目标,那么left一定停在恰好比目标大的index上,right一定停在恰好比目标小的index上,比较推荐这种实现。"  


2.旋转数组的查找I:

基本二分查找比较mid的值,这里比较target是否在区间,别无特殊。
不用纠结于Array怎么无序的,关注于旋转后一定有half是有序的。

public class Solution {
    public int search(int[] A, int target) {
        int left=0;
        int right=A.length-1;
        while(left<=right){    //循环条件和基本二分查找一样
            int mid=(left+right)/2;
            if(A[mid]==target)
                return mid;
            if(A[left]<=A[mid]){   //leftHalf有序【注意1】
                if(A[left]<=target && targetA[mid],leftHalf无序【注意3】
                if(A[mid]

【注意1】条件必须是 A[left] <= A[mid],因为考虑到 left == mid 的case。例如:只写"<",那么考虑 A=[3,1], target=1 的测试用例,结果会是错误的"-1"。

【注意2】注意写区间时候按照[,)来写。判断target是否在有序的half里,思路较清楚。

  至于为什么区间含left(或right)不含mid,因为target可能在两个边缘,如果在mid,就会直接return。

【注意3】条件写成 if ( A[left] > A[mid] ) -- else 也可以。


【注意4】关注于leftHalf是否有序,条件只能写成" if ( A[left] <= A[mid] ) -- else ",原因如上。(Soulmachine Ver.)
  关注于rightHalf是否有序,条件可以写成" if ( A[mid] < A[right] ) -- else ",或" if ( A[mid] < A[right] ) -- else ",OJ均会accept。(Code_Ganker Ver.)


3.旋转数组的查找II:

和上题一样,只是因为元素重复,if(A[left]<=A[mid])不一定是有序的,需要将这个case拆解成两部分处理:

-若 A[left] < A[mid] ,按照有序处理;

-若 A[left] ==A[mid],left++,处理边缘再来查找就ok。 

public class Solution {
    public boolean search(int[] A, int target) {
        int left=0;
        int right=A.length-1;
        while(left<=right){
            int mid=(left+right)/2;
            if(A[mid]==target)
                return true;
            if(A[left]
【注意1】"对left移动一步,直到边缘和中间不在相等或者相遇,这就导致了会有不能切去一半的可能。所以最坏情况(比如全部都是一个元素,或者只有一个元素不同于其他元素,而他就在最后一个)就会出现每次移动一步,总共是n步,算法的时间复杂度变成O(n)。"


你可能感兴趣的:(LeetCode第2章:线性表)