[劍指Offer]49~52

學(xué)習(xí)使用工具

劍指Offer http://itmyhome.com/sword-means-offer/sword-means-offer.pdf

LeetCode的劍指Offer題庫 https://leetcode.cn/problemset/all/

劍指 Offer 49. 丑數(shù)

我們把只包含質(zhì)因子 2夸浅、3 和 5 的數(shù)稱作丑數(shù)(Ugly Number)很澄。求按從小到大的順序的第 n 個(gè)丑數(shù)臭觉。

示例:

輸入: n = 10
輸出: 12
解釋: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 個(gè)丑數(shù)。

**說明: **

  1. 1 是丑數(shù)廓俭。
  2. n 不超過1690。

解法:

1是丑數(shù)唉工,剩下的丑數(shù)都可以由已知丑數(shù)乘2研乒、3、5得到淋硝。

建立三個(gè)一模一樣的列表雹熬,記錄丑數(shù)序列。同時(shí)設(shè)置3個(gè)指針谣膳,分別遍歷三個(gè)列表中的元素竿报,被遍歷過的數(shù)已經(jīng)被用于做乘子來得到更大的丑數(shù)。而三個(gè)列表分別記錄該數(shù)是否已經(jīng)被乘過2继谚、3或5烈菌。

設(shè)置計(jì)數(shù)變量i,每次循環(huán)尋找下一個(gè)最小的丑數(shù)花履,并令對(duì)應(yīng)列表的指針后移一位芽世。同時(shí)判定該數(shù)是否已經(jīng)被加入列表,如果已經(jīng)加入诡壁,則繼續(xù)尋找济瓢;若沒有辞槐,則將該數(shù)加入列表坡贺,并使i+1。當(dāng)i已經(jīng)計(jì)數(shù)到n時(shí)岖寞,結(jié)束循環(huán)纽帖。返回列表中的第n個(gè)數(shù)即可。

def nthUglyNumber(self, n: int) -> int:
        ans2 = [1]
        ans3 = [1]
        ans5 = [1]
        poi2 = 0
        poi3 = 0
        poi5 = 0
        i = 0

        while i < n:
            temp = min(ans2[poi2]*2, ans3[poi3]*3, ans5[poi5]*5)
            if temp == ans2[poi2]*2:
                poi2 += 1
            elif temp == ans3[poi3]*3:
                poi3 += 1
            else: 
                poi5 += 1
            if not temp in [ans2[-1], ans3[-1], ans5[-1]]:
                ans2.append(temp)
                ans3.append(temp)
                ans5.append(temp)
                i += 1

        return ans2[n - 1]

劍指 Offer 50. 第一個(gè)只出現(xiàn)一次的字符

在字符串 s 中找出第一個(gè)只出現(xiàn)一次的字符举反。如果沒有懊直,返回一個(gè)單空格。 s 只包含小寫字母火鼻。

示例 1:

輸入:s = "abaccdeff"
輸出:'b'

示例 2:

輸入:s = "" 
輸出:' '

限制:

0 <= s 的長度 <= 50000

解法:

開辟flag數(shù)組進(jìn)行記錄室囊。flag[i]記錄26個(gè)小寫字母是否出現(xiàn)過。遍歷原始字符串魁索,檢查每個(gè)字符融撞,如果該字符未出現(xiàn)過,則將對(duì)應(yīng)flag置為1粗蔚;如果已出現(xiàn)過尝偎,從字符串中刪去所有該字符。遍歷結(jié)束后,返回結(jié)果字符串中的第一個(gè)字符致扯。

def firstUniqChar(self, s: str) -> str:
        flag = [0] * 26
        ans = s

        for c in s:
            if flag[ord(c) - ord('a')] == 0:
                flag[ord(c) - ord('a')] = 1
            else:
                ans = ans.replace(c, '')

        if ans:
            return ans[0]
        else:
            return ' '

劍指 Offer 51. 數(shù)組中的逆序?qū)?/strong>

在數(shù)組中的兩個(gè)數(shù)字肤寝,如果前面一個(gè)數(shù)字大于后面的數(shù)字,則這兩個(gè)數(shù)字組成一個(gè)逆序?qū)Χ督]斎胍粋€(gè)數(shù)組鲤看,求出這個(gè)數(shù)組中的逆序?qū)Φ目倲?shù)。

示例 1:

輸入: [7,5,6,4]
輸出: 5

限制:

0 <= 數(shù)組長度 <= 50000

解法:

進(jìn)行一次歸并排序耍群。在合并階段义桂,記錄逆序?qū)倲?shù)即可。

