牛客——链表

1、反转链表

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class Solution:
    def ReverseList(self , head: ListNode) -> ListNode:
        # write code here
        if not head:return None
        prev=None# 前驱节点
        cur=head# 当前节点
        while cur:
            cur.next,prev,cur=prev,cur,cur.next
            # 下一个节点指向了前驱节点,前驱就指向当前的节点(因为要往后做了),当前就也往后挪一个
            # 其实说简单一点就是借助节点,其实我们的链表是没有改变的,只是获得链表内容的节点顺序改变了
        return prev

上下两个方法是一样的,但是下面那个更绕一点

class Solution:
    def ReverseList(self , head: ListNode) -> ListNode:
        # write code here
        # 借助栈 先进后出 一个一个插进去(因该是这样的)
        # 有点绕 大概就是弹出一个 然后压入 再弹出一个 再压入
        # 设置两个指针,一个当前节点的指针,一个上一个节点的指针(初始为空)
        pre = None# 先定义空 前驱节点
        while(head):# 这里就是第一个插进去
            temp = head.next# 除开第一个
            head.next = pre
            pre = head
            head = temp
        return pre

2、链表内指定区间反转

在这里插入图片描述
在这里插入图片描述

class Solution:
    def reverseBetween(self , head: ListNode, m: int, n: int) -> ListNode:
        # write code here
        if m==n:
            return head
        if not head and head.next:# head为空且head.next不为空
            return head
        dummy = ListNode(0)
        dummy.next = head# 新建一个链表 头上加了一个数字0
        pre = dummy # dummy的指针
        cur = head  # cur是head的指针
        for i in range(m-1):#前面几个直接加里边
            pre = cur
            cur = cur.next
        for i in range(n-m):# 这个就是直接反转链表就行了
            temp = cur.next# temp先存一下下一个节点
            cur.next = temp.next# cur的下一个就等于temp的下一个 就相当于是cur的下一个
            # 当前指向下一个
            temp.next = pre.next# temp下面就指向当前
            pre.next = temp   # 这里的pre就像之前那道题的前驱节点,因为他是多了一个节点的,所以他就是前一个
            # 前驱指向当前
        return dummy.next

3、链表中的节点每k个一组翻转

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里需要注意一下,如果不足k个是不需要翻转的,所以这里的方法是特别好的。

class Solution:
    def reverseKGroup(self , head: ListNode, k: int) -> ListNode:
        # write code here
#         # 因为这个是链表 所以不能用这个方法
#         n=len(head)
#         for i in range(n//k):
#             k1=i*k
#             k2=(i+1)*k
#             y=head[k1:k2]
#             y=y[::-1]
#             head=head[0:k1]+y+head[k2:]
#         return head
        cur = head# 指针
        cnt = 0 #一个参数
        while cur and cnt != k:# 这里就是在不断的后移
            cur = cur.next
            cnt += 1
        if cnt == k:
            cur = self.reverseKGroup(cur,k)# 指针到k+1个的时候 再调用这个函数
            while cnt:# 这里在翻转
                head.next,cur,head = cur,head,head.next
                cnt -= 1
            head = cur # 转换之后 把他赋值给head 我们的cur是不会再回到一的 他是在原始的head里做处理 只改变指针
        return head
    # 还没看懂

4、合并两个排序的链表

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class Solution:
    def Merge(self , pHead1: ListNode, pHead2: ListNode) -> ListNode:
        # write code here
        dummy=cur=ListNode(-1) #dummy是尾 cur是一个指针 这一步是必要的
        while pHead1 and pHead2:# 任意一个不空
            if pHead1.val<=pHead2.val:
                cur.next=pHead1
                pHead1=pHead1.next
            else:
                cur.next=pHead2
                pHead2=pHead2.next
            cur=cur.next# 从这往下是欠缺的地方
        cur.next=pHead1 if pHead1 else pHead2 # 这里是最后比完了在看没有装进来的东西
        return dummy.next

5、合并k个已排序的链表

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
分治法 简而言之就是

