LeetCode | Search for a Range(查找数据出现的范围)

来源:互联网 发布:ai 人工智能 影评 编辑:程序博客网 时间:2024/06/05 15:48


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

查找某一个值出现在数组中的范围。

方案一:

先二分查找到key,然后再二分查找,知道arr[mid]==key && arr[mid-1] < key时为最左边界,arr[mid]==key && arr[mid-1] > key为最右边界。但是要注意考察mid==0 和 mid==n-1时的情况。所以判断时还要加强条件。代码如下

int SearchRange(int arr[], int n, int key,int *left,int *right){int lo = 0, hi = n - 1, mid = 0;int lhi, rlo;while (lo <= hi){mid = (lo + hi) / 2;if (arr[mid] == key){lhi = mid;//要取等于mid,防止左半区不再含有key值rlo = mid;//同上,防止右半区不含key值while (lo <= lhi){mid = (lo + lhi) / 2;if (arr[mid] == key && (mid == 0 || arr[mid - 1] < key)){*left = mid;break;}if (arr[mid] >= key)//arr[mid] == key的情况要放入这个里面lhi = mid - 1;elselo = mid + 1;}while (rlo <= hi){mid = (rlo + hi) / 2;if (arr[mid] == key && (mid == n - 1 || arr[mid + 1] > key)){*right = mid;break;}if (arr[mid] > key)hi = mid - 1;else//arr[mid] == key的情况要放入这个里面rlo = mid + 1;}return 1;}if (arr[mid] > key)hi = mid - 1;elselo = mid + 1;}return 0;}


方案二:

上面写的有些繁琐,还要先查到再左右加强条件遍历。我们可以分两次二分查找,第一次查找最左端,当arr[mid] >= key时,依然让hi = mid-1。这样得到的越界l刚好为左边界left;同理,第二次查找右边界,当arr[mid] <= key时,依然让l = mid+1。越界的r刚好为右边界。(这两个地方需要仔细考虑好,不然又会像上面一样,在中间添加很多代码来判断)

上面的思路充分利用了循环l<=r的特性。合适超出边界。还有判断时,等号应处于哪个范围。

当然最后还要判断查找失败时的情况。

class Solution {//Binary Search//we must know how to process the 3 cases below://1.how to find the right most target//2.how to find the left most target//3.how to find the insert positionpublic:vector<int> searchRange(int A[], int n, int target) {// Start typing your C/C++ solution below// DO NOT write int main() functionint l = 0;int r = n-1;while (l <= r){int mid = l+(r-l)/2;if (A[mid] >= target)//find the left most target r = mid-1;else if (A[mid] < target)l = mid+1;}int left = l;l = 0; r = n-1;while (l <= r){int mid = l+(r-l)/2;if (A[mid] > target)//find the right most targetr = mid-1;else if (A[mid] <= target)l = mid+1;}int right = r;if(A[left] != target || A[right] != target)left = right = -1;vector<int> ans(2);ans[0] = left;ans[1] = right;return ans;}};


还有一种是传递一个标志符,开表示查找左边界还是右边界。简化了代码。但要考虑清楚如何判断

class Solution {public:    int findPos(int a[], int beg, int end, int key, bool findLeft)    {        if (beg > end)            return -1;                    int mid = (beg + end) / 2;                if (a[mid] == key)        {            int pos = findLeft ? findPos(a, beg, mid - 1, key, findLeft) : findPos(a, mid + 1, end, key, findLeft);            return pos == -1 ? mid : pos;        }        else if (a[mid] < key)            return findPos(a, mid + 1, end, key, findLeft);        else            return findPos(a, beg, mid - 1, key, findLeft);           }        vector<int> searchRange(int A[], int n, int target) {        // Start typing your C/C++ solution below        // DO NOT write int main() function        int leftPos = findPos(A, 0, n - 1, target, true);        int rightPos = findPos(A, 0, n - 1, target, false);                vector<int> ret;                ret.push_back(leftPos);        ret.push_back(rightPos);        return ret;    }};




0 0
原创粉丝点击