Leetcode題目分析思路總結(jié)(一)

根據(jù)數(shù)據(jù)結(jié)構(gòu)和算法的分類來進(jìn)行刷題,有時(shí)候會(huì)有一種被劇透了的感覺箱亿,思考方向會(huì)不自覺靠著對(duì)應(yīng)算法上去想。如果出現(xiàn)一道沒有見過的題目弃秆,有時(shí)候很難想到對(duì)應(yīng)的解法届惋,通過一些關(guān)鍵詞的常見套路,可以很快找到解題思路菠赚。


一脑豹、看數(shù)據(jù)范圍大小

通過提供的數(shù)據(jù)范圍大小可以大致判斷出所需算法的時(shí)間復(fù)雜度


數(shù)據(jù)范圍對(duì)應(yīng)的時(shí)間復(fù)雜度

時(shí)間復(fù)雜度對(duì)應(yīng)的算法


時(shí)間復(fù)雜度

二、數(shù)據(jù)結(jié)構(gòu)

看處理對(duì)象的數(shù)據(jù)結(jié)構(gòu)衡查,比較常見的有:一維數(shù)組瘩欺,二維數(shù)組寓涨,字符串怎栽,二叉樹

1. 一維數(shù)組

根據(jù)我個(gè)人的做題經(jīng)驗(yàn)贵试,將數(shù)組問題大致劃分為以下幾個(gè)方向:數(shù)組有序沮脖,數(shù)組無序,子數(shù)組問題拍埠,子序列問題阁吝,多個(gè)數(shù)組問題。


數(shù)組有序

如果題目沒有要求保留原來順序的械拍,都可以將數(shù)組進(jìn)行排序突勇。

a. 數(shù)組有序/有單調(diào)性

如果數(shù)組本身具有單調(diào)性,需要尋找的是數(shù)組中的某個(gè)值坷虑,可以考慮二分搜索甲馋。

33 搜索旋轉(zhuǎn)排序數(shù)組
整數(shù)數(shù)組 nums 按升序排列,數(shù)組中的值 互不相同 迄损。
在傳遞給函數(shù)之前定躏,nums 在預(yù)先未知的某個(gè)下標(biāo) k(0 <= k < nums.length)上進(jìn)行了 旋轉(zhuǎn),使數(shù)組變?yōu)?[nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下標(biāo) 從 0 開始 計(jì)數(shù))芹敌。例如痊远, [0,1,2,4,5,6,7] 在下標(biāo) 3 處經(jīng)旋轉(zhuǎn)后可能變?yōu)?[4,5,6,7,0,1,2] 。
給你 旋轉(zhuǎn)后 的數(shù)組 nums 和一個(gè)整數(shù) target 氏捞,如果 nums 中存在這個(gè)目標(biāo)值 target 碧聪,則返回它的下標(biāo),否則返回 -1 液茎。

雖然數(shù)組在某處進(jìn)行了旋轉(zhuǎn)逞姿,但依舊是部分有序的,仍然可以使用二分搜索捆等。將數(shù)組分為左右兩部分時(shí)可以發(fā)現(xiàn)滞造,必定有一部分是有序,根據(jù)有序的部分可以判斷上下界的迭代栋烤。

def search(self, nums: List[int], target: int) -> int:
    if not nums:
        return -1
    l, r = 0, len(nums) - 1
    while l <= r:
        mid = (l + r) // 2
        if nums[mid] == target:
            return mid
        if nums[0] <= nums[mid]:
            if nums[0] <= target < nums[mid]:
                r = mid - 1
            else:
                l = mid + 1
        else:
            if nums[mid] < target <= nums[len(nums) - 1]:
                l = mid + 1
            else:
                r = mid - 1
    return -1

4 尋找兩個(gè)正序數(shù)組的中位數(shù)(歸并+二分)
81 搜索旋轉(zhuǎn)排序數(shù)組 II
153 尋找旋轉(zhuǎn)排序數(shù)組中的最小值
378 有序矩陣中第 K 小的元素

如果數(shù)組本身已經(jīng)排序谒养,并且需要找出兩個(gè)數(shù)字,那么可以使用雙指針明郭。
167 兩數(shù)之和 II - 輸入有序數(shù)組

b. 求解過程中存在單調(diào)性

在按照題目的描述一步步求解的過程中买窟,如果發(fā)現(xiàn)搜索目標(biāo)解的過程中,搜索過的值單調(diào)遞增或者遞減达址,可以通過維護(hù)單調(diào)棧來實(shí)現(xiàn)蔑祟。要意識(shí)到這一點(diǎn)需要根據(jù)題目要求,將求解過程模擬出來沉唠。

42 接雨水
給定 n 個(gè)非負(fù)整數(shù)表示每個(gè)寬度為 1 的柱子的高度圖,計(jì)算按此排列的柱子苛败,下雨之后能接多少雨水满葛。

