LeetCode Num34_Search for a Range

  问题描述:  

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].

  释义:数组有序, 非递减顺序, 算法时间复杂度要求O(log n), 找到指定target在数组中的下标区间, 数组起始位置为0, 数组数量 n。

  问题分析:

  1. 二分法保证算法复杂度为 O(log n), 利用二分法分别寻找起始位置left和终止位置right;

  2. 确定边界条件和异常情况;

  3. 考虑边界条件:A[0]==target && A[n-1] == target 与 A[0]>target || target>A[n-1]  n<=0 情况进行处理;

  实现:

   采用二分法方式进行处理:

/*
 *  @biref: using binary search for achieving the algorithm's runtime complexity be in the order of O(log n)
 *  @authour: zhangjinxing jinxingbay@163.com
 *  @time: 2015 01 04 09 40
 *  @edition: 3.0
 *  @ notation backups
 */

class Solution {
public:
vector<int> searchRange(int A[], int n, int target) {
   if (target == A[0] && target == A[n-1]) {
       //  special case: the whole sortd array is a combination of target A[] = {target, target , ..., target}
       //  return the whole range [0, n-1]

       vector<int> ret{0, n-1};
       return ret;
   }
   
   //  find the left bound of the range
   const int left = searchLeftBound(A, 0, n-1, target);
   //  find the right bound of the range
   const int right = searchRightBound(A, 0, n-1, target);
   //  return the range of the combination of {target}
   vector<int> ret{left, right};
    return ret;
}
private:
    //  @brief: search the left bound of the range in the array
    //  @authour: zhangjinxing thoughts derives from the dream at 2015 01 04 
    //  @time: 2015 0104
    //  @parameter: const int A[] -- array 
    //              const int ibeg, begin index of the array A[] to be find
    //              const int iend, end index of the array A[]
    //              const int target, target combination number

    int searchLeftBound(const int A[], const int ibeg, const int iend, const int target) {
        int left = -1;
        //  case 1
        /*if (ibeg > iend) {//    out of the range
            return left;
        }
        */
        //  case 2

        if (ibeg == iend) {//   only one number to be search
            if (target == A[ibeg]) {//  if the number is equal to the target, return the index
                left = ibeg;//   left = iend;
            }
            return left;
        }
        //  case 3

        const int n = iend - ibeg + 1;//    get the total numbers of the array
        if (n <= 0) {//  the array is zero or out of the range, case1 is the subset here
            return left;
        }
        //  case 4
        if (target < A[ibeg] || target > A[iend]) {// the target is not contained in the array
            return left;// left === -1
        }
        
        // case 5
        const int imid =ibeg + (iend - ibeg)/2;// middle index of the array A sized by n
        if (A[imid] > target) {//   left bound must in the range A[ibeg, imid-1], search it
            left = searchLeftBound(A, ibeg, imid-1, target);
        }
        if (A[imid] < target) {//   left bound must in the range A[imid+1, iend], search it
            left = searchLeftBound(A, imid+1, iend, target);
        }
        if (A[imid] == target) {//  in the range A[ibeg, imid] 
            left = searchLeftBound(A, ibeg, imid, target);
        }
        
        return left;
    }
    int searchRightBound(const int A[], const int ibeg, const int iend, const int target) {
        int right = -1;
        //  case 1
        /*if (ibeg > iend) {//    out of range
            return right;
        }*/
        //  case 2
       
if (ibeg == iend ) {
            if (target == A[ibeg]) {//  begin == end, only one number
                right = iend;// right = ibeg 
            }
            return right;
        }
        
        //  case 3
        const int n = iend - ibeg + 1;//    get the total numbers of the array
        if (n <= 0) {//  the array is zero or out of the range, case1 is the subset here
            return right;
        }
        //  case 4

        if (target < A[ibeg] || target > A[iend]) {// the target is not contained in the array
            return right;// right === -1
        }
        //  case 5
        if (1 == (iend - ibeg)) {// ibeg + 1 == iend, two numbers here
            if (A[iend] == target) {//  if the *end === target, return iend
                right = iend;
            } else if (A[ibeg] == target){//    if the*end != target && *beg === target, return ibeg
                right = ibeg;
            }
            return right;
        }
        
        //  case 6
        const int imid = ibeg + (iend - ibeg)/2;// middle index of the array A sized by n, lower to int 
        if (A[imid] > target) {//   right bound must in the range A[ibeg, imid-1], search it
            right = searchRightBound(A, ibeg, imid-1, target);
        }
        if (A[imid] < target) {//   right bound must in the range A[imid+1, iend], search it
            right = searchRightBound(A, imid+1, iend, target);
        }
        if (A[imid] == target) {//   right bound maybe in the range A[imid, iend] or A[imid+1]
            //  case 6.1:   {target, x, x, y, ...} --- right = imid
            //  case 6.2:   {target, ..., target, ...} --- right = r_uper
       
    right = searchRightBound(A,imid, iend, target);//  may return imid, or r_uper
          const int r_uper = searchRightBound(A,imid+1, iend, target);// in first case, return -1; in second case, return last index
            if (-1 != r_uper) {
                right = r_uper;
            }
        }
        
        return right;
    }
};

分析

  注意left 和 right 的区别之处,以及产生的原因。

i. searchLeftBound中,通过比较A[imid] 与 target, 当A[imid]>target时,left 肯定在[ibeg, imid-1]区间内;当A[imid]<target, left在[imid+1, iend]区间内;当A[imid]== target,left在[imid, iend]区间内;

ii. searchRightBound中,同样分析三种情况,并对相等情况进行特殊处理;

注意其他特殊情况,并进行处理,以及特殊情况处理的顺序问题。

总结

i. consider special cases completely, using the whole given conditions;

ii. build the bug-free coding fragment is difficult, to be there, I must do exercises, coding & thinking;

iii. run the codes in you heart under special cases first;

iv. special cases comes first and just "code" it.


-----One "Acceptance" a day, keep my mind awake.-----noted by bayingbf-----2015.01.04-----

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值