def reversePairs(self, nums: List[int]) -> int:
        temp = [0] * len(nums) # 輔助數(shù)組蹈垢,用于歸并階段
        def merge(l: int, r: int): # 歸并排序慷吊,返回值為此數(shù)組所含的逆序?qū)倲?shù)
            if l >= r: # 如果l>=r,說明此時(shí)子數(shù)組的長度已經(jīng)<=1耘婚,返回0
                return 0
            
            m = (l + r) // 2 # 劃分
            res = merge(l, m) + merge(m + 1, r) # res等于左右兩個(gè)數(shù)組各自劃分后得到的逆序?qū)倲?shù)

            i = l # 左指針遍歷左數(shù)組
            j = m + 1 # 右指針遍歷右數(shù)組
            temp[l: r + 1] = nums[l: r + 1] # temp保存原始數(shù)組的值便于歸并
            for k in range(l, r + 1): # 歸并階段罢浇,k表示當(dāng)前的排序位置,每次將對(duì)應(yīng)的元素置于nums[k]
                if i == m + 1: # 如果左指針已經(jīng)遍歷完畢沐祷,則將右指針數(shù)字加入排序位置嚷闭,右指針后移
                    nums[k] = temp[j]
                    j += 1
                elif j == r + 1: # 如果右指針已經(jīng)遍歷完畢,則將左指針數(shù)字加入排序位置赖临,左指針后移
                    nums[k] = temp[i]
                    i += 1
                elif temp[i] <= temp[j]:# 如果左指針小于右指針胞锰,則將左指針數(shù)字加入排序位置,左指針后移
                    nums[k] = temp[i]
                    i += 1
                else: 
                # 如果左指針大于右指針兢榨,則將右指針數(shù)字加入排序位置嗅榕,右指針后移。
                # 此時(shí)產(chǎn)生數(shù)量為(m-i+1)的逆序?qū)Γ醋髷?shù)組剩下的元素?cái)?shù)量)吵聪,加入res
                    nums[k] = temp[j]
                    j += 1
                    res += m - i + 1
            return res

        return merge(0, len(nums) - 1)

劍指 Offer 52. 兩個(gè)鏈表的第一個(gè)公共節(jié)點(diǎn)

輸入兩個(gè)鏈表凌那,找出它們的第一個(gè)公共節(jié)點(diǎn)。

如下面的兩個(gè)鏈表

示例

在節(jié)點(diǎn) c1 開始相交吟逝。

示例 1:

示例1
輸入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
輸出:Reference of the node with value = 8
輸入解釋:相交節(jié)點(diǎn)的值為 8 (注意帽蝶,如果兩個(gè)列表相交則不能為 0)。從各自的表頭開始算起块攒,鏈表 A 為 [4,1,8,4,5]励稳,鏈表 B 為 [5,0,1,8,4,5]。在 A 中囱井,相交節(jié)點(diǎn)前有 2 個(gè)節(jié)點(diǎn)驹尼;在 B 中,相交節(jié)點(diǎn)前有 3 個(gè)節(jié)點(diǎn)庞呕。

示例 2:

示例2
輸入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
輸出:Reference of the node with value = 2
輸入解釋:相交節(jié)點(diǎn)的值為 2 (注意新翎,如果兩個(gè)列表相交則不能為 0)。從各自的表頭開始算起,鏈表 A 為 [0,9,1,2,4]料祠,鏈表 B 為 [3,2,4]骆捧。在 A 中,相交節(jié)點(diǎn)前有 3 個(gè)節(jié)點(diǎn)髓绽;在 B 中敛苇,相交節(jié)點(diǎn)前有 1 個(gè)節(jié)點(diǎn)。

示例 3:

示例3
輸入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
輸出:null
輸入解釋:從各自的表頭開始算起顺呕,鏈表 A 為 [2,6,4]枫攀,鏈表 B 為 [1,5]。由于這兩個(gè)鏈表不相交株茶,所以 intersectVal 必須為 0来涨,而 skipA 和 skipB 可以是任意值。
解釋:這兩個(gè)鏈表不相交启盛,因此返回 null蹦掐。

注意:

  • 如果兩個(gè)鏈表沒有交點(diǎn),返回 null.
  • 在返回結(jié)果后僵闯,兩個(gè)鏈表仍須保持原有的結(jié)構(gòu)卧抗。
  • 可假定整個(gè)鏈表結(jié)構(gòu)中沒有循環(huán)。
  • 程序盡量滿足 O(n) 時(shí)間復(fù)雜度鳖粟,且僅用 O(1) 內(nèi)存社裆。

解法:

自己寫的稍微有點(diǎn)笨蛋的解法,先獲取兩個(gè)鏈表的長度向图,然后截去長鏈表的開頭部分讓兩個(gè)鏈表一樣長泳秀,之后再遍歷就行了。

