leetcode刷题笔记-heap

heap is a specialized tree-based data structure which is essentially an almost complete tree. In a min heap, the parent nodes 

always smaller than childern nodes.

1405. Longest Happy String


 

class Solution:
    def longestDiverseString(self, a: int, b: int, c: int) -> str:
        hp = []
        if a != 0:
            heappush(hp, (-a, 'a'))
        if b != 0:
            heappush(hp, (-b, 'b'))
        if c != 0:
            heappush(hp, (-c, 'c'))
        re = ''
        while hp:
            count1, c1 = heapq.heappop(hp)
          
            if len(re) >= 2 and c1 == re[-1] and c1 == re[-2]:
                if hp:
                    count2, c2 = heapq.heappop(hp)
                    re += c2
                    count2 += 1
                    if count2 <= -1:
                        heapq.heappush(hp, (count2, c2))
                    heapq.heappush(hp, (count1, c1))
                else:
                    return re
            else:
                re += c1
                count1 += 1
                if count1 <= -1:
                    heapq.heappush(hp, (count1, c1))
        return re


1094. Car Pooling

class Solution:
    def carPooling(self, trips: List[List[int]], capacity: int) -> bool:
        trip = [[b, c, a] for a, b, c in trips]
        trip.sort()
        h = []
        while trip:
            start, end, num = trip.pop(0)
            # print("cur", start, end, num, "heap", h)
            if not h:
                heapq.heappush(h, [end, num])
                capacity -= num
            else:
                while h:
                    e, n = h[0]
                    # print("top heap", e, n, capacity)
                    if start >= e:
                        heapq.heappop(h) # needs to keep pop till not meet start>= e and then push cur into heap
                        # print("pop", e, n)
                        capacity += n
                    else:
                        break
                    
                heapq.heappush(h, [end, num])
                capacity -= num
            # print("capacity", capacity)
            if capacity < 0:
                return False
        return True
    def carPooling(self, trips: List[List[int]], capacity: int) -> bool:
        lst = []
        for n, start, end in trips:
            lst.append((start, n))
            lst.append((end, -n))
        lst.sort()
        pas = 0
        for loc in lst:
            pas += loc[1]
            if pas > capacity:
                return False
        return True

1882. Process Tasks Using Servers

class Solution:
    def assignTasks(self, servers: List[int], tasks: List[int]) -> List[int]:
        avaSrv = [(weight, i) for i, weight in enumerate(servers)] # heap 1: (weight, Server index) # O(n)
        heapq.heapify(avaSrv) 
        onTasks = []  # heap 2 ongoing tasks: (endTime, serverIndex)
        re = []
        curTime = 0
        for t, needTime in enumerate(tasks): # O(m)
            curTime = max(t, curTime)
            if not avaSrv:
                curTime = onTasks[0][0]
                
            while onTasks and onTasks[0][0] <= curTime:
                _, serIdx = heapq.heappop(onTasks)
                heapq.heappush(avaSrv, (servers[serIdx], serIdx))  # log(n)

            _, idx = heapq.heappop(avaSrv)
            heapq.heappush(onTasks, (curTime + needTime, idx))  # log(m)
            re.append(idx)
            
        return re
# heapify takes O(n) time. The loop iterates m times and both heaps have sizes no more than n. Thus, the overall run-time is O(n + mlogn).

​​​​​

1387. Sort Integers by The Power Value 

class Solution:
    def getKth(self, lo: int, hi: int, k: int) -> int:
        self.d = {}
        def power(x):
            if x == 1:
                return 1
            if x in self.d:
                return self.d[x]
            self.d[x] = (power(x / 2) if x % 2 == 0 else power(3 * x + 1)) + 1
            return self.d[x]
        
        re = [(power(x), x) for x in range(lo, hi+1)]
        heapq.heapify(re)

        for i in range(k):
            res = heapq.heappop(re)
        return res[1]

1642. Furthest Building You Can Reach