首先思考什么樣的柱子才能接到雨水径簿,必然是一個(gè)“洼地”。假設(shè)對(duì)一片“洼地”從左向右遍歷嘀韧,在到達(dá)最低點(diǎn)前篇亭,柱子的高度一定是遞減的,因此可以使用單調(diào)棧來記錄數(shù)據(jù)锄贷。如果遍歷到的數(shù)字不滿足遞減關(guān)系了译蒂,說明到了“洼地”的另一側(cè),此時(shí)可以計(jì)算出能接到的雨水的增量谊却。更加詳細(xì)的動(dòng)畫演示可以參考力扣的題解柔昼。

def trap(self, height: List[int]) -> int:
    n = len(height)
    stack = []
    ans = 0
    for i in range(n):
        curr = height[i]
        while stack and curr>height[stack[-1]]:
            last = stack.pop()
            while stack and height[stack[-1]]==height[last]:
                stack.pop()
            if stack:
                h= min(height[stack[-1]], curr)-height[last]
                ans += h*(i-stack[-1]-1)
        stack.append(i)
    return ans

739 每日溫度

c. 求解結(jié)果有序

對(duì)于前 k 大或前 k 小這類問題,有一個(gè)通用的解法:優(yōu)先隊(duì)列炎辨。優(yōu)先隊(duì)列可以在O(logn) 的時(shí)間內(nèi)完成插入或刪除元素的操作(其中 n 為優(yōu)先隊(duì)列的大胁锻浮),并可以 O(1)地查詢優(yōu)先隊(duì)列頂端元素碴萧。

215 數(shù)組中的第K個(gè)最大元素
在未排序的數(shù)組中找到第 k 個(gè)最大的元素乙嘀。請(qǐng)注意,你需要找的是數(shù)組排序后的第 k 個(gè)最大的元素破喻,而不是第 k 個(gè)不同的元素虎谢。

使用一個(gè)小根堆,如果小根堆的大小小于K就向里面加數(shù)字曹质,否則就彈出堆頂(K+1個(gè)數(shù)中最小的)嘉冒,最后堆頂就是第K大的元素。

def findKthLargest(self, nums: List[int], k: int) -> int:
    n = len(nums)
    heap = []
    for i in range(n):
        heapq.heappush(heap, nums[i])
        if len(heap)>k:
            heapq.heappop(heap)
    return heap[0]

692 前K個(gè)高頻單詞


數(shù)組無序

a. 存在對(duì)應(yīng)關(guān)系

如果在數(shù)組中存在對(duì)應(yīng)關(guān)系咆繁,可以通過哈希表存儲(chǔ)關(guān)鍵字讳推,減少計(jì)算,提高代碼效率玩般。這里的對(duì)應(yīng)關(guān)系可以是一個(gè)數(shù)學(xué)關(guān)系银觅,或者是某種映射關(guān)系,比如數(shù)組索引與對(duì)應(yīng)數(shù)字的關(guān)系坏为,與頻數(shù)相關(guān)的題目也經(jīng)常會(huì)用哈希表究驴。

1兩數(shù)之和
給定一個(gè)整數(shù)數(shù)組 nums 和一個(gè)整數(shù)目標(biāo)值 target,請(qǐng)你在該數(shù)組中找出 和為目標(biāo)值 的那 兩個(gè) 整數(shù)匀伏,并返回它們的數(shù)組下標(biāo)洒忧。
你可以假設(shè)每種輸入只會(huì)對(duì)應(yīng)一個(gè)答案。但是够颠,數(shù)組中同一個(gè)元素在答案里不能重復(fù)出現(xiàn)熙侍。

數(shù)組中的元素存在著對(duì)應(yīng)關(guān)系:nums[i] = target - nums[j], nums[i] 與索引 i。

可以以nums[i]為key,以索引i為value蛉抓,對(duì)于每一個(gè)值nums[i]庆尘,尋找target - nums[j]是否存在于哈希表內(nèi)。

def twoSum(self, nums: List[int], target: int) -> List[int]:
    table = {}
    for i in range(len(nums)):
        if target-nums[i] in table:
            return [table[target-nums[i]],i]
        table[nums[i]] = i
    return []

454四數(shù)相加II
給定四個(gè)包含整數(shù)的數(shù)組列表 A , B , C , D ,計(jì)算有多少個(gè)元組 (i, j, k, l) 巷送,使得 A[i] + B[j] + C[k] + D[l] = 0驶忌。

可以將這個(gè)四數(shù)相加的問題轉(zhuǎn)化為兩數(shù)相加的問題,將A,B,C,D分為兩組笑跛,分別為A,B相加的所有可能結(jié)果和C,D相加的所有可能結(jié)果付魔,要尋找的是滿足 A[i] + B[j] = - C[k] - D[l]的元組的個(gè)數(shù)。

