第四周算法作业

Leetcode No.56 No.148 No.274作业报告

No.56 合并区间

  • 思路
本题我使用了两种方法
第一种是比较笨的即用字典记录被包含进去的区间,第二种是对区间进行直接合并
1. 第一种方法参见下面的代码块一
   字典除了记录被包含的整数之外还记录整数与整数之间是否连接为一个完整区间
   方法是两个整数之间的0.5分位如果也在字典中,即认为是连续区间,否则不连续
2. 第二种方法,先对区间进行排序,按照左下限的数字升序排列
   由于升序排列,因此对于下一个需要合并的区间而言只需要判断是否有重叠部分即可
   如有重叠部分则修改当前区间的上限,否则另开辟一个区间
  • 代码
class Solution(object):
    def merge(self, intervals):
        """
        :type intervals: List[List[int]]
        :rtype: List[List[int]]
        """
        # 使用字典来记录是否处于区间之内
        isIn ={}
        # 记录出现过的最大最小值
        minNum = 10000
        maxNum = 0
        for i in range(len(intervals)):
            left = intervals[i][0]
            right = intervals[i][1]
            if left < minNum:
                minNum = left
            if right > maxNum:
                maxNum = right
            
            # 对于左右象限相等的特殊情况,只将left那一个点标记
            if left == right:
                if isIn.get(left, False)!=True:
                    isIn[left] = True
            else:
                # 左右象限不相等的时候,将[left,right]之间的点
                # 以及标记点之间的中间位都做标记
                for j in range(left, right):
                    isIn[j] = True
                    isIn[j+0.5] = True
                isIn[right] = True

        
        mergeResults = []
        
        i = minNum
        while i <= maxNum:
            
            #寻找特殊节点,即左右值相同
            while isIn.get(i, False) == True and \
                isIn.get(i+0.5, False) != True and i <= maxNum:
                mergeResults.append([i,i])
                i = i + 1
            
            # 寻找左节点
            while isIn.get(i,False)!=True and i < maxNum:
                i = i + 1
            
            # 当前的i存在于字典中,
            # 但需要判断寻找到的是不是特殊节点
            if isIn.get(i+0.5, False) == True:
                left = i

                # 寻找右节点
                while isIn.get(i,False)==True and \
                    isIn.get(i+0.5, False) == True and i < maxNum:
                    i = i + 1
                right = i 
                mergeResults.append([left, right])
                i = i + 1

        return mergeResults
class Solution(object):
    def takeFirst(self, elem):
        return elem[0]
    
    def merge(self, intervals):
        """
        :type intervals: List[List[int]]
        :rtype: List[List[int]]
        """
        intervals.sort(key=self.takeFirst)
        merged = []
        for interval in intervals:
            # 如果列表为空,或者当前区间与上一区间不重合,直接添加
            if not merged or merged[-1][1] < interval[0]:
                merged.append(interval)
            else:
                # 否则的话,我们就可以与上一区间进行合并
                merged[-1][1] = max(merged[-1][1], interval[1])

        return merged
  • 作业截图
    在这里插入图片描述

No.148 排序链表

  • 思路
采用自底向上的非递归的归并排序
相关的步骤可以查看下面的代码注释
1. 每次将当前的链表切成n+1段,前n端长度为subLength
   最后一段长度为m,这n+1段内部进行归并排序
   将归并排好序的子链表接回主链表,先接头,后接尾
2. 最后一轮前面的subLength/2已经排好序
   后面的totalLength-subLength/2也排好序,需要进行合并

ps: 此题debug了很久,可能出现的疏忽是:
1.  排好序后忘记将新链表合并回主链表
2.  合并完之后,后面凑不齐subLength个节点的链表也要排序
  • 代码
class Solution(object):
    def merge(self, firstHead, secondHead):
        headTmp = ListNode()
        cur = headTmp
        
        while firstHead!=None and secondHead !=None:
            if firstHead.val < secondHead.val:
                cur.next = firstHead
                cur = firstHead
                firstHead = firstHead.next
            else: 
                cur.next = secondHead
                cur = secondHead
                secondHead = secondHead.next

        if firstHead != None:
            cur.next = firstHead
        if secondHead != None:
            cur.next = secondHead

        return headTmp.next
    
    def sortList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        # 使用自底向上的归并排序
        # 先算出链表总长度
        
        totalLength = 0
        tmpNode = head
        while tmpNode!=None:
            totalLength = totalLength + 1
            tmpNode = tmpNode.next
        
        if totalLength==0 or totalLength==1:
            return head
        
        # 这个是头指针的前一个临时指针,最后会删掉
        headTmp = ListNode(next=head)
        

        subLength = 2
        # 每次归并排序subLength长度的子链表
        while subLength<=totalLength:
            # previousEnd用于存储上一个已经排好序的尾节点
            previousEnd = headTmp
            
            n = totalLength // subLength
            m = totalLength % subLength
            # 将当前的链表切成n+1段,前n端长度为subLength
            # 最后一段长度为m,这n+1段内部进行归并排序

            # cur指针用于切割链表
            cur = headTmp.next

            # 打印当前的整个链表
            '''
            tmp = headTmp.next
            print('before subLength', subLength)
            while tmp != None:
                print(tmp.val)
                tmp = tmp.next
            print('end')
            '''
            ###############
            
            for index in range(n):
                # 这n段的长度都是subLength,需要将subLength分成两段
                # 然后调用merge

                firstHead = cur
                for i in range(subLength/2 -1):
                    cur = cur.next

                secondHead = cur.next
                cur.next = None
                cur = secondHead

                for i in range(subLength/2 -1):
                    cur = cur.next

                end = cur.next
                cur.next = None
                mergeHead = self.merge(firstHead,secondHead)
                # 将归并排好序的子链表接回主链表,先接头,后接尾
                previousEnd.next = mergeHead
                while previousEnd.next!=None:
                    '''
                    print('index previousEnd',\
                        index, previousEnd.val)
                    '''
                    previousEnd = previousEnd.next
                previousEnd.next = end
                cur = end

            # 最后的m个节点进行合并
            # 这m个节点中的前subLength/2个节点已经排好序
            if m>subLength/2: 
                firstHead = cur
                for i in range(subLength/2 -1):
                    cur = cur.next
                
                secondHead = cur.next
                cur.next = None
                mergeHead = self.merge(firstHead,secondHead)
                previousEnd.next = mergeHead

            # 打印当前的整个链表
            '''
            tmp = headTmp.next
            print('after subLength', subLength)
            while tmp != None:
                print(tmp.val)
                tmp = tmp.next
            print('end')
            '''
            ###############

            # 一轮合并完成
            subLength = subLength*2
        
        # 前面的subLength/2已经排好序
        # 后面的totalLength-subLength/2也排好序,需要进行合并
        cur = headTmp.next
        firstHead = cur
        for i in range(subLength/2 -1):
            cur = cur.next
        secondHead = cur.next
        cur.next = None
        mergeHead = self.merge(firstHead,secondHead)
        

        return mergeHead
  • 作业截图

在这里插入图片描述

No.274 H 指数

  • 思路
先降序排序,然后如果第i篇文章(即引用数第i多的文章)的引用数没有大于i,则为H指数
  • 代码
class Solution(object):
    def hIndex(self, citations):
        """
        :type citations: List[int]
        :rtype: int
        """
        # 先降序排序
        citations.sort(reverse=True)
        for i in range(len(citations)):
            if citations[i]<i+1:
                return i+1
        return len(citations)
  • 作业截图

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值