Python編程題52--在排序列表中查找元素的第一個和最后一個位置

題目

給定一個按照升序排列的整數(shù)列表 nums譬挚,和一個目標值 target缠沈。請查找出給定目標值在列表中的開始位置和結(jié)束位置攻锰。

如果列表中不存在目標值 target揩魂,則返回 [-1, -1]。

例如:

給定一個列表 nums :[5, 7, 7, 8, 8, 10]拐揭,target = 8
返回結(jié)果:[3, 4]

給定一個列表 nums :[5, 7, 7, 8, 8, 10]撤蟆,target = 6
返回結(jié)果:[-1, -1]

給定一個列表 nums :[],target = 0
返回結(jié)果:[-1, -1]

實現(xiàn)思路1

  • 定義2個變量:left_index堂污、right_index 家肯,分別表示開始位置和結(jié)束位置,默認值均為 -1
  • 直接進行一輪遍歷盟猖,如果列表中存在目標值 target讨衣,那么就記錄第一個出現(xiàn)的位置换棚,并更新到 left_index、right_index反镇,如果在剩余列表元素中依然存在目標值 target固蚤,那么就只更新 right_index

代碼實現(xiàn)

class Solution:
    def search_range(self, nums, target):
        left_index, right_index = -1, -1
        for i, value in enumerate(nums):
            if value == target and left_index == -1:
                left_index = i
            if value == target:
                right_index = i
        return [left_index, right_index]
  • 時間復(fù)雜度:O(n)
  • 空間復(fù)雜度:O(1)

實現(xiàn)思路2

  • 使用 二分查找 來實現(xiàn)
  • 定義2個變量:left_index、right_index 歹茶,分別表示開始位置和結(jié)束位置夕玩,通過二分查找判斷,如果列表 nums 中不存在目標值 target惊豺,則直接返回 [-1, -1]燎孟,如果列表中存在目標值 target,并且查找出來的目標值下標為 index 尸昧,那么就將 left_index揩页、right_index 均更新為 index
  • 在上面二分查找時,因為列表中可能存在多個相同元素烹俗,所以查找出來的 index 不一定是目標值 target 在列表中第一個出現(xiàn)的位置爆侣,因此需要對 left_index、right_index 做進一步處理
  • 對于left_index幢妄,如果其左側(cè)的元素也等于目標值累提,即nums[left_index - 1] == target,那么就連續(xù)更新 left_index = left_index - 1磁浇,直到 left_index 恰為目標值在列表中第一個出現(xiàn)的下標位置
  • 對于right_index,如果其右側(cè)的元素也等于目標值朽褪,即nums[right_index + 1] == target置吓,那么就連續(xù)更新 right_index = right_index + 1,直到 right_index 恰為目標值在列表中最后一個出現(xiàn)的下標位置

代碼實現(xiàn)

class Solution:
    def search_range(self, nums, target):
        index = self.binary_search(nums, target)
        if index == -1:  # 如果列表中不存在 target
            return [-1, -1]
        left_index, right_index = index, index
        while left_index > 0 and nums[left_index - 1] == target:  # 處理 left_index缔赠,找到第一個出現(xiàn)位置
            left_index -= 1
        while right_index < len(nums) - 1 and nums[right_index + 1] == target:  # 處理 right_index衍锚,找到最后一個出現(xiàn)位置
            right_index += 1
        return [left_index, right_index]

    def binary_search(self, nums, target):  # 二分查找
        left, right = 0, len(nums) - 1
        while left <= right:
            mid = (left + right) // 2
            if nums[mid] > target:
                right = mid - 1
            elif nums[mid] < target:
                left = mid + 1
            else:
                return mid
        return -1

從上面可以看到,如果列表中可能存在多個相同元素嗤堰,那么我們通過二分查找法查找返回的元素下標可能不是第一個出現(xiàn)位置戴质,因此,我們可以對上面的二分查找進行優(yōu)化:

  • 在二分查找函數(shù) binary_search() 的參數(shù)中增加一個參數(shù):flag
  • 如果flag為True踢匣,那么表示查找列表nums中第一個大于等于target的下標
  • 如果flag為False告匠,那么表示查找列表nums中第一個大于target的下標

優(yōu)化后的代碼如下:

class Solution:
    def search_range(self, nums, target):
        left_index = self.binary_search(nums, target, True)  # 查找第一個大于等于target的索引
        right_index = self.binary_search(nums, target, False)  # 查找第一個大于target的索引
        if left_index <= right_index - 1 and nums[left_index] == target and nums[right_index - 1] == target:
            return [left_index, right_index - 1]
        return [-1, -1]

    def binary_search(self, nums, target, flag):  # 改進后的二分查找
        left, right, index = 0, len(nums) - 1, len(nums)
        while left <= right:
            mid = (left + right) // 2
            if (nums[mid] > target) or (flag and nums[mid] >= target):
                right = mid - 1
                index = mid
            else:
                left = mid + 1
        return index
  • 時間復(fù)雜度:O(log n)
  • 空間復(fù)雜度:O(1)

更多Python編程題,等你來挑戰(zhàn):Python編程題匯總(持續(xù)更新中……)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末离唬,一起剝皮案震驚了整個濱河市后专,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌输莺,老刑警劉巖戚哎,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件裸诽,死亡現(xiàn)場離奇詭異,居然都是意外死亡型凳,警方通過查閱死者的電腦和手機丈冬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來甘畅,“玉大人埂蕊,你說我怎么就攤上這事¢吓ǎ” “怎么了粒梦?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長荸实。 經(jīng)常有香客問我匀们,道長,這世上最難降的妖魔是什么准给? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任泄朴,我火速辦了婚禮,結(jié)果婚禮上露氮,老公的妹妹穿的比我還像新娘祖灰。我一直安慰自己,他們只是感情好畔规,可當(dāng)我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布局扶。 她就那樣靜靜地躺著,像睡著了一般叁扫。 火紅的嫁衣襯著肌膚如雪三妈。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天莫绣,我揣著相機與錄音畴蒲,去河邊找鬼。 笑死对室,一個胖子當(dāng)著我的面吹牛模燥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播掩宜,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蔫骂,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了锭亏?” 一聲冷哼從身側(cè)響起纠吴,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎慧瘤,沒想到半個月后戴已,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體固该,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年糖儡,在試婚紗的時候發(fā)現(xiàn)自己被綠了伐坏。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡握联,死狀恐怖桦沉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情金闽,我是刑警寧澤纯露,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站代芜,受9級特大地震影響埠褪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜挤庇,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一钞速、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嫡秕,春花似錦渴语、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至掷酗,卻和暖如春狭郑,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背汇在。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留脏答,地道東北人糕殉。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像殖告,于是被迫代替她去往敵國和親阿蝶。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,779評論 2 354

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