LeetCode刷题笔记——链表(python实现)

实现单链表

  用虚拟头结点+precNode+curNode

class Node:
    def __init__(self, val):
        self.val = val
        self.Next = None


class MyLinkedList:

    def __init__(self):
        self.head = Node(0)
        self.counter = 0

    def get(self, index: int) -> int:
        if index < 0 or index >= self.counter:
            return -1
        else:
            node = self.head
            for i in range(index + 1):
                node = node.Next
            return node.val

    def addAtHead(self, val: int) -> None:
        self.addAtIndex(0, val)

    def addAtTail(self, val: int) -> None:
        self.addAtIndex(self.counter, val)

    def addAtIndex(self, index: int, val: int) -> None:
        if index < 0:
            index = 0
        elif index > self.counter:
            return
        self.counter += 1
        
        pre_node = None
        cur_node = self.head
        add_node = Node(val)

        for i in range(index + 1):
            pre_node, cur_node = cur_node, cur_node.Next
        else:
            pre_node.Next,add_node.Next = add_node, cur_node
             

    def deleteAtIndex(self, index: int) -> None:
        if 0 <= index < self.counter:
            self.counter -= 1
            pre_node = None
            cur_node = self.head
            for i in range(index + 1):
                pre_node, cur_node = cur_node, cur_node.Next
            else:            
                pre_node.Next, cur_node.Next = cur_node.Next, None
            
        

实现双链表

  自定义_get_node()函数与_update()函数,减少代码量,调用方便

class Node:
    def __init__(self, val):
        self.val = val
        self.next = None
        self.prev = None

class MyLinkedList:
    def __init__(self):
        self.head = Node(0)
        self.tail = Node(0)
        self.head.next = self.tail
        self.tail.prev = self.head
        self.count = 0

    def _get_node(self, index: int) -> Node:
        # 当index小于_count//2时, 使用_head查找更快, 反之_tail更快
        if index >= self.count // 2:
            # 使用prev往前找
            node = self.tail
            for _ in range(self.count - index):
                node = node.prev
        else:
            # 使用next往后找
            node = self.head   
            for _ in range(index + 1):
                node = node.next
        return node

    def get(self, index: int) -> int:
        if 0 <= index < self.count:
            node = self._get_node(index)
            return node.val
        else:
            return -1


    def addAtHead(self, val: int) -> None:
        self._update(self.head, self.head.next, val)


    def addAtTail(self, val: int) -> None:
        self._update(self.tail.prev, self.tail, val)

    def addAtIndex(self, index: int, val: int) -> None:
        if index < 0:
            index = 0
        elif index > self.count:
            return
        
        node = self._get_node(index)
        self._update(node.prev, node, val)


    def _update(self, prev, next, val):
        self.count += 1
        node = Node(val)
        prev.next, next.prev = node, node
        node.prev, node.next = prev, next

    def deleteAtIndex(self, index: int) -> None:
        if 0 <= index < self.count:
            node = self._get_node(index)
            self.count -= 1
            
            node.prev.next, node.next.prev = node.next, node.prev

        else:
            return



# Your MyLinkedList object will be instantiated and called as such:
# obj = MyLinkedList()
# param_1 = obj.get(index)
# obj.addAtHead(val)
# obj.addAtTail(val)
# obj.addAtIndex(index,val)
# obj.deleteAtIndex(index)

删除链表元素

  用虚拟头结点非常方便,且逻辑清晰

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeElements(self, head: ListNode, val: int) -> ListNode:
        prev = ListNode(next = head)
        dummyhead = prev
        cur = head
        while cur != None:
            if cur.val == val:
                prev.next, cur = cur.next, cur.next
            else:
                prev, cur = prev.next, cur.next

        return dummyhead.next

反转链表

  需要一个cur指针,一个prev指针,prev初始化为None,cur初始化为head,循环过程中还需要一个tmp指针保存cur.next

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        pre = None
        cur = head

        while cur != None:
            cnext = cur.next
            cur.next = pre
            cur, pre = cnext, cur

        return pre

两两交换链表中的节点:

  把节点前后位置都保存下来,加上虚拟头结点,思路会更加清晰。
  一定要画图辅助理清思路

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def swapPairs(self, head: ListNode) -> ListNode:
        dummyhead = ListNode(next = head)
        prev = dummyhead
        
        # 必须有pre的下一个和下下个才能交换,否则说明已经交换结束了
        while prev.next != None and prev.next.next != None:
            cur = prev.next #给两个指针赋值
            cnext = prev.next.next

            prev.next = cur.next
            cur.next = cnext.next
            cnext.next = cur

            prev = prev.next.next

        return dummyhead.next

删除链表的倒数第N个节点

  用快慢双指针,快指针先走N步,慢指针再开始跟快指针一起走。
  当快指针到尾节点的时候,慢指针则位于倒数第N个节点处。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        dummyhead = ListNode(next = head)
        slow, fast = dummyhead, dummyhead

        for i in range(n):
            fast = fast.next

        while fast.next != None:#为了方便删除,定位到的其实是要删除节点的前一个
            fast = fast.next
            slow = slow.next

        slow.next = slow.next.next

        return dummyhead.next

链表相交

  两个单链表相交的起始节点,即找到链表交点节点的指针。
  先求出两个链表的长度,并求出两个链表长度的差值,然后让curA移动到和curB离末尾相同距离的位置。此时就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB;如果遇到curA == curB,则找到交点;否则循环退出返回空指针

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

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        lenA, lenB = 0, 0
        curA, curB = headA, headB
        
        #得到A,B的长度
        while curA:
            lenA += 1
            curA = curA.next

        while curB:
            lenB += 1
            curB = curB.next

        curA = headA
        curB = headB
        #保证A为较长链表
        if lenA < lenB:
            lenA, lenB = lenB, lenA
            curA, curB = curB, curA

        #两链表尾部对齐
        for i in range(lenA - lenB):
            curA = curA.next

        while curA:
            if curA == curB:
                return curA
            curA = curA.next
            curB = curB.next

        return None

环形链表

  给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
判断链表是否有环:
  设定快慢指针,快指针每次走两步,慢指针每次走一步,如果快慢指针相遇了,则说明有环存在。
有环,如何找到这个环的入口:
  从头结点和快慢指针相遇结点处分别出发一个指针,两个指针相遇的地方即为入口处

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

class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        fast, slow = head, head
        while fast and fast.next:
            fast = fast.next.next
            slow = slow.next
            if fast == slow:#证明有环
                p = head
                q = fast
                while p != q:
                    p = p.next
                    q = q.next
                return p

        return None

你可能感兴趣的:(链表,leetcode,python)