1. 程式人生 > 其它 >leetcode初級演算法——連結串列

leetcode初級演算法——連結串列

技術標籤:leetcode連結串列演算法python

(題目源自leetcode,方法都是自(cai)己(ji)寫的,可能比較符合菜雞們的思路)
連結串列是做到現在,感覺自己最拉垮的一節,資料結構真的都還給老師了

1.刪除連結串列中的節點

請編寫一個函式,使其可以刪除某個連結串列中給定的(非末尾)節點。傳入函式的唯一引數為 要被刪除的節點 。

示例 1:

輸入:head = [4,5,1,9], node = 5
輸出:[4,1,9]
解釋:給定你連結串列中值為 5 的第二個節點,那麼在呼叫了你的函式之後,該連結串列應變為 4 -> 1 -> 9.

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

一開始沒看到啥意思,後來發現,給的node,就是讓你刪除的node。。。

2.刪除連結串列的倒數第N個節點

給定一個連結串列,刪除連結串列的倒數第 n 個節點,並且返回連結串列的頭結點。

示例:

給定一個連結串列: 1->2->3->4->5, 和 n = 2.

當刪除了倒數第二個節點後,連結串列變為 1->2->3->5.

class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        len = 0
        mid = head
        if head.next == None:
            return
head.next while mid != None: mid = mid.next len = len + 1 target = len - n mid = head while target > 1: mid = mid.next target = target - 1 if mid.next != None and target != 0: mid.next = mid.next.next if target == 0: head = head.next return head

比較蠢的辦法,用了兩次遍歷,第一次算出連結串列的總長度,第二次,根據n求出正方向遍歷的節點位置,刪掉。

也可以用快慢指標,快指標提前出發n步
或者用迭代回溯,回溯n次
(感覺連結串列相關的,很多都需要迭代回溯)

3.反轉連結串列

反轉一個單鏈表。

示例:

輸入: 1->2->3->4->5->NULL
輸出: 5->4->3->2->1->NULL

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        if head == None or head.next == None:
            return head
        out = self.reverseList(head.next)
        head.next.next = head
        head.next = None
        return out

使用迭代回溯,這裡注意,其實out自始至終都沒有變過,就是指在了最後一個node,變得是head.next.next = head,而且head.next一定得擦除,不然會無限迴圈

4.合併兩個有序連結串列

將兩個升序連結串列合併為一個新的 升序 連結串列並返回。新連結串列是通過拼接給定的兩個連結串列的所有節點組成的。

示例:

輸入:1->2->4, 1->3->4
輸出:1->1->2->3->4->4

class Solution:
    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
        if not l1: return l2
        if not l2: return l1
        if l1.val<=l2.val:
            l1.next = self.mergeTwoLists(l1.next,l2)
            return l1
        else:
            l2.next = self.mergeTwoLists(l1,l2.next)
            return l2

明明很簡單,自己想了好久。還是用遞迴,自己在連結串列的遞迴方面真的太不熟練了

5.迴文連結串列

請判斷一個連結串列是否為迴文連結串列。

示例 1:

輸入: 1->2
輸出: false

class Solution:
    def isPalindrome(self, head: ListNode) -> bool:
        out = []
        while head:
            out.append(head.val)
            head = head.next
        return True if out[:]==out[::-1] else False

就是遍歷了連結串列,把所有的值放進了列表裡,然後判斷列表是否迴文。

6.環形連結串列

給定一個連結串列,判斷連結串列中是否有環。

如果連結串列中有某個節點,可以通過連續跟蹤 next 指標再次到達,則連結串列中存在環。 為了表示給定連結串列中的環,我們使用整數 pos 來表示連結串列尾連線到連結串列中的位置(索引從 0 開始)。 如果 pos 是 -1,則在該連結串列中沒有環。注意:pos 不作為引數進行傳遞,僅僅是為了標識連結串列的實際情況。

如果連結串列中存在環,則返回 true 。 否則,返回 false 。

進階:

你能用 O(1)(即,常量)記憶體解決此問題嗎?
示例 1:

在這裡插入圖片描述

輸入:head = [3,2,0,-4], pos = 1
輸出:true
解釋:連結串列中有一個環,其尾部連線到第二個節點。

class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        if not head:
            return False
        slow = head
        quick = head.next
        while slow != quick:
            if not quick or not quick.next or not slow.next:
                return False
            slow = slow.next
            quick = quick.next.next
        return True

還是用了快慢指標,慢指標走一步,快指標走兩步,兩個指標指向同一個node,就證明有環。
還可以定義一個hash={},遍歷連結串列,把node放進hash表裡,遇到重複的,就證明是有環。