1.只有一个链表时返回该链表
2.只有两个链表时返回合并后的链表
3.有两个以上链表时,拆分成两部分分别合并
下面就是这个方法做的,分成两部分,分别求合并

class Solution:
    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:# 合并俩
        head = ListNode(None)
        p = head
        while l1 and l2:
            if l1.val <= l2.val:
                p.next = l1
                l1 = l1.next
            else:
                p.next = l2
                l2 = l2.next
            p = p.next
        if not l1:
            p.next = l2
        else:
            p.next = l1
        return head.next
    def mergeKLists(self, lists: List[ListNode]) -> ListNode:# 合并k
        n = len(lists)
        if n == 0:
            return None
        return self.mergeLR(lists,0,n-1)
    def mergeLR(self,lists,L,R):# 合并k下面的左右平分合并
        if R == L:#就是len(list)==1
            return lists[L]
        if R-L != 1:# 当不是2的时候 就开始平分 若是为2 就直接用合并2
            mid = (L+R)//2
            lists[L] = self.mergeLR(lists,L,mid)
            lists[R] = self.mergeLR(lists,mid+1,R)
        return self.mergeTwoLists(lists[L],lists[R])

一个笨方法
简单点来说就是 把所有的链表放一起 然后排序之后再放在一个链表里

class Solution:
    def mergeKLists(self , lists: List[ListNode]) -> ListNode:
        # write code here
        # 这个是把他转换为了一个大的list来做的,下面有个tmp.sort
        tmp = []
        for node in lists:
            while node:
                tmp.append(node.val)
                node = node.next
        if not tmp:
            return None
        tmp.sort()
        cur = head = ListNode(tmp[0])
        for i in range(1,len(tmp)):
            node = ListNode(tmp[i])
            cur.next = node
            cur = cur.next
        return head

6、判断链表中是否有环

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class Solution:
    def hasCycle(self , head: ListNode) -> bool:
        fast = head
        slow = head
        while slow!=None and fast.next!=None and fast.next.next!=None:
            fast = fast.next.next;
            slow = slow.next;
            if fast==slow:
                return True
        return False

7、链表中环的入口结点

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class Solution:
    def EntryNodeOfLoop(self, pHead):
        if not pHead:
            return None
        slow = fast = pHead
        while slow and fast:# 俩都不为空的时候
            if not slow.next or not fast.next:# 二者中任意一个的next不为none
                return None
            slow = slow.next
            fast = fast.next.next # 第二个链表
            if slow == fast:
                while slow != pHead:
                    pHead = pHead.next
                    slow = slow.next
                return slow
        return None

下面是另一个方法,借助了一个新的表来做的

class Solution:
    def EntryNodeOfLoop(self, pHead):
        # write code here
        addr = []
        while pHead.next != None:    # 遍历
            addr.append(pHead)        # 记录地址到列表
            pHead = pHead.next        # 遍历下一个
            if pHead.next in addr:    # 存在下一个链表地址在列表中,则下一个链表就是入口
                return pHead.next
        
        return None                   # 无法循环,返回空

8、链表中倒数最后k个结点

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
和刚刚的环有点类似,借助快指针和慢指针,快指针比满指针先走k步,当快指向none了,慢就可以开始输出了

class Solution:
    def FindKthToTail(self , pHead: ListNode, k: int) -> ListNode:
        # write code here
        # 两个指针隔开k出发 当先出发的到尾巴的时候 后出发的那个就开始返回值就行
        fast=slow=pHead
        n=0
        while pHead:
            n+=1
            pHead=pHead.next
        print(n)

        if n<k:
            return None

        else:
            for i in range(k):
                fast=fast.next
            while fast:
                fast=fast.next
                slow=slow.next
            return slow

9、删除链表的倒数第n个节点

在这里插入图片描述
在这里插入图片描述
这个方法和上面的一样,他是直接就先把前n个一一存起来,然后删掉第n个,之后再直接加上就行了

