新手算法學習之路----二分法Search-for-a-Range

題目:給定一個包含 n 個整數的排序數組,找出給定目標值 target 的起始和結束位置。數組

          若是目標值不在數組中,則返回[-1, -1]this

思路:若是中點等於target就要將數組分爲兩部分來查找即:0-mid和mid-end,中點的左右部分分別來找第一個和最後一個target值;左邊,只考慮mid值小於和等於target值;右邊只考慮mid值大於和等於target值;這種            方法代碼看起來太冗長了,空間複雜很差。spa

        第二種方法,是直接分爲兩次來查,整個數組用兩次來查。第一次查左邊的,第二次查右邊的。code

static int[] searchRange(int[] A, int target) {
           int start=0, end = A.length-1;
           int mid,left_position=-1,right_position=-1;
           if(A.length == 0) return new int []{-1,-1};
           while(start<end-1){
                  mid = start+(end-start)/2;
                  if(A[mid]<target){
                     start = mid +1;
                  }else if(A[mid]>target){
                     end = mid-1;
                  }else{
                   left_position=Search_Middle_left(A, start, mid-1,target);
                   right_position=Search_Middle_right(A, mid+1, end,target);
                   break;
                  }
             }
//             int []resualt={left_position,right_position};
//             return resualt;      
             return new int[]{left_position,right_position};
    }
    
     public static int Search_Middle_right(int[] A, int low, int high,int target){
         int this_low = low, this_high=high;
         int mid;
         while(this_low+1<this_high){
             mid = this_low+(this_high-this_low)/2;//在上一個中點的左邊找target值,左邊是不可能有元素值小於target 因此只討論 等於 和大於的時候
             if(A[mid]==target){          //target值等於mid的時候,繼續往序列的左邊找,              
                this_low = mid;           //當中間值等於target時候,若是要往右繼續尋找,就必須從mid的那個位置開始,若是從mid-1,那麼若是從mid-1位置就大於target,那麼程序就要出錯了
             }else if(A[mid]>target){     //target值小於mid的時候,往mid的右邊找
                this_high = mid -1;
             }
          }
         if(A[this_low]==target)
          return this_low;
         else return this_high;       
       }
    
     public static int Search_Middle_left(int[]A, int low ,int high, int target){
         int this_low = low, this_high=high;
         int mid;
         while(this_low+1<this_high){               // 當中間值等於target值的時候在左邊部分找,左邊部分不能有大於target的值,因此不考慮A[mid]>target的時候
             mid = this_low+(this_high-this_low)/2;
             if(A[mid]==target){            // 中間值等於target的時候繼續往左找
                this_high = mid;
             }else if(A[mid]<target) {   //若是中間值小於target值的時候,就往右找
                this_low = mid +1;
             }
          }
         if(A[this_high]==target)
          return this_high;
         else return this_low;
       }

第二種方法:此方法就很簡潔。blog

public int[] searchRange(int[] A, int target) {
           int left_start=0, left_end = A.length-1,right_start=0,right_end=A.length-1;
           int mid,left_position=-1,right_position=-1;
           
           if(A.length==0) return new int []{left_position, right_position};
           
             while(left_start+1 < left_end){
                  mid = left_start+(left_end-left_start)/2;
                  if(A[mid]<target){
                     left_start = mid;
                  }else if(A[mid]>=target){
                     left_end = mid;
                  }
             }
             
             if(A[left_start]==target) left_position=left_start;     //判斷最後start和end仍是有講究的,左邊的時要先判斷start即數組最左邊的數,而後是end值
             else if(A[left_end]==target) left_position = left_end;
             
             
              while(right_start+1 < right_end){
                  mid = right_start+(right_end-right_start)/2;
                  if(A[mid]<=target){
                     right_start = mid;
                  }else if(A[mid]>target){
                     right_end = mid;
                  }
             }
             if(A[right_end]==target) right_position = right_end;   //右邊的時候要先判斷end值,即數組最右邊的數,而後纔是start
             else if(A[right_start]==target) right_position=right_start;
             
             return new int []{left_position, right_position};
    }
相關文章
相關標籤/搜索