数据结构归纳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
行动是治愈恐惧的良药,而犹豫拖延将不断滋养恐惧。