[Leetcode]34.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)),對於一個區間 [left, right]:

1.如果 target 不在其中 [left] > target or [right] < target,則返回 [-1, -1];
2.看中點(mid = (left+right)/2)與 target 的大小
  2.1.如果 [mid] > target,說明在區間 [left, mid];
  2.2.如果 [mid] < target,說明在區間 [mid + 1, right];
  2.3.否則,[mid] == target,說明 mid 是在結果中,我們在分別考慮左右兩側,得到
[left1, right1] 與 [left2, right2].然後拼接整理結果:

    2.3.1.如果 left1 == -1,則返回 [left2, right2]
    2.3.2.如果 left2 == -1,則返回 [left1, right1] (其實肯定是 [-1, -1])
    2.3.2.返回 [left1, right2] (即兩者都在結果之中,拼接返回即可)

python 代碼 [自己對邊界的處理還是不好,需要注意]

class Solution(object):
    def searchRange(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        return self.searchLR(nums, target, 0, len(nums) - 1)

    def searchLR(self, nums, target, left, right):
        if nums[left] > target or nums[right] < target:
            return [-1, -1]

        if left == right: # left==right should take care
            if nums[left] == target:
                return [left, left]
            else:
                return [-1, -1]

        mid = (left + right)//2

        if nums[mid] < target: #[mid] 較小,應在 mid 右側
            return self.searchLR(nums, target, mid + 1, right)
        elif nums[mid] > target:
            return self.searchLR(nums, target, left, mid)
        else: #相等,說明在其兩端
            [l1, r1] = self.searchLR(nums, target, left, mid)
            [l2, r2] = self.searchLR(nums, target, mid + 1, right)

            if l1 == -1:
                return [l2, r2]
            if l2 == -1:
                return [l1, r1]
            #即兩端都有
            return [l1, r2]

網上看到更優雅些的

其實題目只需二分查找值爲 target 最左與最右邊的位置即可。
個人感覺很厲害的一個人寫的
他在處理 [mid] == key 時對 pos 的再次賦值做的很好(pos == -1 ? mid : pos),如果在左邊(或右邊,取決於尋找最左還是最右)沒能找到值爲 key 的位置,直接將 mid 返回。

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;
    }
};

另一個“抽象”點的

因爲他的 binarySearch 在 [mid] <= target 時更新了一下返回值,這樣在 [mid + 1, right] 沒能找到時可以直接返回 mid。

class Solution {  
public:  
    vector<int> searchRange(int A[], int n, int target) {  
        // Start typing your C/C++ solution below  
        // DO NOT write int main() function  
        vector<int> res(2);  
        res[0] = binarySearch(A, n, target - 1) + 1;  
        res[1] = binarySearch(A, n , target);  
        if(res[1] == -1 || A[res[1]] != target){  
            res[0] = -1;  
            res[1] = -1;  
        }
        return res;  
    }  
    int binarySearch(int A[], int n, int target){  
        int l = 0;  
        int r = n -1;  
        int m = (l+r)/2;  
        int ret = -1;  
        while(l<=r){  
            if(A[m] > target){  
                r = m - 1;  
                m = (l+r)/2;  
            }  
            else{  
                ret = m;  
                l = m + 1;  
                m = (l+r)/2;  
            }  
        }  
        return ret;  
    }  
};  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章