class Solution:
    def furthestBuilding(self, heights: List[int], bricks: int, ladders: int) -> int:
        heap = []
        
        for i in range(len(heights) - 1):
            d = heights[i+1] - heights[i]
            if d > 0:
                heapq.heappush(heap, d)
            if len(heap) > ladders:  # means we have to use bricks, we will choose the min diff d to use
                bricks -= heapq.heappop(heap)
            if bricks < 0:
                return i
        return len(heights) - 1

1942. The Number of the Smallest Unoccupied Chair

class Solution:
    def smallestChair(self, times: List[List[int]], targetFriend: int) -> int:
        '''
        when people left, return the chair to ava_seat[]
        when people arr, check if there is any returned chair, if so, take the smallest one
        if not, the seat index he will take will be the current total people - 1 in the people
        '''
        total_people = 0
        arr_heap, lev_heap, ava_seat = [], [], []
        d = {}  # map people index to seat index
        for i, (arr, lev) in enumerate(times):
            heapq.heappush(arr_heap, [arr, i])
            heapq.heappush(lev_heap, [lev, i])
        
        while arr_heap:
            arr, cur_i = heapq.heappop(arr_heap)  # arr_time or cur time, cur people index
            total_people += 1
            
            while lev_heap[0][0] <= arr:  # people left before cur time
                lev, i = heapq.heappop(lev_heap)
                heapq.heappush(ava_seat, d[i])  # return the seat to the ava_seat
                total_people -= 1
            else:
                # check if there is an return seat, if so, take it
                if ava_seat:
                    take_seat_i = heapq.heappop(ava_seat)
                    d[cur_i] = take_seat_i
                else:
                    # seat_i will be the total people - 1  
                    d[cur_i] = total_people - 1
                
                if cur_i == targetFriend:
                    return d[cur_i]

1488. Avoid Flood in The City

class Solution:
    def avoidFlood(self, rains: List[int]) -> List[int]:
        # heap
        lake_rain_days = collections.defaultdict(list)
        N = len(rains)
        re = [-1] * N
        heap = []  # stores the lakes need to be emptyed 
        full = set()
        
        for day, lake in enumerate(rains):
            lake_rain_days[lake].append(day)
        
        
        for i, lake in enumerate(rains):
            if lake:
                if lake in full:
                    return []
                
                full.add(lake)
                lake_rain_days[lake].pop(0)  # 当前的天
                
                if lake_rain_days[lake]:
                    heapq.heappush(heap, lake_rain_days[lake][0])  # 里面存的是day 不是lake
            else:
                
                if heap:
                    re[i] = rains[heapq.heappop(heap)]  # 里面存的是 day
                    full.remove(re[i])
                else:
                    re[i] = 1  ## 多个0 前面没有lake可以empty
                    
        return re
                

1834. Single-Threaded CPU

class Solution:
    def getOrder(self, tasks: List[List[int]]) -> List[int]:
        tasks = sorted([task[0], task[1], i] for i, task in enumerate(tasks))  # sort the task by start time
        res = []
        h = []
        cur_time = tasks[0][0]  # set the current time to the first start time in the task list.
        i = 0
        n = len(tasks)
        while len(res) < n:  # end when the res has the same # of tasks with tasks
            # Push all tasks whose start time is ≤ the current time into heap h
            while i < n and tasks[i][0] <= cur_time:
                heapq.heappush(h,  (tasks[i][1], tasks[i][2]))  # process time, index
                i += 1
            
            if h: # all the tasks in h has start_time <= cur_time 
                pro_time, index = heapq.heappop(h)
                cur_time += pro_time
                res.append(index)
                
            elif i < n:
                cur_time = tasks[i][0]
        
        return res

215. Kth Largest Element in an Array 

373. Find K Pairs with Smallest Sums

