逐渐成为灵魂画手[doge]。。
复习链表:
链表中倒数第k个节点
class Solution:
def FindKthToTail(self, head, k):
# write code here, 快慢指针,k是两个指针的相对固定举例,当快指针到达None,慢指针就是结果
first = head
second = head
# 让快指针先走k步
for i in range(k):
if first == None: # 注意这里需要先判断哦
return None
first = first.next
# 当快指针到达None的时候,慢指针就是倒数第K个节点
while first:
first = first.next
second = second.next
return second
反转链表:
class Solution:
# 返回ListNode
def ReverseList(self, pHead):
# write code here
# 需要3个指针,分别指向比如第左号节点,让它的指针指向None,
# while 当最右边指针指向None的时候,这时的mid节点就是新的表头节点
# 让刚才的中号节点指针指向左号
# 向右同时移动一步,3个指针,左号变为中,中变为右号,右号指向下一个节点
# 注意边界
if pHead == None:
return None
if pHead.next == None:
return pHead
leftPointer = pHead
midPointer = leftPointer.next
rightPointer = midPointer.next
leftPointer.next = None
while rightPointer != None:
midPointer.next = leftPointer
leftPointer = midPointer
midPointer = rightPointer
rightPointer = rightPointer.next
midPointer.next = leftPointer # 边界,当只有2个节点时,不走上面的while
return midPointer
合并两个排序链表
需要 4个指针
class Solution:
# 返回合并后列表
def Merge(self, pHead1, pHead2):
# write code here
if pHead1 == None:
return pHead2
if pHead2 == None:
return pHead1
# 指针1
newHead = pHead1 if pHead1.val < pHead2.val else pHead2
# 指针2 & 3
tmp1 = pHead1
tmp2 = pHead2
if newHead == tmp1:
tmp1 = tmp1.next
else:
tmp2 = tmp2.next
# 指针4
pre = newHead
# 判断条件,当不管谁,最后一个为None的时候,退出循环
while tmp1 and tmp2:
if tmp1.val < tmp2.val:
pre.next = tmp1
pre = tmp1
tmp1 = tmp1.next
else:
pre.next = tmp2
pre = tmp2
tmp2 = tmp2.next
# 剩下最后一个节点情况,谁先到头了,把pre链接到另一个剩下的节点
if tmp1 == None:
pre.next = tmp2
else:
pre.next = tmp1
return newHead
两个链表的第一个公共节点
class Solution:
def FindFirstCommonNode(self, pHead1, pHead2):
# write code here
# 先找到2个链表的长度差
# 然后让长的链表先走长度差
# 然后两个指针同时走,当遇到相同的节点时候,那就是公共节点(注意边界条件,两个相同长度的链表)
tmp1 = pHead1
tmp2 = pHead2
while tmp1 and tmp2:
if tmp1 == tmp2:
return tmp1
tmp1 = tmp1.next
tmp2 = tmp2.next
if tmp1: # 意味着tmp2先到头,等于None
return self.find_common(tmp1,tmp2,pHead1, pHead2)
if tmp2:
return self.find_common(tmp2,tmp1,pHead2, pHead1)
def find_common(self, long_pointer, short_pointer, long_head, short_head):
# 需要4个指针,2个指向两个链表头,2个分别指向链表节点
# 计算K的差距
k = 0
while long_pointer:
long_pointer = long_pointer.next
k += 1
# 先走k步
long_pointer = long_head
short_pointer = short_head
for i in range(k):
long_pointer = long_pointer.next
# 一起走直到相等
while long_pointer != short_pointer:
long_pointer = long_pointer.next
short_pointer = short_pointer.next
return long_pointer
链表中环的入口节点
核心: -> 判断是否有环(快慢指针) -> 从相遇点走单步 --> over
# 利用快慢指针判断是否存在环,快指针走2步,慢指针走1步
# 上一个while退出条件存在2个,当为快指针走到None,或者 快慢指针相遇都会退出,这里是只相遇
# 所以从相遇点,快指回到pHead, 慢指针继续走那m,第一次遇到相同的节点就是环的起点
# 啰嗦的写法
class Solution:
def EntryNodeOfLoop(self, pHead):
# 运行超时了!!!该方法不行
# write code here
if pHead == None:
return None
# 利用快慢指针判断是否存在环,快指针走2步,慢指针走1步
fastPointer = pHead
slowPointer = pHead
while fastPointer and fastPointer.next:
fastPointer = fastPointer.next.next
slowPointer = slowPointer.next
if fastPointer == slowPointer:
break
# 上一个while退出条件存在2个,当为快指针走到None,或者 快慢指针相遇都会退出
if fastPointer == None or fastPointer.next == None:
return None
# 到这里就说明是快慢指针相遇了,需要按公式进行计算,搜索环入口节点
# 快慢指针相遇 所以慢指针走了l,快指针走了2l
# 慢指针环外面距离为s,环里走的长度为d,环内没走的长度为m --> l = s + d ,
# 快指针走的距离为 n*(m + d) + d + s = 2l
# 代入公式,所以 s = m + (n-1)(m+d) ,
# 所以从相遇点,快指回到pHead, 慢指针继续走那m,第一次遇到相同的节点就是环的起点
fastPointer = pHead
while fastPointer != slowPointer:
fastPointer = fastPointer.next
slowPointer = slowPointer.next
return slowPointer
# 简洁的写法:
class Solution:
def EntryNodeOfLoop(self, pHead):
if pHead == None or pHead.next == None:
return None
fast = pHead
slow = pHead
while fast.next and slow:
fast = fast.next.next
slow = slow.next
if fast == slow:
fast = pHead
while fast != slow:
fast = fast.next
slow = slow.next
return fast
return None
删除链表中的重复元素
class Solution:
def deleteDuplication(self, pHead):
# write code here
# 边界条件
if pHead == None:
return None
# 需要3个指针,root,pre, cur,
root = ListNode(0) # 为什么需要root指针,因为 1->1->2 最前面需要root指针
root.next = pHead
pre = root
cur = root
# 判断单个连续 1->2->2->3
while cur:
while cur.next and cur.val == cur.next.val:
cur = cur.next
# 判断多个连续情况 1->2->2->3->3->4
cur = cur.next
if cur and cur.next and cur.val == cur.next.val:
continue
pre.next = cur
pre = pre.next
return root.next
复杂链表的复制
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。
(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
# -*- coding:utf-8 -*-
# class RandomListNode:
# def __init__(self, x):
# self.label = x
# self.next = None
# self.random = None
class Solution:
# 返回 RandomListNode
def Clone(self, pHead):
# write code here
self.clone_node(pHead)
self.clone_random(pHead)
return self.split(pHead)
def clone_node(self, pHead):
node = pHead
while node:
copynode = RandomListNode(node.label)
copynode.next = node.next
node.next = copynode
node = copynode.next
def clone_random(self, pHead):
node = pHead
while node:
clone = node.next
if node.random:
clone.random =node.random.next
node = clone.next
def split(self, pHead):
node = pHead
copyhead = copynode = None
if node:
copyhead = copynode = node.next
node.next = copynode.next
node = node.next
while node:
copynode.next, copynode = node.next, copynode.next
node.next, node = copynode.next, node.next
return copyhead