1. 程式人生 > 實用技巧 >LeetCode 34 在排序陣列中查詢元素的第一個和最後一個位置

LeetCode 34 在排序陣列中查詢元素的第一個和最後一個位置

LeetCode 34 在排序陣列中查詢元素的第一個和最後一個位置

https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/

方法一:線性掃描

我們可以從左到右對陣列掃描一遍,然後記錄target所在的小標即可。掃描的結果會有一下三種情況,這三種情況以及它們對應的左右邊界情況如下:

  • 陣列中不存在target——左右邊界不存在,均為-1

  • 陣列中只出現一個target——左右邊界存在且相等

  • 陣列中出現了兩個及以上的target——左右邊界存在且不相等

class Solution {
public:
    // 列舉
    // 時間和空間複雜度:O(N), O(1)
    vector<int> searchRange(vector<int>& nums, int target) {
        int sz = nums.size();
        int lbound = -1, rbound = -1;
        for (int i = 0; i < sz; ++i) {
            if (nums[i] == target) {
                if (lbound == -1) lbound = i;
                else rbound = i;
            }
        }

        if (lbound != -1) return {lbound, rbound != -1 ? rbound : lbound};
        else return {lbound, rbound};
    }
};

方法二:二分搜尋

根據題目的時間複雜度要求和陣列有序的特性,可以使用二分搜尋的方法來搜尋target在陣列中的下標。

class Solution {
public:
    // 二分搜尋
    // 時間和空間複雜度:O(logN), O(1)
    vector<int> searchRange(vector<int>& nums, int target) {
        if (nums.size() == 0) return {-1, -1};

        int lbound = bound(nums, target, "left");
        int rbound = bound(nums, target, "right");
        return {lbound, rbound};
    }

    int bound(vector<int>& nums, int target, string bound_type) {
        int sz = nums.size();
        int mid, l =0, r = sz - 1;
        while (l <= r) {
            mid = (l + r) / 2;
            if (nums[mid] == target) {
                // 如果求左邊界則調整右指標往左邊界逼近;如果求右邊界則調整左指標往右邊界逼近
                if (bound_type == "left") r = mid - 1;
                else if (bound_type == "right") l = mid + 1;
            }
            else if (nums[mid] < target) l = mid + 1;
            else if (nums[mid] > target) r = mid - 1;
        }

        if (bound_type == "left") {
            if (l >= sz || nums[l] != target) return -1;
            return l;
        }
        else if (bound_type == "right") {
            if (r < 0 || nums[r] != target) return -1;
            return r;
        }

        return -1;
    }

    /*
    // 返回左邊界下標
    int left_bound(vector<int>& nums, int target) {
	    int mid, l = 0, r = nums.size() - 1;
	    while (l <= r) {
		    mid = l + (r - l) / 2;
		    if (nums[mid] == target) r = mid - 1;
		    else if (nums[mid] < target) l = mid + 1;
		    else if (nums[mid] > target) r = mid - 1;
	    }

	    if (l > nums.size() || nums[l] != target) return -1;
	    return l;
    }

    // 返回右邊界下標
    int right_bound(vector<int>& nums, int target) {
	    int mid, l = 0, r = nums.size() - 1;
	    while (l <= r) {
		    mid = l + (r - l) / 2;
		    if (nums[mid] == target) l = mid + 1;
		    else if (nums[mid] < target) l = mid + 1;
		    else if (nums[mid] > target) r = mid - 1;
	    }
	    if (r < 0 || nums[r] != target) return -1;
	    return r;
    }
    */
};