鏈表

今天開始抽空刷一些leetcode里數(shù)據(jù)結(jié)構(gòu)的題,在這里記錄下來(lái)。按難易程度開始刷吧。

第一次更新:2018.10.15

237、刪除鏈表中的節(jié)點(diǎn)
開始看題的時(shí)候有點(diǎn)懵,沒(méi)太懂題目意思,刪除鏈表中值為某個(gè)值的節(jié)點(diǎn),但題目沒(méi)有給定鏈表。后來(lái)想了一會(huì),直接用該鏈表的下一個(gè)節(jié)點(diǎn)覆蓋掉這個(gè)節(jié)點(diǎn)就可以了。

class Solution(object):
    def deleteNode(self, node):
        """
        :type node: ListNode
        :rtype: void Do not return anything, modify node in-place instead.
        """
        if node:        
            node.val = node.next.val
            node.next = node.next.next

206、反轉(zhuǎn)鏈表
先用迭代實(shí)現(xiàn)

class Solution(object):
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if not head:
            return None
        a, b, c = None, head, head.next
        while c:
            b.next = a
            a, b, c = b, c, c.next
        b.next = a
        return b

再用遞歸

class Solution(object):
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if not head:
            return None
        elif not head.next:
            return head
        new_head = self.reverseList(head.next)
        head.next.next = head
        head.next = None
        return new_head

21、合并兩個(gè)有序鏈表

class Solution(object):
    def mergeTwoLists(self, l1, l2):
        head = ListNode(-1)
        temp = head
        while l1 and l2:
            if l1.val <= l2.val:
                temp.next = l1
                l1 = l1.next
                temp = temp.next
            else:
                temp.next = l2
                l2 = l2.next
                temp = temp.next
        if l1:
            temp.next = l1
        if l2:
            temp.next = l2
        return head.next

83、刪除排序鏈表中的重復(fù)元素

