leetcode题解python版:21-25

21、合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
解:链表的基本应用

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
        ans=ListNode(None)
        result=ans
        if not l1:
            return l2
        if not l2:
            return l1
        while l1 and l2:
            if l1.val<l2.val:
                ans.next=l1
                ans=ans.next
                l1=l1.next
            else:
                ans.next=l2
                ans=ans.next
                l2=l2.next
        while l1:
            ans.next=l1
            ans=ans.next
            l1=l1.next
        while l2:
            ans.next=l2
            ans=ans.next
            l2=l2.next
        return result.next

运行时间为48 ms,击败了62.83%的用户,内存消耗为13.7 MB。

22、括号生成
数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
解法一:本题的想法是把每一次的增减左右括号单列出来分析,这时为了括号合法,必须保证左括号的数量不少于右括号的数量。

class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        ans=[["",0,0]]
        result=[]
        n2=len(ans)
        while ans:
            ans=self.addLeftandRight(ans,result,n)
        result.sort()
        return result
    def addLeftandRight(self,alist,result,n):#一次增加左括号以及右括号的操作
        n1=len(alist)
        blist=[]
        for i in range(n1):
            left=alist[i][1]
            right=alist[i][2]
            s=alist[i][0]
            curList=[]
            for j in range(1,n-left):
                for k in range(1,left+j+1-right):
                    curList.append([s+"("*j+")"*k,left+j,k+right])
            result.append(s+"("*(n-left)+")"*(n-right))
            blist=blist+curList
        return blist

执行用时:40 ms击败了83.43%的用户;内存消耗:13.8 MB。

23、合并K个排序链表
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
解法一:用归并排序给lists排序,每一次拿出最小的加到ans里,然后最小的next插入剩下的已经排好的,继续操作。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def mergeKLists(self, lists: List[ListNode]) -> ListNode:
        ans=ListNode(None)
        result=ans
        if not lists:
            return None
        lists=list(filter(lambda x: x!=None, lists))
        if not lists:
            return None        
        lists=self.mergeSort(lists)
        while len(lists)>1:
            ans.next=lists[0]
            lists[0]=lists[0].next
            if lists[0]==None:
                del lists[0]
            else:
                lists=self.insertSort(lists)
            ans=ans.next
        while lists[0]:
            ans.next=lists[0]
            lists[0]=lists[0].next
            ans=ans.next
        return result.next

    def mergeSort(self,alist):
        if len(alist)>1:
            mid=len(alist)//2
            lefthalf=alist[:mid]
            righthalf=alist[mid:]
            self.mergeSort(lefthalf)
            self.mergeSort(righthalf)
            i=j=k=0
            #拉链式交错把左右半部分从小到大加入到结果列表中
            while i<len(lefthalf) and j<len(righthalf):
                if lefthalf[i].val<righthalf[j].val:
                    alist[k]=lefthalf[i]
                    i=i+1
                else:
                    alist[k]=righthalf[j]
                    j=j+1
                k=k+1
            #归并左半部分剩余项或右半部分剩余项
            while i<len(lefthalf):
                alist[k]=lefthalf[i]
                i=i+1
                k=k+1
            while j<len(righthalf):
                alist[k]=righthalf[j]
                j=j+1
                k=k+1
        return alist
        
    def insertSort(self,alist):#最小的ListNode取next后插入原本排序好的部分
        index=0
        for i in range(1,len(alist)):
            if alist[index].val>alist[i].val:
                temp=alist[index]
                alist[index]=alist[i]
                alist[i]=temp
                index=i
            else:
                break
        return alist

用时:144 ms,击败了28.11%的用户,内存消耗:16.5 MB

24、两两交换链表中的节点
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
解:本题的关键在于交换a,b两数是a.next,b.next以及last.next的交换,也就是说这里的交换是改变连接点的交换,不能通过直接赋值完成。理解了这点本题就只需要通过3个指针就能高效实现。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def swapPairs(self, head: ListNode) -> ListNode:
        count=1
        ans=ListNode(None)
        last=ans
        if not head or not head.next:
            return head
        last.next=head
        first=head
        second=head.next
        while last.next and last.next.next:
            first=last.next
            second=last.next.next
            first.next=second.next
            second.next=first
            last.next=second
            last=last.next.next
        return ans.next

执行用时:20 ms击败了100.00%的用户;内存消耗:13.6 MB。

25、 K 个一组翻转链表
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
解法:与上一道题的大体思路类似,可以先遍历一遍列表取长度,然后再K个一组添加到列表里,从右到左改变next值。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
        count=0
        ans=ListNode(None)
        ans.next=head
        last=ans
        travel=ans
        while travel.next:
            travel=travel.next
            count=count+1
        if count<k:
            return ans.next
        for j in range(count//k):
            alist=[]
            result=last
            for i in range(k):
                alist.append(result.next)
                result=result.next
            last.next=alist[k-1]
            alist[0].next=alist[k-1].next
            for i in range(k-1,0,-1):
                alist[i].next=alist[i-1]
            for i in range(k):
                last=last.next
        return ans.next        

运行时间52 ms, 击败了86.59%的用户;
内存消耗:14.5 MB,击败了38.33%的用户

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值