zoukankan      html  css  js  c++  java
  • 堆相关题目-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/

  • 相关阅读:
    Unity3d中的属性(Attributes)整理【转载】
    在Unity里面使MMD动起来吧【2】
    在Unity里面使MMD动起来吧【1】
    Unity代码混淆方案
    萌舞Android版Unity笔记整理
    c#实现16进制和字符串之间转换的代码
    关于sqlite3使用top的一些规则总结
    【转】UniSky入门资料
    【转】.NET 产品版权保护方案 (.NET源码加密保护)
    百度云管家下载出错解决思路记录
  • 原文地址:https://www.cnblogs.com/rnanprince/p/11879690.html
Copyright © 2011-2022 走看看