1. 程式人生 > >Leetcode——初級部分——連結串列部分——Python實現

Leetcode——初級部分——連結串列部分——Python實現

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

請編寫一個函式,使其可以刪除某個連結串列中給定的(非末尾)節點,你將只被給定要求被刪除的節點。

現有一個連結串列 -- head = [4,5,1,9],它可以表示為:

4 -> 5 -> 1 -> 9

示例 1:

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

示例 2:

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

說明:

  • 連結串列至少包含兩個節點。
  • 連結串列中所有節點的值都是唯一的。
  • 給定的節點為非末尾節點並且一定是連結串列中的一個有效節點。
  • 不要從你的函式中返回任何結果。

我的解答:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

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 #當前結點的下一個結點是原來的下下個結點

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

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

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

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

說明:

給定的 n 保證是有效的。

進階:

你能嘗試使用一趟掃描實現嗎?

我的解答:

(1)定義2個指標p1,p2。

(2)使用迴圈讓p2指向順數第n個節點,同時p1指向第頭結點;

(3)然後,p1和p2同時移動,直到p2指向NULL,此時p1應該指向倒數第n個節點。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def removeNthFromEnd(self, head, n):
        """
        :type head: ListNode
        :type n: int
        :rtype: ListNode
        """
        #這裡head的type就是一個連結串列結點
        
        #連結串列只有一個元素的情況,需要刪除這個元素
        if(head.next == None):
            return None
        else:
            p1 = head
            p2 = head
            count = 0 #這個是控制node1和node2的位置的(倒數第幾個)
            while p1.next != None:
                p1 = p1.next
                if(count >= n):
                    p2 = p2.next
                count = count + 1
            #這時候第一個指標已經走到終點了,然後只需要刪除第二個指標指向的結點
            #刪除最後一個結點的情況
            if(n == 1):
                p2.next = None      
                return head
            #刪除第一個結點的情況
            elif(n - count == 1):
                return head.next
            else:
                p2.next = p2.next.next
                return head

三. 反轉連結串列

反轉一個單鏈表。

示例:

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

進階:

你可以迭代或遞迴地反轉連結串列。你能否用兩種方法解決這道題?

我的解答:


# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        # 第一次 p q r
        # 第二次   p q
        # ......
        
        if(head == None):
            return None
        else:
            p = head
            q = head.next
            p.next = None
            
            while q:
                r = q.next
                q.next = p
                p = q
                q = r
            return p

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

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

示例:

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

我的解答:

方法1:遞迴方法

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def mergeTwoLists(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        #方法一:遞迴
        if not l1 and not l2:
            return None
        if not l1:
            return l2
        if not l2:
            return l1
        if l1.val>=l2.val:
            l2.next = self.mergeTwoLists(l1,l2.next)
            return l2
        else:
            l1.next = self.mergeTwoLists(l1.next,l2)
            return l1

方法2:非遞迴

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def mergeTwoLists(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        #方法2:非遞迴
        head = ListNode(0)
        savehead = head #保留初始連結串列結點索引
        if not l1 and not l2:
            return None
        else:
            while l1 and l2:
                if l1.val >= l2.val:
                    head.next = l2
                    l2 = l2.next
                else:
                    head.next = l1
                    l1 = l1.next
                head = head.next
            if l1:
                head.next = l1
            if l2:
                head.next = l2
            return savehead.next

五. 迴文連結串列

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

示例 1:

輸入: 1->2
輸出: false

示例 2:

輸入: 1->2->2->1
輸出: true

進階:

你能否用 O(n) 時間複雜度和 O(1) 空間複雜度解決此題?

我的解答:

方法1:將連結串列中的數放到一個數組中,然後進行判斷

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def isPalindrome(self, head):
        """
        :type head: ListNode
        :rtype: bool
        """
        #解答1:將連結串列中的數放到一個數組中,然後進行判斷
        #完成連結串列——>陣列
        nums = []
        while head:
            nums.append(head.val)
            head = head.next
        #判斷陣列是否為迴文序列
        for i in range(len(nums)):
            if(nums[i] != nums[-i-1]):
                return False
        return True
方法2:快慢指標(1個走一步,1個走兩步)找到中點(指標1在中點,指標2在末尾),然後將後半部分進行逆序,最後兩部分進行比較看是否是迴文連結串列 

具體實現還沒寫出來

六. 環形連結串列

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

進階:
你能否不使用額外空間解決此題?

我的解答:

快慢指標(1個一次一格,另1個一次兩格),那麼如果有環的話,跑的快的一定會追滿的一圈(相當於每次next,兩個指標就會接近一步)。

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def hasCycle(self, head):
        """
        :type head: ListNode
        :rtype: bool
        """
        #判斷連結串列是否為空,如果為空,返回false
        if not head:
            return False
        #非空連結串列如下
        p1 = head
        p2 = head
        while p2.next and p2.next.next:
            p1 = p1.next
            p2 = p2.next.next
            if p1 == p2:
                return True
        return False