class Solution(object):
    def deleteDuplicates(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if not head:
            return None
        else:
            temp = head
            cur = head.next
            while cur:
                if cur.val != temp.val:
                    temp.next = cur
                    temp = temp.next
                cur = cur.next
            temp.next = None
            return head

203、移除鏈表元素

class Solution(object):
    def removeElements(self, head, val):
        """
        :type head: ListNode
        :type val: int
        :rtype: ListNode
        """ 
        new_head = ListNode(val-1)
        temp = new_head
        cur = head
        while cur:
            if cur.val != val:
                temp.next = cur
                temp = temp.next
            cur = cur.next
        temp.next = None
        return new_head.next

234、回文鏈表
第一次做的時(shí)候把值存在了列表里,然后判斷列表是不是回文列表。可以用雙指針找到中間的節(jié)點(diǎn),還要用到之前的反轉(zhuǎn)鏈表,代碼比較長(zhǎng),也是調(diào)試了幾次才AC。


class Solution(object):
    def isPalindrome(self, head):
        """
        :type head: ListNode
        :rtype: bool
        """
        def reverseList(head):
            """
            :type head: ListNode
            :rtype: ListNode
            """
            if not head:
                return None
            a, b, c = None, head, head.next
            while c:
                b.next = a
                a, b, c = b, c, c.next
            b.next = a
            return b

        if not head or not head.next:
            return True
        slow = head
        fast = head
        while fast.next:
            if not fast.next.next:
                break
            else:
                fast = fast.next.next
                slow = slow.next
        new_listnode = reverseList(slow.next)
        p = new_listnode
        q = head
        while p:
            if p.val != q.val:
                return False
            p = p.next
            q = q.next
        return True
        

第二次更新:2018.10.16

141、環(huán)形鏈表
使用快指針和慢指針就可以了

class Solution(object):
    def hasCycle(self, head):
        """
        :type head: ListNode
        :rtype: bool
        """
        if not head:
            return False
        slow = head
        fast = head
        while fast:
            if fast.next:
                fast = fast.next.next
                slow = slow.next
                if fast == slow:
                    return True
            else:
                return False
        else:
            return False

160、相交鏈表
劍指offer里面也有這題

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        p1 = headA
        p2 = headB
        while p1 != p2:
            p1 = p1.next if p1.next else headB
            p2 = p2.next if p2.next else headA
        return p1

109、有序鏈表轉(zhuǎn)換二叉搜索樹
今天在劍指offer里刷了一道二叉搜索樹轉(zhuǎn)雙向鏈表的,這道題反過(guò)來(lái)將鏈表轉(zhuǎn)二叉搜索樹。有序鏈表的順序就是二叉搜索樹的中序遍歷的順序。
只要找到中間的節(jié)點(diǎn),然后遞歸就可以了。但是鏈表找中間節(jié)點(diǎn)有點(diǎn)麻煩,可以用笨辦法先轉(zhuǎn)為列表再找中間節(jié)點(diǎn),然后重新轉(zhuǎn)化為節(jié)點(diǎn)。但用雙指針也可以找到中間節(jié)點(diǎn),不過(guò)在遞歸過(guò)程中不斷找中間節(jié)點(diǎn)有點(diǎn)困難,沒(méi)有寫出來(lái)。還是參考了別人的代碼

class Solution(object):
    def sortedListToBST(self, head):
        """
        :type head: ListNode
        :rtype: TreeNode
        """

        def convert(head, tail):
            if head == tail:
                return None
            if head.next == tail:
                return TreeNode(head.val)
            fast = head
            mid = head
            while fast != tail and fast.next != tail:
                fast = fast.next.next
                mid = mid.next
            root = TreeNode(mid.val)
            root.left = convert(head, mid)
            root.right = convert(mid.next, tail)
            return root

        return convert(head, None)

24、兩兩交換鏈表中的節(jié)點(diǎn)
直接用遞歸

class Solution(object):
    def swapPairs(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if not head:
            return None
        if not head.next:
            return head
        a, b = head, head.next
        temp = self.swapPairs(b.next)
        b.next = a
        a.next = temp
        return b

114、二叉樹轉(zhuǎn)為鏈表
要求原地修改二叉樹,所以不能先序遍歷再連接。

class Solution(object):
    def flatten(self, root):
        if not root:
            return None
        if root.left:
            self.flatten(root.left)
        if root.right:
            self.flatten(root.right)
        temp = root.right
        root.right = root.left
        root.left = None
        while root.right:
            root = root.right
        root.right = temp

148、排序鏈表
題目要求了時(shí)間復(fù)雜度:O(n log n)。好像快排,歸并排序,堆排序都是O(n log n)級(jí)別的,但我還沒(méi)看,先跳過(guò)


382、鏈表隨機(jī)節(jié)點(diǎn)
獲得長(zhǎng)度后用random模塊隨機(jī)一個(gè)數(shù)字代表第幾個(gè)節(jié)點(diǎn)

class Solution(object):

    def __init__(self, head):
        """
        @param head The linked list's head.
        Note that the head is guaranteed to be not null, so it contains at least one node.
        :type head: ListNode
        """
        import random
        self.head = head

    def getRandom(self):
        """
        Returns a random node's value.
        :rtype: int
        """
        if not self.head:
            return None
        length = 0
        cur = self.head
        while cur:
            length += 1
            cur = cur.next
        index = random.randint(0, length-1)
        cur = self.head
        for i in range(length):
            if i == index:
                return cur.val
            else:
                cur = cur.next
                i += 1

147、對(duì)鏈表進(jìn)行插入排序
劍指offer刷完我就去看排序!先跳過(guò)

328、奇偶鏈表
用了三個(gè)指針。

class Solution(object):
    def oddEvenList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if not head or not head.next:
            return head
        a, b, c = head, head.next, head.next.next
        new_head = b
        i = 0
        while c:
            i += 1 
            a.next = c
            a, b, c = b, c, c.next
        if i%2 == 0:
            a.next = new_head
        else:
            b.next = new_head
            a.next = None
        return head

第三次更新:2018.10.17
明天要開組會(huì),準(zhǔn)備了一晚上組會(huì)的東西= =,抓緊時(shí)間寫兩道題

143、重排鏈表
寫了很久,想法是后半段鏈表先翻轉(zhuǎn),然后前半段和后半段交叉連接就可以了。

class Solution(object):
    def reorderList(self, head):

        def reverse(head):
            if not head:
                return None
            a, b, c = None, head, head.next
            while c:
                b.next = a
                a, b, c = b, c, c.next
            b.next = a
            return b

        if  head and head.next:
            fast = head
            slow = head
            while fast.next:
                if fast.next.next:
                    fast = fast.next.next
                    slow = slow.next
                else:
                    break
            new_head = reverse(slow.next)
            a = head
            b = new_head
            final_head = ListNode(0)
            temp = final_head
            i = 0
            while b:
                if i%2==0:
                    temp.next = a
                    temp = temp.next
                    a = a.next
                if i%2 == 1:
                    temp.next = b
                    temp = temp.next
                    b = b.next
                i += 1
            temp.next = a
            if temp.next:
                temp.next.next = None
            head = temp.next

2、兩數(shù)相加
最簡(jiǎn)單的可以直接將數(shù)值取出來(lái)再相加。當(dāng)然有更好的解法,參考了別人的,用memory記錄進(jìn)位

class Solution(object):
    def addTwoNumbers(self, l1, l2):
        mem = 0
        new_head = ListNode(0)
        cur = new_head
        while l1 or l2:
            a = l1.val if l1 else 0
            b = l2.val if l2 else 0
            c = a + b
            if l1:
                l1 = l1.next
            if l2:
                l2 = l2.next
            cur.next = ListNode((c+mem)%10)
            cur = cur.next
            mem = (c+mem) // 10
        if mem != 0:
            cur.next = ListNode(mem)
        return new_head.next

445、兩數(shù)相加Ⅱ
這題跟上一題類似,不過(guò)上一題最高位處于鏈表的尾節(jié)點(diǎn),這題最高位處于頭節(jié)點(diǎn)。簡(jiǎn)單一點(diǎn)的可以將兩個(gè)鏈表反轉(zhuǎn)后再?gòu)?fù)制上一題的代碼,但應(yīng)該有更好的答案,但我沒(méi)想出來(lái)。網(wǎng)上搜了一下其實(shí)就是把值都取出來(lái)存在棧里==。看來(lái)是我想復(fù)雜了

