• 堆相关题目-python


    栈&队列&哈希表&堆-python  https://blog.csdn.net/qq_19446965/article/details/102982047

    1、丑数 II 

    编写一个程序,找出第 n 个丑数。

    丑数就是只包含质因数 2, 3, 5 的正整数。

    示例:

    输入: n = 10
    输出: 12
    解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。
    说明:  

    1 是丑数。
    n 不超过1690。

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/ugly-number-ii

    先回忆一下《丑数 I》

    编写一个程序判断给定的数是否为丑数。

    https://leetcode-cn.com/problems/ugly-number-ii/

    class Solution(object):
        def isUgly(self, num):
            """
            :type num: int
            :rtype: bool
            """
            if num <= 0:
                return False
            if num == 1:
                return True  
              
            while num >= 2 and num % 2 == 0:
                num /= 2
            while num >= 3 and num % 3 == 0:
                num /= 3 
            while num >= 5 and num % 5 == 0:
                num /= 5
              
            return num == 1
    

      

    丑数 II有点相反

    class Solution(object):
        def nthUglyNumber(self, n):
            """
            :type n: int
            :rtype: int
            """
            import heapq
            heap = [1]
            visited = set([1])
            
            num = None
            for i in range(n):
                num = heapq.heappop(heap)
                for factor in [2, 3, 5]:
                    if num * factor not in visited:
                        visited.add(num * factor)
                        heapq.heappush(heap, num * factor)
                
            return num
    

     

    2、Top k largest Number 

    例:n个数值选出最大k个数(3<k<n)的最小算法复杂度是( O(n) )

    1.最简单的方法:将n个数排序,排序后的前k个数就是最大的k个数,这种算法的复杂度是O(nlogn)

    2.O(n)的方法:

    解法1:利用快排的patition思想,从数组S中随机找出一个元素X,把数组分为两部分Sa和Sb。Sa中的元素大于等于X,Sb中元素小于X。这时有两种情况:

          1. Sa中元素的个数小于k,则Sb中的第k-|Sa|个元素即为第k大数;

          2. Sa中元素的个数大于等于k,则返回Sa中的第k大数。时间复杂度近似为O(n),但最坏情况下复杂度为O(n^2)。

    解法2:利用hash保存数组中元素Si出现的次数,利用计数排序的思想,线性从大到小扫描过程中,前面有k-1个数则为第k大数,平均情况下时间复杂度O(n)

    3.O(nlogk)的方法:先创建一个大小为k的最小堆,接下来我们每次从输入的n个整数中读入一个数,如果这个数比最小堆的堆顶元素还要大,那么替换这个最小堆的堆顶并调整。

    两种方法的优缺点:

    堆排序适用于海量数据,即它不需要所有的数据都加载进内存,只需要维护一个大小为m的小顶堆,这是其一个巨大的优势。

    快排方法速度快,但是面对海量数据是就显得无能为力了,因为他需要维护整个数组。

    4..O(n)查找第K小的数 BFPRT算法 - warm3snow - 博客园  https://www.cnblogs.com/informatics/p/5092741.html

    算法的思想是修改快速选择算法的主元选取方法,提高算法在最坏情况下的时间复杂度。其主要步骤为:

    1. 首先把数组按5个数为一组进行分组,最后不足5个的忽略。对每组数进行排序(如插入排序)求取其中位数。
    2. 把上一步的所有中位数移到数组的前面,对这些中位数递归调用BFPRT算法求得他们的中位数。
    3. 将上一步得到的中位数作为划分的主元进行整个数组的划分。
    4. 判断第k个数在划分结果的左边、右边还是恰好是划分结果本身,前两者递归处理,后者直接返回答案。

    其预算法不作实现,本次只关注堆

    class Solution:
        def get_top_k(k, nums):
            import heapq
            heap = []
            for num in nums:
                heapq.heappush(heap, num)
                if len(heap) > k:
                    heapq.heappop(heap)
    
            return sorted(heap, reverse=True)
    

    3、合并k个排序链表

    合并k个排序链表,并且返回合并后的排序链表。尝试分析和描述其复杂度。

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

    方法一:归并算法

    class Solution:
        """
        @param lists: a list of ListNode
        @return: The head of one sorted list.
        """
        def mergeKLists(self, lists):
            if not lists:
                return None
            
            return self.merge_range_lists(lists, 0, len(lists) - 1)
            
        def merge_range_lists(self, lists, start, end):
            if start == end:
                return lists[start]
            
            mid = (start + end) // 2
            left = self.merge_range_lists(lists, start, mid)
            right = self.merge_range_lists(lists, mid + 1, end)
            return self.merge_two_lists(left, right)
            
        def merge_two_lists(self, head1, head2):
            tail = dummy = ListNode(0)
            while head1 and head2:
                if head1.val < head2.val:
                    tail.next = head1
                    head1 = head1.next
                else:
                    tail.next = head2
                    head2 = head2.next
                tail = tail.next
                
            if head1:
                tail.next = head1
            if head2:
                tail.next = head2
            
            return dummy.next
    

      

    方法二:使用 heap

    1、将所有元素加入到堆
    2、遍历,一个一个取出最小值,连接起来
    import heapq
    ListNode.__lt__ = lambda x, y: (x.val < y.val)
    
    class Solution:
        """
        @param lists: a list of ListNode
        @return: The head of one sorted list.
        """
        def mergeKLists(self, lists):
            if not lists:
                return None
            
            dummy = ListNode(0)
            tail = dummy
            heap = []
            for head in lists:  # 1、将所有元素加入到堆
                if head:
                    heapq.heappush(heap, head)
                    
            while heap:         # 2、遍历,一个一个取出最小值,连接起来
                head = heapq.heappop(heap)
                tail.next = head
                tail = head
                if head.next:
                    heapq.heappush(heap, head.next)
                        
            return dummy.next
    

      

    ———————————————————

     参考:九章算法讲解 https://www.jiuzhang.com/solution/

  • 相关阅读:
    SQL常用语句(不定期更新)包含 日期格式,取列
    前端开发 ---浏览器自动刷新
    记录Redis使用中遇到的两个问题(原子性及数据完整性)
    Linux 输出重定向
    逆向手机内核,添加调试支持及绕过反调试
    阿里2014移动安全挑战赛第二题调试笔记
    在redhat6.4上编译z3求解器
    WCF学习笔记一(概述)
    DataReader反射泛型对象
    自定义配置节点(一)
  • 原文地址:https://www.cnblogs.com/rnanprince/p/11879690.html
Copyright © 2020-2023  润新知