leetcode 二分查找系列

Search Insert Position
 
AC Rate: 968/2757

Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.

You may assume no duplicates in the array.

Here are few examples.
[1,3,5,6], 5 → 2
[1,3,5,6], 2 → 1
[1,3,5,6], 7 → 4
[1,3,5,6], 0 → 0


典型的二分查找,本质是找第一个大于等于target的位置

class Solution {
public:
    int searchInsert(int A[], int n, int target) {
        // Note: The Solution object is instantiated only once and is reused by each test case.
        if(0 == n || target <= A[0]) return 0;
        if(target > A[n-1]) return n;
        //find the first element who is greater than target
        int left = 0,right = n-1,m = 0;
        while(left <= right){
            m = left + (right - left)/2;
            if(A[m] < target){
                left = m+1;
            }
            else{
                right = m-1;
            }
        }
        return left;
    }
};


Search for a Range
 
AC Rate: 608/2104

Given a sorted array of integers, find the starting and ending position of a given target value.

Your algorithm's runtime complexity must be in the order of O(log n).

If the target is not found in the array, return [-1, -1].

For example,
Given [5, 7, 7, 8, 8, 10] and target value 8,
return [3, 4].

需要找出第一个等于target的位置和最后一个等于target的位置

class Solution {
public:
    vector<int> searchRange(int A[], int n, int target) {
        // Note: The Solution object is instantiated only once and is reused by each test case.
       vector<int> range(2,-1);
       int left(0),right(n-1),m(0);
       while(left <= right){
           m = left + (right-left)/2;
           if(A[m] < target){
               left = m + 1;
           }
           else{
               right = m - 1;
           }
       }
       if(A[left] != target){
           return range;
       }
       range[0] = left;
       left= 0,right = n - 1;
       while(left <= right){
           m = left + (right - left) / 2;
           if(A[m] > target){
               right = m - 1;
           }
           else{
               left = m + 1;
           }
       }
       range[1] = right;
       return range;
    }
};
另一种类似的代码

class Solution {
public:
    vector<int> searchRange(int A[], int n, int target) {
        // Note: The Solution object is instantiated only once and is reused by each test case.
       vector<int> range(2,-1);
       int left(0),right(n),m(0);
       while(left < right){
           m = left + (right-left)/2;
           if(A[m] < target){
               left = m + 1;
           }
           else{
               right = m ;
           }
       }
       if(A[left] != target){
           return range;
       }
       range[0] = left;
       left= 0,right = n;
       while(left < right){
           m = left + (right - left) / 2;
           if(A[m] > target){
               right = m ;
           }
           else{
               left = m + 1;
           }
       }
       range[1] = right - 1;
       return range;
    }
};


Search in Rotated Sorted Array
 
AC Rate: 779/2757

Suppose a sorted array is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

You are given a target value to search. If found in the array return its index, otherwise return -1.

You may assume no duplicate exists in the array.

关键在于确定哪一段是排好序的,然后利用排序特性做二分即可。

class Solution {
public:
    bool InRange(int left,int right,int query){
        return query >= left && query <= right;
    }
    int search(int A[], int n, int target) {
        // Note: The Solution object is instantiated only once and is reused by each test case.
        int left = 0, right = n-1 , m = 0;
        while(left <= right){
            m = left + (right-left)/2;
            if(A[m] == target){
                return m;
            }
            if(A[m] >= A[left]){//left part is sorted 
                if(InRange(A[left],A[m],target)){//target is in this part
                    right = m - 1;
                }
                else{//not in this part
                    left = m + 1;
                }
            }
            else{//the other part is sorted
                if(InRange(A[m],A[right],target)){
                    left = m + 1;
                }
                else{
                    right = m - 1;
                }
            }
        }
        return -1;
    }
};

扩展:

查找旋转数组最小数字(剑指offer,九度1386)

要注意特例情况

#include <iostream>
#include <vector>
using namespace std;