class Solution:
    def removeNthFromEnd(self , head: ListNode, n: int) -> ListNode:
        # write code here
        slow=head
        fast=head
        for _ in range(n):
            fast=fast.next
        if not fast:
            return head.next# 这里就是当fast到最后了 就除掉当前
        while fast.next:
            fast = fast.next
            slow = slow.next
        slow.next = slow.next.next
        return head

10、两个链表的第一个公共结点

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

class Solution:
    def FindFirstCommonNode(self , pHead1 , pHead2 ):
        # write code here
        # 分别记为x、y、z,1、2、共同,那么让A走xzy b走yzx 那么最后都是指到了z的第一个
        pa,pb= pHead1 , pHead2
        while pa!=pb:
            pa=pa.next if pa else pHead2
            pb=pb.next if pb else pHead1
        return pa

11、链表相加(一)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这个循环时间会比较长

class Solution:
    def ListAdd(self , l1: ListNode, l2: ListNode) -> ListNode:
        # write code here
        up = 0 #设置进位
        head = ListNode(0) #设置表头
        node = head #设置中间节点
        while l1 or l2:
            x = l1.val if l1 else 0  #if else语句是为了防止两个输入链表不一样长导致为None
            y = l2.val if l2 else 0
            s = x + y + up #求和时要加上进位值
            up = s // 10 #和大于10则进位
            node.next = ListNode(s % 10) #输出链表增加一个节点
            if l1:
                l1 = l1.next
            if l2:
                l2 = l2.next
            node = node.next #更新链表的next
        if up != 0:   #检查最后一位是否进位
            node.next = ListNode(1) #进位则加上一个1的节点
        return head.next #返回时记得去除表头的0节点,即head本身

这个的时间也会超

