syntax highlighter

2013年9月15日星期日

Leetcode Array 中的 Binary Search I

Binary Search 说简单也简单,思想很简单。说难确实也难,变种,corner case很多

1. Median of Two sorted Array

首先看总元素个数N是奇数还是偶数,奇数的话中位数 index(1 开头)k就是N/2+1 偶数的话就是N/2. N/2+1的平均数。然后就是求AB 的第K个数。要求A的长度小于B。 如果A的长度是0 那么返回B[k-1]. 否则的话,取pa=min(k/2, m), m是A的长度,pb=k-pa。 这里主要是让k每次一半递减,也就是说 要去掉k/2的元素(从A,B里)找第k/2大的元素就是答案。那么正确的去掉这k/2的元素就是关键 (并不是说去掉最小的k/2个元素,而是说这k/2个元素肯定是前K个里面的)因此如果A[pa-1]<=B[pb-1] 那么A的前Pa个元素就要被去掉 (Pa+Pb==K). 详见代码:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
 double fms(int A[], int m, int B[], int n,int k){
        if(m>n) return fms(B,n,A,m,k);
        if(m==0) return B[k-1];
        if(k==1) return min(A[0],B[0]);
        int pa=min(k/2,m);
        int pb=k-pa;
        if(A[pa-1]<=B[pb-1]) return fms(A+pa,m-pa,B,n,k-pa);
        else return fms(A,m,B+pb,n-pb,k-pb);
    }
    double findMedianSortedArrays(int A[], int m, int B[], int n) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        int total =m+n;
        if(total%2==1)
            return fms(A,m,B,n,total/2+1);
        else
            return (fms(A,m,B,n,total/2)+fms(A,m,B,n,total/2+1))/2;
        
    }

2. Search in rotated array

思路并不难,如果A[start]<A[mid] 证明 [start,mid] 这段是排好序的。若A[start]<=target&&taget<A[mid] end=mid-1;否则start=mid+1. 如果A[mid]<A[end] 证明[mid,end]这段是排好序的。

这道题目重点两个: while 条件 start<=end. 判断时A[start]<=target 而不是A[start]<target.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int search(int A[], int n, int target) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        int l=0;
        int r=n-1;
        while(l<=r){
            int mid=(l+r)/2;
            if(A[mid]==target) return mid;
            if(A[l]<=A[mid]){
                if(A[l]<=target&&target<A[mid])
                    r=mid-1;
                else
                    l=mid+1;                    
            }
            else{
                if(A[r]>=target&&target>A[mid])
                    l=mid+1;
                else
                    r=mid-1;                    
            }  
        }
        return -1;
    }
};
2.1. Search in Rotated Sorted Array II

duplicates are allowed. 主要是处理A[l]==A[mid]的情况 l++ skip.


3. Search for a Range

其实是求第一个target 的 index(low)和最后一个target的index(upp)。方法有多种,这里介绍的方法是这样:初始化start=0;end=n; 最后下届就是start, 上届就是end-1. 在这个过程中,有这么几个变量公式需要保证: 求下届时, A[low]=第一个target, A[upp]>=target. 所以当A[mid]<=target的时候 upp=mid. 因为如果是upp=mid-1的话有可能漏过的这个是唯一的target. 求上届时,A[upp]是第一个比target大的元素。因此当A[mid]>target的时候 upp=mid.这样能保证upp>target. 此时low也只是参照,只要保证low小于upp.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
bool search(int A[], int n, int target) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
         int l = 0, r = n - 1;
    while (l <= r) {
        int m = (l+r)/2;
        if (A[m] == target) return true; //return m in Search in Rotated Array I
        if (A[l] < A[m]) { //left half is sorted
            if (A[l] <= target && target < A[m])
                r = m - 1;
            else
                l = m + 1;
        } else if (A[l] > A[m]) { //right half is sorted
            if (A[m] < target && target <= A[r])
                l = m + 1;
            else
                r = m - 1;
        } else l++;
    }
    return false;
    }
另一种解法,更直观点
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
vector<int> res(2,-1);
        int l=0;
        int r=n-1;
        while(l<=r){
            int m=l+(r-l)/2;
            if(A[m]==target){
                if(m==0||A[m-1]<A[m]){
                    res[0]=m;
                    l=m;
                    r=n-1;
                }
                 if(m==n-1||A[m]<A[m+1]){
                    res[1]=m;
                    r=m;
                    l=0;
                }
                if(res[0]>=0&&res[1]>=0)
                    return res;
            
                 if(res[0]==-1)
                    r=m-1;
                  else
                    l=m+1;
             
                
            }
            else if(A[m]<target)
                l=m+1;
            else
                r=m-1;
    }
    return res;
4. Search Insert Position

如果数组元素个数是n, 那么插入位置是0...n. 初始化 start=0, end=n-1. 最后的终止状态是start=end=mid. 因此 while loop start<=end. 然后if A[mid]< target return mid+1


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
int searchInsert(int A[], int n, int target) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
         int start = 0;
         int end = n-1;
        int mid = 0;
        while(start <= end)
        {
            mid = (start + end) / 2;
            if(A[mid] == target)
                return mid;
            else if(A[mid] < target)
                start = mid +1;
            else
                end = mid-1;
        }
        if(A[mid] < target)
            return mid+1;
        else
            return mid;
        }
5. Search in a 2D matrix
如果按行扫描,这其实是一个一维排好序的数组。关键是把二维index转换为一维index A[i]=A[i/col][i%col]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
bool searchMatrix(vector<vector<int> > &matrix, int target) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
       int rows=matrix.size();
       int cols=matrix[0].size();
       int start=0;
       int end=rows*cols-1;
       
       while(start<=end){
           int mid=(start+end)/2;
           if(matrix[mid/cols][mid%cols]==target)
                return true;
           else if(matrix[mid/cols][mid%cols]<target)
            start=mid+1;
            else
            end=mid-1;
       }
       return false;
    }

没有评论:

发表评论