数据结构归纳1-链表

0,技巧

1,巧用python的同步赋值,同步赋值时先计算等号右边再给左边依此赋值,注意左边的顺序不要相互干扰
例子1,取反:
nodeBefore, node = head, head.next
while node:
  node.next, nodeBefore, node = nodeBefore, node, node.next
return nodeBefore
例子2,两两交换链表中的值:
nodeBefore.next, node.next, nodeAfter.next, nodeBefore, node, nodeAfter = nodeAfter, nodeAfter.next, node, node, nodeAfter.next, nodeAfter.next.next

2,在链表首添加节点以防止节点位置移动后,原有的链表首变为新的节点
newHead = ListNode(None, head)
...
return newHead.next

3,头插法思维:
记录要交换的链表段的起始节点Node,和Node的前一个节点BeforeNode,将要交换的节点依此链接到Node前面
BeforeNode.next, Node.next.next, Node.next = node.next, BeforeNode.next, Node.next.next    (注意等号左边Node.next.next, Node.next的相对顺序不能变;原因为技巧1)
该思维在24. 两两交换链表中的节点,25. K 个一组翻转链表,92. 反转链表 II等与范围内链表反转的题目中都可应用

4,将一段链表切出来经过操作以后再拼接回去
操作前需要记录四个值:partBefore, partAfter, head, tail    分别对应:段前节点,段后节点,段首,段尾
操作后需要记录两个值:newhead,newtail  操作后新的段首,段尾
切割就是:tail.next=None  (此使从head出发就是一个独立的链表)
拼接就是:partBefore.next, newtail.next = newhead, partAfter

5,快慢指针
用处1-需要切出右侧k长度的链表段:fast指针先走k个node,然后slow和fast指针同时右移到fast为None
用处2-判断是否有环((slow一次移动一个node,fast一次移动两个node,判断是否存在fast==slow)
用处3-寻找链表的重点(slow一次移动一个node,fast一次移动两个node)

链表的边界条件一定要慎之又慎

1,反转单向或双向链表

解题思路

保留三个连续的node,前两个反转,第三个记录

代码1

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        if head:
            nodeBefore = None
            node = head
            nodeAfter = node.next
            while nodeAfter:
                node.next = nodeBefore
                nodeBefore = node
                node = nodeAfter
                nodeAfter = nodeAfter.next
            node.next = nodeBefore
            return node
        else:
            return None

代码2

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
          nodeBefore = None
          node = head
          while node:
              node.next, nodeBefore, node = nodeBefore, node, node.next  #这里等号左边的node.next和node的位置不能互换,因为虽然等号是先计算右侧的值,再将右侧的值赋值给左侧,但是赋值也是从左到右依此进行的;如果先更新node的值,那么node.next就会相应的发生变化,所以应该先更新node.next的值,再更新node的值
          return nodeBefore

2,旋转链表

解题思路1

将各节点存储到列表中,对列表切片+拼接实现循环右移,再重新生成链表

代码1

class Solution:
    def rotateRight(self, head: ListNode, k: int) -> ListNode:
        
        if not head:
            return None

        stack = [head]
        head = head.next
        while head:
            stack.append(head)
            head = head.next
        transLength = k % len(stack)
        stack = stack[-transLength:] + stack[:-transLength]
        stack.append(None)

        for i in range(len(stack)-1):
            stack[-i-2].next = stack[-i-1]

        return stack[0]

解题思路2

求链表长度;
找出倒数第 k+1 个节点;
链表重整:将链表的倒数第 k+1 个节点和倒数第 k 个节点断开,并把后半部分拼接到链表的头部。

代码2

class Solution:
    def rotateRight(self, head, k):
        if not head or not head.next: return head
        # 求链表长度
        _len = 0
        cur = head
        while cur:
            _len += 1
            cur = cur.next
        # 对长度取模
        k %= _len
        if k == 0: return head
        # 让 fast 先向后走 k 步
        fast, slow = head, head
        while k:
            fast = fast.next
            k -= 1
        # 此时 slow 和 fast 之间的距离是 k;fast 指向第 k+1 个节点
        # 当 fast.next 为空时,fast 指向链表最后一个节点,slow 指向倒数第 k + 1 个节点
        while fast.next:
            fast = fast.next
            slow = slow.next
        # newHead 是倒数第 k 个节点,即新链表的头
        newHead = slow.next
        # 让倒数第 k + 1 个节点 和 倒数第 k 个节点断开
        slow.next = None
        # 让最后一个节点指向原始链表的头
        fast.next = head
        return newHead

posted @ 2021-12-22 14:47  tensor_zhang  阅读(39)  评论(0编辑  收藏  举报