class Solution(object):
    def addTwoNumbers(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        stack1 = []
        stack2 = []
        while l1:
            stack1.append(l1.val)
            l1 = l1.next
        while l2:
            stack2.append(l2.val)
            l2 = l2.next
        answer = None
        carry = 0
        while stack1 and stack2:
            add = stack1.pop() + stack2.pop() + carry
            carry = 1 if add >= 10 else 0
            temp = answer
            answer = ListNode(add % 10)
            answer.next = temp
        l = stack1 if stack1 else stack2
        while l:
            add = l.pop() + carry
            carry = 1 if add >= 10 else 0
            temp = answer
            answer = ListNode(add % 10)
            answer.next = temp
        if carry:
            temp = answer
            answer = ListNode(1)
            answer.next = temp
        return answer

86、分隔鏈表
用了個(gè)比較笨的辦法,用一個(gè)新鏈表存儲(chǔ)小于目標(biāo)值的節(jié)點(diǎn),另一個(gè)新鏈表存儲(chǔ)其它節(jié)點(diǎn),最后再合并

class Solution(object):
    def partition(self, head, x):
        """
        :type head: ListNode
        :type x: int
        :rtype: ListNode
        """
        smallhead = ListNode(-1)
        bighead = ListNode(-1)
        a , b= smallhead, bighead
        cur = head
        while cur:
            if cur.val < x:
                a.next = cur
                a = a.next
                cur = cur.next
            else :
                b.next = cur
                b = b.next
                cur = cur.next
        a.next = None
        b.next = None
        cur = smallhead
        while cur.next:
            cur = cur.next
        cur.next = bighead.next
        return smallhead.next

92、反轉(zhuǎn)鏈表Ⅱ
跟反轉(zhuǎn)鏈表第一題差不多,注意一下反轉(zhuǎn)的界限就可以了。實(shí)際寫的時(shí)候出了很多問(wèn)題,最終還是沒(méi)寫出來(lái)。。參考別人代碼,實(shí)際思路是一樣的

class Solution:
    def reverseBetween(self, head, m, n):
        """
        :type head: ListNode
        :type m: int
        :type n: int
        :rtype: ListNode
        """
        if head == None or head.next == None or m >= n or m < 0 or n < 0:
            return head

        h = ListNode(-1)
        h.next = head
        pre = h
        cur = head
        i = 1
        while i < m and cur != None:
            pre = cur
            cur = cur.next
            i += 1

        t1 = pre
        t2 = cur

        while i <= n and cur != None:
            lat = cur.next
            cur.next = pre
            pre = cur 
            cur = lat
            i += 1

        t1.next = pre
        t2.next = cur
        return h.next

2018.10.20

82、刪除鏈表中的重復(fù)元素Ⅱ

class Solution:
    # @param head, a ListNode
    # @return a ListNode
    def deleteDuplicates(self, head):
        if not head:
            return None
        new_head = ListNode(head.val - 1)
        temp = new_head
        a, b, c = temp, head, head.next
        while b:
            if not c:
                if b.val != a.val:
                    temp.next = b
                    break
                else:
                    temp.next = None
                    break
            elif a.val != b.val != c.val:
                temp.next = b
                temp = b
                a, b, c = b, c, c.next
            else:
                a, b, c = b, c, c.next
        b.next = None
        return new_head.next

61、旋轉(zhuǎn)鏈表
調(diào)試了很久才AC。

class Solution(object):
    def rotateRight(self, head, k):
        if not head:
            return None
        if k == 0:
            return head
        length = 0
        cur = head
        while cur:
            length += 1
            cur = cur.next
        if length == 1 or k%length==0:
            return head
        pos = length - k % length + 1
        cur = head
        i = 1
        while i < pos-1:
            cur = cur.next
            i += 1
        temp = cur
        new_head = cur.next
        cur = cur.next
        while cur.next:
            cur = cur.next
        temp.next = None
        cur.next = head
        return new_head

19、刪除鏈表的倒數(shù)第N個(gè)節(jié)點(diǎn)
遍歷兩遍鏈表的話很容易,但一遍的話沒(méi)想到該怎么做。參考別人的答案:https://blog.csdn.net/dongrongyu/article/details/78346583

想法是這樣的:維護(hù)兩個(gè)指針,pre和end。一開始初始化時(shí)使得pre指針指向鏈表頭節(jié)點(diǎn),end指針指向pre+n的節(jié)點(diǎn)位置。然后同時(shí)往后移動(dòng)pre和end指針位置,使得end指針指向最后一個(gè)節(jié)點(diǎn),那么pre指針指向的則是end-n的節(jié)點(diǎn)位置(即倒數(shù)第n個(gè)元素的前一個(gè)節(jié)點(diǎn)),則將其刪除。

class Solution(object):
    def removeNthFromEnd(self, head, n):
        """
        :type head: ListNode
        :type n: int
        :rtype: ListNode
        """
        if not head:
            return None
        fast = head
        for i in range(n):
            fast = fast.next
        if not fast:
            return head.next
        slow = head
        while fast.next:
            fast = fast.next
            slow = slow.next
        slow.next = slow.next.next
        return head

142、環(huán)形鏈表Ⅱ
劍指offer里刷過(guò)了

class Solution(object):
    def detectCycle(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if not head:
            return None
        fast = head
        slow = head
        while fast.next:
            if not fast.next.next:
                return None
            else:
                fast = fast.next.next
                slow = slow.next
                if fast == slow:
                    if fast==head:
                        return head
                    slow = head
                    while True:
                        fast = fast.next
                        slow = slow.next
                        if fast == slow:
                            return fast
        return None
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,401評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,011評(píng)論 3 413
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,263評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,543評(píng)論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,323評(píng)論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,874評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,968評(píng)論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,095評(píng)論 0 286
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,605評(píng)論 1 331
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,551評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,720評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,242評(píng)論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 43,961評(píng)論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,358評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,612評(píng)論 1 280
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,330評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,690評(píng)論 2 370

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