以A[i] + B[j]的值為key飞蹂,以出現(xiàn)次數(shù)為value建立哈希表几苍,在C,D中尋找滿足A[i] + B[j] = - C[k] - D[l]的索引,并計(jì)算出現(xiàn)次數(shù)晤柄。

def fourSumCount(self, A: List[int], B: List[int], C: List[int], D: List[int]) -> int:
    n = len(A)
    ans = 0
    group1 = collections.defaultdict(int)
    for i in range(n):
        for j in range(n):
            group1[A[i]+B[j]]+=1
    for i in range(n):
        for j in range(n):
            tmp = C[i]+D[j]
            if -tmp in group1:
               ans += group1[-tmp]
    return ans

其他用到了哈希表的題目:
30 串聯(lián)所有單詞的子串
138 復(fù)制帶隨機(jī)指針的鏈表
146 LRU緩存機(jī)制

b. 需要同時(shí)維護(hù)兩個(gè)值

如果求解過程中需要同時(shí)維護(hù)兩個(gè)變量擦剑,可以考慮雙指針。如果暴力的解法需要用到多重循環(huán)枚舉芥颈,并且在枚舉時(shí)發(fā)現(xiàn)枚舉元素間保持著某種關(guān)系惠勒,比如隨著第一個(gè)元素增加,第二個(gè)元素是遞減的(三數(shù)之和)爬坑,就可以使用雙指針的方法纠屋,將時(shí)間復(fù)雜度從O(N^2)減少到O(N)

11 盛最多水的容器
給你 n 個(gè)非負(fù)整數(shù) a1盾计,a2售担,...,an署辉,每個(gè)數(shù)代表坐標(biāo)中的一個(gè)點(diǎn) (i, ai) 族铆。在坐標(biāo)內(nèi)畫 n 條垂直線,垂直線 i 的兩個(gè)端點(diǎn)分別為 (i, ai) 和 (i, 0) 哭尝。找出其中的兩條線哥攘,使得它們與 x 軸共同構(gòu)成的容器可以容納最多的水。

盛水需要左右兩個(gè)邊同時(shí)存在材鹦,并且左右兩邊中較小的那個(gè)決定了水位的高度逝淹,左右兩邊的間隔決定了容器的長(zhǎng)度,可以使用左右兩個(gè)指針來分別指向左右兩邊桶唐。

尋找盛水最多的容器需要遍歷容器的長(zhǎng)度和水位的高度栅葡,長(zhǎng)度可以通過移動(dòng)左右指針來實(shí)現(xiàn)。水位高度是由最短邊決定的尤泽,因此無論長(zhǎng)邊如何移動(dòng)欣簇,得到的水位高度都會(huì)等于或者小于短邊的高度规脸,因此每一次迭代,需要移動(dòng)短的一邊醉蚁。

def maxArea(self, height: List[int]) -> int:
    maxare = 0
    left = 0
    right = len(height) -1
        
    while left <right:
        distance = right-left
        maxare = max(maxare, min(height[left],height[right])*(distance))
        if height[left] <height[right]:
            left += 1 
        else:
            right -=1
    return maxare

15三數(shù)之和

c. 左右各遍歷一次

比較有技巧性的方法燃辖,從左向右遍歷一次數(shù)組鬼店,再從右向左遍歷一次數(shù)組网棍,應(yīng)用場(chǎng)景與雙指針相似,但是不太容易想到妇智。當(dāng)要求解的是最大最小的問題滥玷,比如距離最近的最大是多少,有可能用到這種技巧巍棱。

581. 最短無序連續(xù)子數(shù)組
給你一個(gè)整數(shù)數(shù)組 nums 惑畴,你需要找出一個(gè) 連續(xù)子數(shù)組 ,如果對(duì)這個(gè)子數(shù)組進(jìn)行升序排序航徙,那么整個(gè)數(shù)組都會(huì)變?yōu)樯蚺判颉?br> 請(qǐng)你找出符合題意的 最短 子數(shù)組如贷,并輸出它的長(zhǎng)度。

根據(jù)題意需要找到的是到踏,數(shù)組中需要排序的最短子數(shù)組的邊界杠袱。對(duì)于一個(gè)已經(jīng)排好序的數(shù)組,從左到右遍歷到的最大值應(yīng)該等于當(dāng)前值窝稿,從右到左遍歷到的最小值楣富,應(yīng)該也是當(dāng)前值;否則就說明當(dāng)前遍歷到的數(shù)字為亂序伴榔。從左到右遍歷和從右到左遍歷分別記錄下需要排序的子數(shù)組的起始和終止位置纹蝴。