class Solution(object):
    def kSmallestPairs(self, nums1, nums2, k):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :type k: int
        :rtype: List[List[int]]
        """
        heap = []
        res = []
        if not nums1 or not nums2:
            return res
        # add init pairs (sum, nums1[i], nums2[0], ids of nums2)
        for i in xrange(min(k, len(nums1))):
            heapq.heappush(heap, [nums1[i]+nums2[0], nums1[i], nums2[0], 0])  # 0 is the index of nums2
        
        for i in xrange(min(k, len(nums1)*len(nums2))):
            cur = heapq.heappop(heap)
            res.append([cur[1], cur[2]])
            
            if cur[3] < len(nums2)-1:  # cur[3] is the idx of nums3: still at least one elem after num2 in array nums2
                idx = cur[3] + 1
                heapq.heappush(heap, [cur[1]+nums2[idx], cur[1], nums2[idx], idx])
                
        return res

378. Kth Smallest Element in a Sorted Matrix

 我第一个想法是Heap,最小堆解,但是不会写,因为heap用得太少了,库都不熟悉。

此题还有binary search的解法,速度更快,时间复杂度更低。

heap:  堆排序时间复杂度是nlogn,插入是logn

  • insert an element into heap: O(log(n)), where n is the width of the matrix
  • find k the k-th element O(k)
  • Overall: O(klog(n))
class Solution(object):
    def kthSmallest(self, matrix, k):
        """
        :type matrix: List[List[int]]
        :type k: int
        :rtype: int
        """
        h = [(row[0], row, 1) for row in matrix]
        heapq.heapify(h)
        for i in xrange(k-1):
            num, row, index = h[0]
            if index < len(matrix[0]):
                heapq.heapreplace(h, (row[index], row, index+1))
            else:
                heapq.heappop(h)
        return h[0][0]

binary search:

  1. Since we are given 1 <= k <= n^2, the kth number must exist in [lo, hi] range.
  2. We use binary search to find the minimum number A, such that the count of ( numbers satisfying num <= A ) is >= k.
  3. The time complexity is O(n * log(n) * log(N)), where N is the search space that ranges from the smallest element to the biggest element. You can argue that int implies N = 2^32, so log(N) is constant. In a way, this is an O(n * log(n)) solution.

好好好,good good good ,this is the first time that I know we can use binary search on such a nxm matrix.

class Solution(object):
    def kthSmallest(self, matrix, k):
        """
        :type matrix: List[List[int]]
        :type k: int
        :rtype: int
        """
        low, high = matrix[0][0], matrix[-1][-1]
        
        while low < high:
            mid = (low + high) / 2
            
            count, j = 0, len(matrix[0]) - 1
            for i in xrange(len(matrix)):
                while j >= 0 and matrix[i][j] > mid:
                    j -= 1
                count += j + 1
            
            if count < k: low = mid + 1
            else: high = mid
        
        return low
            

295. Find Median from Data Stream

class MedianFinder(object):

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.heaps = [], []

    def addNum(self, num):
        """
        :type num: int
        :rtype: void
        """
        small, large = self.heaps
        heapq.heappush(small, -heapq.heappushpop(large, num))
        if len(large) < len(small):
            heapq.heappush(large, -heapq.heappop(small))

    def findMedian(self):
        """
        :rtype: float
        """
        small, large = self.heaps
        if len(small) == len(large):
            return (large[0]-small[0]) / 2.0
        else:
            return large[0]

703. Kth Largest Element in a Stream

class KthLargest(object):

    def __init__(self, k, nums):
        """
        :type k: int
        :type nums: List[int]
        """
        heapq.heapify(nums)  # inplace
        self.heap = nums
        self.k = k
        while len(self.heap) > k:
            heapq.heappop(self.heap)
        

    def add(self, val):
        """
        :type val: int
        :rtype: int
        """
        if len(self.heap) < self.k:
            heapq.heappush(self.heap, val)
            return self.heap[0]
        
        if val > self.heap[0]:
            heapq.heappushpop(self.heap, val)
        return self.heap[0]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值