【LeetCode34.在排序數(shù)組中尋找元素的第一個和最后一個位置】——二分查找

34.在排序數(shù)組中尋找元素的第一個和最后一個位置

給你一個按照非遞減順序排列的整數(shù)數(shù)組 nums,和一個目標(biāo)值 target钦铺。請你找出給定目標(biāo)值在數(shù)組中的開始位置和結(jié)束位置诫尽。

如果數(shù)組中不存在目標(biāo)值 target,返回 [-1, -1]臀防。

你必須設(shè)計并實現(xiàn)時間復(fù)雜度為 O(log n) 的算法解決此問題。

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

示例 1:

輸入:nums = [5,7,7,8,8,10], target = 8
輸出:[3,4]

示例 2:

輸入:nums = [5,7,7,8,8,10], target = 6
輸出:[-1,-1]     

示例 3:

輸入:nums = [], target = 0
輸出:[-1,-1]

提示:

  • 0 <= nums.length <= 105
  • -109 <= nums[i] <= 109
  • nums 是一個非遞減數(shù)組
  • nums 是一個非遞減數(shù)組

思路分析:

這也是一道典型的二分查找的問題边败,與之前不同的是袱衷,需要找出元素第一次出現(xiàn)的位置和最后一次出現(xiàn)的位置,而若是元素沒有出現(xiàn)過的話笑窜,需要返回數(shù)組[-1,-1]致燥,這里可以在最后利用一個判斷語句進(jìn)行判斷,如下:

 if (a <= b && b < (int)nums.size() && nums[a] == target && nums[b] == target)
        {
            return vector<int>{a, b};
        }
        return {-1,-1};

那么總的套路還是一樣的排截,仍然可以參考我之前總結(jié)的二分查找的多個不同模板進(jìn)行求解嫌蚤。

(3條消息) 【LeetCode704.二分查找】——二分查找方法匯總_一粒蛋TT的博客-CSDN博客

左分右邊法:

class Solution {
public:
    //求出第一次出現(xiàn)位置
    int target(vector<int>& nums, int target) {
        int l = -1;
        int r = (int)nums.size();
        while ((l + 1) != r)
        {
            int m = (l + r) / 2;
            //cout << "m=" << m<<endl;
            if (nums[m] < target)
            {
                l = m;
            }
            else
            {
                r = m;
            }
        }
        cout << "target1=" << r << endl;
        return r;
    }
    //求出最后一次出現(xiàn)的位置
    int targettwo(vector<int>& nums, int target)
    {
        int l = -1;
        int r = (int)nums.size();
        while ((l + 1) != r)
        {
            int m = (l + r) / 2;
            //cout << "m=" << m<<endl;
            if (nums[m] <= target)
            {
                l = m;
            }
            else
            {
                r = m;
            }
        }
        cout << "target2=" << l << endl;
        return l;
    }

    vector<int> searchRange(vector<int>& nums, int target )
    {
        int a = this->target(nums, target );
        int b = this->targettwo(nums, target );
        if (a <= b && b < (int)nums.size() && nums[a] == target && nums[b] == target)
        {
            return vector<int>{a, b};
        }
        return {-1,-1};
    }
};

左閉右閉法:

class Solution { 
public:
    int binarySearch(vector<int>& nums, int target, bool lower) {
        int left = 0, right = (int)nums.size() - 1, ans = (int)nums.size();
        while (left <= right) {
            int mid = (left + right) / 2;
            if (nums[mid] > target || (lower && nums[mid] >= target)) {
                right = mid - 1;
                ans = mid;
            } else {
                left = mid + 1;
            }
        }
        return ans;
    }

    vector<int> searchRange(vector<int>& nums, int target) {
        int leftIdx = binarySearch(nums, target, true);
        int rightIdx = binarySearch(nums, target, false) - 1;
        if (leftIdx <= rightIdx && rightIdx < nums.size() && nums[leftIdx] == target && nums[rightIdx] == target) {
            return vector<int>{leftIdx, rightIdx};
        } 
        return vector<int>{-1, -1};
    }
};

利用STL庫:

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        if (nums.empty()) {
            return {-1, -1};
        }
        int leftIdx = lower_bound(nums.begin(), nums.end(), target)-nums.begin();
        int rightIdx = upper_bound(nums.begin(), nums.end(), target)-1-nums.begin();
        if(leftIdx<=rightIdx && rightIdx<nums.size() && nums[leftIdx]==target && nums[rightIdx]==target) {
            return {leftIdx, rightIdx};
        }
        return {-1, -1};
    }
};

利用CPP中的STL庫函數(shù),我們可以更快的直接求出元素的第一次出現(xiàn)位置以及最后一次出現(xiàn)的位置断傲。這部分代碼參考了leetcode隨心源的題解脱吱。

總的來說,該題是對之前簡單二分查找的一個延伸拓展认罩。

后續(xù)也會堅持更新我的LeetCode刷題筆記箱蝠,歡迎大家關(guān)注我,一起學(xué)習(xí)。
如果這篇文章對你有幫助宦搬,或者你喜歡這篇題解牙瓢,可以給我點個贊哦。
CSDN同步更新床三,歡迎關(guān)注我的博客:一粒蛋TT的博客_CSDN博客-LeetCode學(xué)習(xí)筆記,HTML+CSS+JS,數(shù)據(jù)結(jié)構(gòu)領(lǐng)域博主

往期回顧:
LeetCode367.有效的完全平方數(shù)
LeetCode69.x的平方根
LeetCode35.搜索插入位置
LeetCode704.二分查找

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末一罩,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子撇簿,更是在濱河造成了極大的恐慌聂渊,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件四瘫,死亡現(xiàn)場離奇詭異汉嗽,居然都是意外死亡,警方通過查閱死者的電腦和手機找蜜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來洗做,“玉大人弓叛,你說我怎么就攤上這事〕现剑” “怎么了撰筷?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長畦徘。 經(jīng)常有香客問我毕籽,道長,這世上最難降的妖魔是什么井辆? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任关筒,我火速辦了婚禮,結(jié)果婚禮上杯缺,老公的妹妹穿的比我還像新娘蒸播。我一直安慰自己,他們只是感情好萍肆,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布袍榆。 她就那樣靜靜地躺著,像睡著了一般匾鸥。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上碉纳,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天勿负,我揣著相機與錄音,去河邊找鬼。 笑死奴愉,一個胖子當(dāng)著我的面吹牛琅摩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播锭硼,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼房资,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了檀头?” 一聲冷哼從身側(cè)響起轰异,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎暑始,沒想到半個月后搭独,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡廊镜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年牙肝,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嗤朴。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡配椭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出雹姊,到底是詐尸還是另有隱情股缸,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布容为,位于F島的核電站乓序,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏坎背。R本人自食惡果不足惜替劈,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望得滤。 院中可真熱鬧陨献,春花似錦、人聲如沸懂更。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽沮协。三九已至龄捡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間慷暂,已是汗流浹背聘殖。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人奸腺。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓餐禁,卻偏偏與公主長得像,于是被迫代替她去往敵國和親突照。 傳聞我的和親對象是個殘疾皇子帮非,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容