int getSmallElement(const vector<int>& arr){

            int left(0),right(arr.size()-1),m(left);
             //if the array is sorted or has only one element , just return 
            if(left == right || arr[left] < arr[right]) return arr[left];
            while(arr[left] >= arr[right] ){
                   if(right - left == 1){
                             m = right; 
                             break;
                  }
                    m = left + (right-left)/2;
                      // 特例情况
                        if (arr[left] == arr[m] && arr[m] == arr[right]) {
                                // 顺序查找
                                for (int i = left + 1, min = arr[left]; i <= right; i ++) {
                                        if (arr[i] < min) {
                                                min = arr[i];
                                                m = i;
                                        }
                                }
                                break;
                        }
                    if(arr[m] >= arr[left])   left = m ;
                    else if(arr[m] <= arr[right])   right = m;
           }
           return arr[m];

}
int main()
{
        int n;
        ios::sync_with_stdio(false);
        vector<int> array;
       while(cin>>n){
              int temp;
              array.clear();
              for(int i = 0; i < n; ++i){
                      cin>>temp;
                      array.push_back(temp);
              }
             cout<<getSmallElement(array)<<endl;
       }
       return 0;
}
Search in Rotated Sorted Array II
 
AC Rate: 436/1440

Follow up for "Search in Rotated Sorted Array":
What if duplicates are allowed?

Would this affect the run-time complexity? How and why?

Write a function to determine if a given target is in the array.

class Solution {
public:
    bool search(int A[], int n, int target) {
        // Note: The Solution object is instantiated only once and is reused by each test case.
        int left(0),right(n-1),m(0);
        while(left <= right){
            m = left + (right - left) / 2;
            if(A[m] == target){
                return true;
            }
            if(A[m] > A[left]){//be careful here is > not >=
                if(target >= A[left] && target < A[m]){
                    right = m - 1;
                }
                else{
                    left = m + 1;
                }
            }
            else if(A[m] < A[left]){//be careful the condition is A[m] < A[left] but not A[m] < A[right]
                if(target > A[m] && target <= A[right]){
                    left = m + 1;
                }
                else{
                    right = m - 1;
                }
            }
            else{//A[m] == A[left]
                left++;
            }
        }
        return false;

    }
};

Search a 2D Matrix
 
AC Rate: 660/2043

Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:

  • Integers in each row are sorted from left to right.
  • The first integer of each row is greater than the last integer of the previous row.

For example,

Consider the following matrix:

[
  [1,   3,  5,  7],
  [10, 11, 16, 20],
  [23, 30, 34, 50]
]

Given target = 3, return true.

这道题在剑指offer也有的。

思路是从右上角开始比较,如果小于target,则可以略去一行向下继续查找,如果大于target,可以略去一列向左继续查找。

class Solution {
public:
    bool searchMatrix(vector<vector<int> > &matrix, int target) {
        // Note: The Solution object is instantiated only once and is reused by each test case.
        //search from the right top corner, every comparition we can cut off one column or row
        int rows = matrix.size();
        if(0 == rows) return false;
        int cols = matrix[0].size();
        int x = 0;
        int y = cols-1;
        while(x < rows && y >= 0){
            if(matrix[x][y] == target){
                return true;
            }
            else if(matrix[x][y] > target){
                y--;
            }
            else{
                x++;
            }
        }
        return false;
    }
};

Median of Two Sorted Arrays
 
AC Rate: 805/5289

There are two sorted arrays A and B of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

这是算法导论的一道课后习题,其中有个很经典的思想,就是在两个排序的数组中找出第K小的元素,( http://discuss.leetcode.com/questions/136/find-the-k-th-smallest-element-in-the-union-of-two-sorted-arrays?page=1&focusedAnswerId=137#137
上代码
class Solution {
public:
    double findMedianSortedArrays(int A[], int m, int B[], int n) {
        // Note: The Solution object is instantiated only once and is reused by each test case.
        int total = m + n;
        if(0 == total % 2){
            return (FindKth(A,m,B,n,total/2) + FindKth(A,m,B,n,total/2+1))/2;
        }
        else
            return FindKth(A,m,B,n,total/2 + 1);
    }
    double FindKth(int A[],int m ,int B[],int n,int k){
        if(m > n)   return FindKth(B,n,A,m,k);
        if(0 == m)  return B[k-1];
        if(0 == n)  return A[k-1];
        if(1 == k)  return min(A[0],B[0]);
        int Amid = min(k/2,m);
        int Bmid = k - Amid;
        if(A[Amid-1] < B[Bmid-1])
            return FindKth(A+Amid,m-Amid,B,n,k-Amid);
        else
            return FindKth(A,m,B+Bmid,n-Bmid,k-Bmid);
        
    }
};



二分查找有很多边界条件需要考虑,极容易出现bug,所以做之前最好能写一些test case,利于检验思路和代码。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值