def search(arr,n):
    if n<2:
        return 0
    leftMax, leftId = float('-inf'), -1
    rightMin, rightId = float('inf'),-1
    for i in range(n):
        if arr[i]>=leftMax:
            leftMax = arr[i]
        else:
            leftId = i # index of num smaller than the leftMax
    if leftId ==-1:
        return 0
    for i in range(n-1,-1,-1):
        if arr[i]<=rightMin:
            rightMin = arr[i]
        else:
            rightId = i
    return leftId-rightId+1

網(wǎng)易校招筆試-電影院選座
疫情逐步緩和后,電影院終于開業(yè)了踪少,但是由于當(dāng)前仍處于疫情期間塘安,應(yīng)盡量保持人群不聚集的原則。所以當(dāng)小易來電影院選定一排后援奢,盡量需要選擇一個(gè)遠(yuǎn)離人群的位置兼犯。已知由0和1組成的數(shù)組表示當(dāng)前排的座位情況,其中1表示已被選座,0表示空座請(qǐng)問小易所選座位和最近人的距離座位數(shù)最大是多少萝究?有如下假設(shè):至少有一個(gè)人已選座免都,至少有一個(gè)空座位,且座位數(shù)限制為[2,1000]帆竹。

從左到右遍歷一次绕娘,從右到左遍歷一次,分別計(jì)算坐在位置i的適合栽连,距離左邊第一個(gè)1的距離和距離右邊第一個(gè)的距離险领,取每個(gè)位置上左右距離中最小的那個(gè)侨舆,然后取其中的最大值。

42 接雨水


下篇:Leetcode題目分析思路總結(jié)(二)

參考:

Leetbook-2021 春招沖刺攻略
程序員代碼面試指南

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末绢陌,一起剝皮案震驚了整個(gè)濱河市挨下,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌脐湾,老刑警劉巖臭笆,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異秤掌,居然都是意外死亡愁铺,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門闻鉴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來茵乱,“玉大人,你說我怎么就攤上這事孟岛∑拷撸” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵渠羞,是天一觀的道長(zhǎng)斤贰。 經(jīng)常有香客問我,道長(zhǎng)堵未,這世上最難降的妖魔是什么腋舌? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮渗蟹,結(jié)果婚禮上块饺,老公的妹妹穿的比我還像新娘。我一直安慰自己雌芽,他們只是感情好授艰,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著世落,像睡著了一般淮腾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上屉佳,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天谷朝,我揣著相機(jī)與錄音,去河邊找鬼武花。 笑死体箕,一個(gè)胖子當(dāng)著我的面吹牛跃须,可吹牛的內(nèi)容都是我干的尽楔。 我是一名探鬼主播轻要,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼凡恍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起钧舌,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤撞牢,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體砰嘁,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡缅阳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡紊撕,死狀恐怖区赵,靈堂內(nèi)的尸體忽然破棺而出逞泄,到底是詐尸還是另有隱情各谚,我是刑警寧澤憔四,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布般眉,位于F島的核電站,受9級(jí)特大地震影響潜支,放射性物質(zhì)發(fā)生泄漏甸赃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一冗酿、第九天 我趴在偏房一處隱蔽的房頂上張望埠对。 院中可真熱鬧,春花似錦裁替、人聲如沸项玛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽襟沮。三九已至,卻和暖如春裕循,著一層夾襖步出監(jiān)牢的瞬間臣嚣,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工剥哑, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人淹父。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓株婴,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親暑认。 傳聞我的和親對(duì)象是個(gè)殘疾皇子困介,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

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

  • 此博文是繼動(dòng)態(tài)規(guī)劃總結(jié)之后的案例分析 動(dòng)態(tài)規(guī)劃的代碼很簡(jiǎn)潔,基本在20行以內(nèi)蘸际。 一維狀態(tài)定義53 最大子序和要求元...
    wanghuohuo0716閱讀 526評(píng)論 0 0
  • 一粮彤、線性表根穷、數(shù)組基礎(chǔ) 很多問題就是在一個(gè)數(shù)組中解決的棧、隊(duì)列导坟、堆的底層都是基于數(shù)組屿良,封裝的數(shù)據(jù)結(jié)構(gòu),后面我們會(huì)遇到...
    奔向算法的喵閱讀 1,088評(píng)論 0 5
  • 原文歡迎關(guān)注http://blackblog.tech/2018/06/03/LeetCodeReview/歡迎關(guān)...
    BlackBlog__閱讀 1,918評(píng)論 0 9
  • to-do:看一下別人寫的題解 https://github.com/981377660LMT/algorithm...
    winter_sweetie閱讀 743評(píng)論 1 0
  • 我是黑夜里大雨紛飛的人啊 1 “又到一年六月惫周,有人笑有人哭尘惧,有人歡樂有人憂愁,有人驚喜有人失落递递,有的覺得收獲滿滿有...
    陌忘宇閱讀 8,536評(píng)論 28 53