牛客网——链表

链表

1. JZ6 从尾到头打印链表

# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param listNode ListNode类 
# @return int整型一维数组
#
class Solution:
    def printListFromTailToHead(self , listNode: ListNode) -> List[int]:
        # write code here
        new_list = []
        while listNode:
            new_list.append(listNode.val)
            listNode = listNode.next
        return new_list[::-1]

2. JZ24 反转链表

# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param head ListNode类 
# @return ListNode类
#
class Solution:
    def ReverseList(self , head: ListNode) -> ListNode:
        # write code here
        if head == None or head.next == None:
            return head
        pre = None
        now = head
        while now != None:
            next = now.next
            now.next = pre
            pre = now
            now = next 
        return pre

3. JZ25 合并两个排序的链表
解法1:

# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param pHead1 ListNode类 
# @param pHead2 ListNode类 
# @return ListNode类
#
class Solution:
    def Merge(self , pHead1: ListNode, pHead2: ListNode) -> ListNode:
        # write code here
        if not pHead1:
            return pHead2
        if not pHead2:
            return pHead1
        
        new_list = ListNode(0)
        dummy = new_list # 保证了二者是存储在相同内存上的ListNode,一个的next改变,另外一个也会跟着改变
        while pHead1 and pHead2:
            if pHead1.val <= pHead2.val:
                new_list.next = pHead1
                pHead1 = pHead1.next
            else:
                new_list.next = pHead2
                pHead2 = pHead2.next
            new_list = new_list.next
        if pHead1:
            new_list.next = pHead1
        elif pHead2:
            new_list.next = pHead2
        return dummy.next           
            

解法2:

# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param pHead1 ListNode类 
# @param pHead2 ListNode类 
# @return ListNode类
#
class Solution:
    def Merge(self , pHead1: ListNode, pHead2: ListNode) -> ListNode:
        if not pHead1:
            return pHead2
        elif not pHead2:
            return pHead1
        if pHead1.val <= pHead2.val:
            pHead1.next = self.Merge(pHead1.next, pHead2)
            return pHead1
        else:
            pHead2.next = self.Merge(pHead1, pHead2.next)
            return pHead2

        
        
        
        
        
        # write code here
#         if not pHead1:
#             return pHead2
#         if not pHead2:
#             return pHead1
        
#         new_list = ListNode(0)
#         dummy = new_list # 保证了二者是存储在相同内存上的ListNode,一个的next改变,另外一个也会跟着改变
#         while pHead1 and pHead2:
#             if pHead1.val <= pHead2.val:
#                 new_list.next = pHead1
#                 pHead1 = pHead1.next
#             else:
#                 new_list.next = pHead2
#                 pHead2 = pHead2.next
#             new_list = new_list.next
#         if pHead1:
#             new_list.next = pHead1
#         elif pHead2:
#             new_list.next = pHead2
#         return dummy.next
            
            

4. JZ52 两个链表的第一个公共结点解答

# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

#
# 
# @param pHead1 ListNode类 
# @param pHead2 ListNode类 
# @return ListNode类
#
class Solution:
    def FindFirstCommonNode(self , pHead1 , pHead2 ):
        # write code here
        p1 = pHead1
        p2 = pHead2
# 因为p1的next在最后一个节点为None,这时候while循环无法继续了,所以不对 
#         while p1 and p2:
#             p1 = p1.next if p1 else pHead2
#             p2 = p2.next if p2 else pHead1
#             if p1 == p2:
#                 return p1
        while p1 != p2:
            p1 = p1.next if p1 else pHead2
            p2 = p2.next if p2 else pHead1
        return p1

5. JZ23 链表中环的入口结点
分析:以下a为AB长度,b为BC长度,c为CB长度。 假设相遇时慢指针已经转了m圈,快指针已经转了n圈。可知m>=0,n>=1 因为b+c为一圈,当慢指针走了a+m(b+c)+b步长时,快指针走的步长为2a+2m(b+c)+2b 而用n表示快指针步长则为 a+b+n(b+c)。即有等式 2a+2m(b+c)+2b = a+b+n(b+c) 化简得:a = (n-2m-1)(b+c) + c。 因为b+c > c,若n-2m-1小于0,则(n-2m-1)(b+c) + c < 0,即a<0 与题意不符。 所以最终得: a = (n-2m-1)(b+c) + c ,且n-2m-1>=0 若第一圈相遇即为m=0,n=1 可得a=c; 然后让fast指向头结点,slow原地不动,让后fast,slow每次走一步,当再次相遇,就是入口结点。。
在这里插入图片描述

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    def EntryNodeOfLoop(self, pHead):
        # write code here
        fast = pHead
        slow = pHead
               
        while fast and fast.next: 
            slow = slow.next
            fast = fast.next.next
            if slow == fast:
                break
                
        if not (fast and fast.next):
            return None
        
        fast = pHead
        while slow != fast:
            slow = slow.next
            fast = fast.next
        
        return fast
           

