链表中倒数第k个节点 & 反转链表 & 合并两个排序链表 & 两个链表的第一个公共节点 & 链表中环的入口节点 & 删除链表中的重复元素 & 复杂链表的复制

逐渐成为灵魂画手[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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值