class Solution:
    def ListAdd(self , l1: ListNode, l2: ListNode) -> ListNode:
        # write code here
        # 初始化个位节点,先不做进位
        newPoint = ListNode(l1.val + l2.val)

        # rt用来作为最后return的节点,tp用来遍历节点
        rt, tp = newPoint, newPoint

        # l1,l2只要后面还有节点,就继续往后遍历;或者新链表还需要继续往后进位
        while (l1 and (l1.next != None)) or (l2 and (l2.next != None)) or (tp.val > 9):
            l1, l2 = l1.next if l1 else l1, l2.next if l2 else l2
            tmpsum = (l1.val if l1 else 0) + (l2.val if l2 else 0)
            # 计算新链表下个节点的值(当前节点的进位+当前l1 l2的值之和),先不做进位
            tp.next = ListNode(tp.val//10 + tmpsum)
            # 新链表当前节点的值取个位
            tp.val %= 10
            # 新链表往后遍历一个节点
            tp = tp.next
        return rt

递归

class Solution:
    def ListAdd(self , l1: ListNode, l2: ListNode) -> ListNode:
        # write code here
        # 某一个加数不存在,那么结果即为另一个加数
        if l1 is None:
            return l2
        if l2 is None:
            return l1
        # 加数都存在,取对位相加,除以10取余
        x = l1.val if l1 else 0
        y = l2.val if l2 else 0
        re = ListNode((x + y) % 10)

        # 下一个节点,即为l1和l2下一个节点相加,再加上此节点的进位
        re.next = self.ListAdd(l1.next, l2.next)
        if x + y > 9:
            re.next = self.ListAdd(re.next, ListNode((x + y) // 10))
        return re

循环

class Solution:
   def ListAdd(self , l1: ListNode, l2: ListNode) -> ListNode:
       # write code here
       #########循环
       result = ListNode(0)
       re = result
       carry = 0
       # l1,l2,进位 有一个存在则需要继续链表
       while l1 or l2 or carry > 0:
           x = l1.val if l1 else 0
           y = l2.val if l2 else 0
           re.next = ListNode((x + y + carry) % 10)
           re = re.next
           # 进位
           carry = (x + y + carry) // 10
           if l1 is not None:
               l1 = l1.next
           if l2 is not None:
               l2 = l2.next
       return result.next

这个是根据下面的那道题改的

class Solution:
    def ListAdd(self , l1: ListNode, l2: ListNode) -> ListNode:
        # write code here
        head,c=l1,0
        while l1 and l2:
            _=l1.val+l2.val+c
            l1.val=_%10
            c=_//10
            tail=l1
            l1,l2=l1.next,l2.next
        if l2:
            tail.next=l2
            while c>0 and l2:
                _=l2.val+c
                l2.val=_%10
                c=_//10
                tail=l2
                l2=l2.next
        elif l1:
            while c>0 and l1:
                _=l1.val+c
                l1.val=_%10
                c=_//10
                tail=l1
                l1=l1.next
        if c>0:
            c=ListNode(c)
            tail.next=c
        return head

12、链表相加(二)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
一点都没看,但是这个就是上一道题的改编版,他需要先翻转一下,再相加,相加的结果再翻转就可以了

class Solution:
    def reverse(self,head):
        if not head or not head.next:return head
        prev=head
        curr=head.next
        prev.next=None
        while curr:
            nxt=curr.next
            curr.next,prev,curr=prev,curr,nxt
        return prev
    def addInList(self , head1: ListNode, head2: ListNode) -> ListNode:
        # write code here
        h1=self.reverse(head1)
        h2=self.reverse(head2)
        head,c=h1,0
        while h1 and h2:
            _=h1.val+h2.val+c
            h1.val=_%10
            c=_//10
            tail=h1
            h1,h2=h1.next,h2.next
        if h2:
            tail.next=h2
            while c>0 and h2:
                _=h2.val+c
                h2.val=_%10
                c=_//10
                tail=h2
                h2=h2.next
        elif h1:
            while c>0 and h1:
                _=h1.val+c
                h1.val=_%10
                c=_//10
                tail=h1
                h1=h1.next
        if c>0:
            c=ListNode(c)
            tail.next=c
        return self.reverse(head)

13、单链表的排序

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class Solution:
    def sortInList(self , head: ListNode) -> ListNode:
        # write code here
        # 这个也是借助sort来排序的
        if not head:# 空的时候直接就是排好的了
            return
        cur=head
        res=[]
        while cur:
            res.append(cur.val)
            cur=cur.next
        res.sort()
        dummy=ListNode(0)
        pre=head
        i=0
        while pre:
            pre.val=res[i]
            pre=pre.next
            i+=1
        return head

14、判断一个链表是否为回文结构

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
学不明白链表,就借助列表

class Solution:
    def isPail(self , head: ListNode) -> bool:
        # write code here
        res = []
        cur = head 
        while cur:
            res.append(cur.val)
            cur = cur.next
        return res == res[::-1]

15、链表的奇偶重排

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class Solution:
    def oddEvenList(self , head: ListNode) -> ListNode:
        # write code here
        if not head:return None
        evenHead = head.next # 偶数的第一个
        odd = head # 奇数
        even = head.next # 偶数
        while even and even.next:
            odd.next = even.next # 奇数指向奇数
            odd = odd.next
            even.next = odd.next # 偶数指向偶数
            even = even.next
        odd.next = evenHead # 奇数最后一个指向偶数第一个
        return head

16、删除有序链表中重复的元素-I(顺序排列)

在这里插入图片描述
在这里插入图片描述

class Solution:
    def deleteDuplicates(self , head: ListNode) -> ListNode:
        # write code here
        # 按顺序排列的 所以可以直接比较就行
        if not head: return None
        slow,fast = head,head.next
        while fast:
            if fast.val != slow.val:# 不等就可以保留
                slow.next = fast
                slow = slow.next
            fast = fast.next
        slow.next = None
        return head

17、删除有序链表中重复的元素-II(删除重复的所有东西)

在这里插入图片描述
在这里插入图片描述

class Solution:
    def deleteDuplicates(self , head: ListNode) -> ListNode:
        # write code here
        res = ListNode(0)
        res.next = head
        fa = res
        cur = head
        while cur and cur.next:
            if cur.val != cur.next.val:
                fa = cur
                cur = cur.next
            else:
                while cur.val==cur.next.val:
                    cur = cur.next
                    if not cur.next:
                        break
                fa.next = cur.next
                cur = cur.next
        return res.next

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值