6. JZ22 链表中倒数最后k个结点

class Solution:
    def FindKthToTail(self , pHead: ListNode, k: int) -> ListNode:
        # write code here
        fast = pHead
        slow = pHead
        
        for i in range(k):
            if fast:
                fast = fast.next
            else: 
                return None
            
        while slow and fast:
            slow = slow.next
            fast = fast.next
        return slow
            

7. JZ35 复杂链表的复制
c++深拷贝、浅拷贝:链接
python直接赋值、深拷贝、浅拷贝:链接
解法1: 构造哈希表

# -*- 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):
        if not pHead:
            return pHead

        dic = {}
        cur = pHead
        
        while cur:
            dic[cur] = RandomListNode(cur.label)
            cur = cur.next
        
        cur = pHead
        while cur:
            dic[cur].next = dic.get(cur.next)
            dic[cur].random = dic.get(cur.random)
            cur = cur.next
        
        return dic[pHead]

解法2:链表拼接、拆分
在这里插入图片描述

# -*- 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):
        if not pHead:
            return
        
        cur = pHead
        while cur:
            curnext = cur.next
            tmp = RandomListNode(cur.label)
            tmp.next = curnext
            cur.next = tmp
            cur = curnext
        
        cur = pHead
        while cur:
            if cur.random:
                cur.next.random = cur.random.next
            cur = cur.next.next
            
#        这段错误的原因可能是因为没有给clone元素的最后一个next赋值(None)        
#         old = pHead 
#         clone = pHead.next
#         clone1 = pHead.next
#         while clone.next: # while 3
#             old.next = clone.next # 1.next = 3
#             clone.next = clone.next.next # 2.next = 4
#             old = old.next # 1 = 3
#             clone = clone.next # 2=4
            
#         return clone1

        
        old = pHead
        clone = pHead.next
        while old:
            old_next = old.next
            next_3 = old_next.next
            old.next = next_3

            if next_3:
                old_next.next = next_3.next
# old.next = next_3 # 放在这儿报错:wrong,cannot used original node of list
            else:
                old_next.next = None
            
            old = next_3
        return clone

8. JZ76 删除链表中重复的结点
解法1:

  • 首先要设置两个指针,一个指针pre保持住目前的节点,另一个指针cur顺着这个节点向后搜索,直到遇到有重复的数字。
  • 比如1<2<2<2<3<3<4<5,当cur指向第一个2时,此时pre指向1,进入第三个while循环,通过搜索有三个相同的2,则pre.next = cur = 3
  • 此时退回第二个while循环,由于cur.next还是等于cur(3 == 3),此时又进入循环,最后pre.next = cur = 4(在cur不断移动的过程中pre一直没动,指向1)
  • 再次退回到第二个循环,由于此时cur = 4 不满足循环条件,则退出第二个循环
  • 回到初始的第一个循环中,此时pre指向4,继续进行之前的判断。
    考虑到有可能头结点就是重复数字,所以给它设置一个新结点。
class Solution:
    def deleteDuplication(self , pHead: ListNode) -> ListNode:
        new = ListNode(0)
        new.next = pHead
        pre, cur = None, new
        while cur:
            pre = cur
            cur = cur.next
            while cur and cur.next and cur.val == cur.next.val:
                t = cur.val
                while cur and cur.val == t:
                    cur = cur.next
                pre.next = cur
        return new.next
                    

解法2:递归

class Solution:
    def deleteDuplication(self , pHead: ListNode) -> ListNode:
        if not pHead or not pHead.next:
            return pHead
        if pHead.val == pHead.next.val:
            tmp = pHead.next
            while tmp and tmp.val == pHead.val:
                tmp = tmp.next
            return self.deleteDuplication(tmp)
        else:
            pHead.next = self.deleteDuplication(pHead.next)
            return pHead

9. JZ18 删除链表的节点
解法1:(自己做的)

class Solution:
    def deleteNode(self , head: ListNode, val: int) -> ListNode:
        # write code here
        if not head:
            return
        new = ListNode(-1)
        new.next = head
        
        tmp = new
        
        while tmp:
            if tmp.next and tmp.next.val == val:
                tmp.next = tmp.next.next
                break
            tmp = tmp.next
        return new.next

解法2:

  • 双指针:看题解说能用双指针就没看答案自己写了下,结果对了
class Solution:
    def deleteNode(self , head: ListNode, val: int) -> ListNode:
        # write code here
        if not head:
            return 
        if head.val == val:
            return head.next
        
        past, cur = head, head.next
        # 至少有一个节点且头节点的值不为val
        while cur: 
            if cur.val == val:
                past.next = cur.next
                break
            past = cur
            cur = cur.next
                
        return head
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值