def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        if not headA or not headB:
            return None
        
        def getlen(head: ListNode):
            count = 0
            while head:
                count += 1
                head = head.next
            return count
        
        lenA = getlen(headA)
        lenB = getlen(headB)

        if lenA >= lenB:
            A = headA
            for i in range(lenA - lenB):
                A = A.next
            B = headB
        else:
            A = headB
            for i in range(lenB - lenA):
                A = A.next
            B = headA

        while A:
            if A == B:
                return A
            A = A.next
            B = B.next

        return A

翻答案發(fā)現(xiàn)有更好的雙指針相遇解法榄攀,截取一下K神的解說:

考慮構(gòu)建兩個(gè)節(jié)點(diǎn)指針 A , B 分別指向兩鏈表頭節(jié)點(diǎn) headA , headB 嗜傅,做如下操作:

指針 A 先遍歷完鏈表 headA ,再開始遍歷鏈表 headB 檩赢,當(dāng)走到 node 時(shí)磺陡,共走步數(shù)為:a+(b?c)

指針 B 先遍歷完鏈表 headB ,再開始遍歷鏈表 headA 漠畜,當(dāng)走到 node 時(shí),共走步數(shù)為:b+(a?c)

如下式所示坞靶,此時(shí)指針 A , B 重合憔狞,并有兩種情況:

a+(b?c)=b+(a?c)

若兩鏈表 有 公共尾部 (即c>0) :指針 A , B 同時(shí)指向「第一個(gè)公共節(jié)點(diǎn)」node 。

若兩鏈表 無 公共尾部 (即c=0) :指針 A , B 同時(shí)指向 null彰阴。

因此返回 A 即可瘾敢。

def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        A, B = headA, headB
        while A != B:
            A = A.next if A else headB
            B = B.next if B else headA
        return A
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子簇抵,更是在濱河造成了極大的恐慌庆杜,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件碟摆,死亡現(xiàn)場離奇詭異晃财,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)典蜕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門断盛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人愉舔,你說我怎么就攤上這事钢猛。” “怎么了轩缤?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵命迈,是天一觀的道長。 經(jīng)常有香客問我火的,道長壶愤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任卫玖,我火速辦了婚禮公你,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘假瞬。我一直安慰自己陕靠,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布脱茉。 她就那樣靜靜地躺著剪芥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪琴许。 梳的紋絲不亂的頭發(fā)上税肪,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音榜田,去河邊找鬼益兄。 笑死,一個(gè)胖子當(dāng)著我的面吹牛箭券,可吹牛的內(nèi)容都是我干的净捅。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼辩块,長吁一口氣:“原來是場噩夢啊……” “哼蛔六!你這毒婦竟也來了荆永?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤国章,失蹤者是張志新(化名)和其女友劉穎具钥,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體液兽,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡骂删,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了抵碟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桃漾。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖拟逮,靈堂內(nèi)的尸體忽然破棺而出撬统,到底是詐尸還是另有隱情,我是刑警寧澤敦迄,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布恋追,位于F島的核電站,受9級(jí)特大地震影響罚屋,放射性物質(zhì)發(fā)生泄漏苦囱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一脾猛、第九天 我趴在偏房一處隱蔽的房頂上張望撕彤。 院中可真熱鬧,春花似錦猛拴、人聲如沸羹铅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽职员。三九已至,卻和暖如春跛溉,著一層夾襖步出監(jiān)牢的瞬間焊切,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來泰國打工芳室, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留专肪,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓堪侯,卻偏偏與公主長得像嚎尤,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子抖格,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

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

  • 《算法文章匯總》[http://www.reibang.com/p/fc7c0e8cc5cb] 劍指 Offer...
    一畝三分甜閱讀 235評(píng)論 0 0
  • 一诺苹,常見數(shù)據(jù)結(jié)構(gòu) 1,數(shù)組 3-找出數(shù)組中重復(fù)的數(shù)字 劍指 Offer 03. 數(shù)組中重復(fù)的數(shù)字[https://...
    嵌入式視覺閱讀 331評(píng)論 0 0
  • 技術(shù)交流QQ群:1027579432雹拄,歡迎你的加入收奔! 歡迎關(guān)注我的微信公眾號(hào):CurryCoder的程序人生 1....
    CurryCoder閱讀 1,851評(píng)論 0 2
  • 27. 二叉樹的鏡像 求一棵樹的鏡像的過程:先前序遍歷這棵樹的每個(gè)節(jié)點(diǎn),如果遍歷到的節(jié)點(diǎn)有子節(jié)點(diǎn)滓玖,就交換它的兩個(gè)子...
    oneoverzero閱讀 290評(píng)論 0 2
  • 前文回顧 之前我們使用三天的時(shí)間坪哄,學(xué)習(xí)了整數(shù)章節(jié)的知識(shí)學(xué)習(xí)。并在Day4的總結(jié)中势篡,結(jié)合讀者們關(guān)于算法學(xué)習(xí)和刷題過程...
    清風(fēng)Python閱讀 88評(píng)論 0 1