Пример #1
0
    def leastInterval(self, tasks, n):
        """
        Solution: Calculating Idle Slot
        Time Complexity: O(n)
        Space Complexity: O(n)
        Inspired By: MySELF!! (684ms, beat 20.24%)
        :type tasks: List[str]
        :type n: int
        :rtype: int
        """
        freq2task_map = collections.Counter(tasks)
        max_freq = max(freq2task_map.values())
        base_sec = []
        for k, v in freq2task_map.iteritems():
            if v == max_freq:
                base_sec.append(k)
        for key in base_sec:
            freq2task_map.pop(key)

        res = len(base_sec)

        _heap = []
        for i in range(max_freq-1):
            pq.heappush(_heap, (len(base_sec), base_sec[:]))
        freq2task_map = [(k, v) for k, v in freq2task_map.iteritems()]
        while freq2task_map:
            k, v = freq2task_map.pop()
            for i in range(v):
                sec_len, sec = pq.heappop(_heap)
                sec.append(k)
                pq.heappush(_heap, (1 + sec_len, sec))
        while _heap:
            sec_len, sec = _heap.pop()
            res += max(n+1, sec_len)
        return res
Пример #2
0
 def mincostToHireWorkers(self, quality, wage, K):
     """
     Solution: Heap
     Time Complexity: O(nlog(n))
     Space Complexity: O(n)
     Perf: Runtime: 424 ms, faster than 31.63%  / Memory Usage: 14.1 MB, less than 12.00%
     Inspired By:
     - https://leetcode.com/problems/minimum-cost-to-hire-k-workers/discuss/237268/Python-heap-solution-with-clean-code-and-explanation
     - https://leetcode.com/problems/minimum-cost-to-hire-k-workers/solution/
     TP:
     - Using wage[i]/quality[i] as sorting points
     :type quality: List[int]
     :type wage: List[int]
     :type K: int
     :rtype: float
     """
     m = len(quality)
     wkr_ratio = []
     for i in range(m):
         wkr_ratio.append((float(wage[i]) / quality[i], quality[i]))
     wkr_ratio.sort()
     h = []
     min_cost = float('inf')
     total_qua = 0
     for ratio, qua in wkr_ratio:
         total_qua += qua
         pq.heappush(h, -qua)
         if len(h) == K:
             min_cost = min(min_cost, total_qua * ratio)
         elif len(h) > K:
             total_qua += pq.heappop(h)
             min_cost = min(min_cost, total_qua * ratio)
     return min_cost
Пример #3
0
 def findCheapestPrice(self, n, flights, src, dst, K):
     """
     Solution: BFS + Dijsktra
     Time Complexity:
     Space Complexity: O(n) (n: heap length)
     Inspired By:
     - https://leetcode.com/problems/cheapest-flights-within-k-stops/solution/
     - https://leetcode.com/problems/cheapest-flights-within-k-stops/discuss/115541/JavaPython-Priority-Queue-Solution
     TP:
     - Using Dijkstra Algorithm but at same time keep the stops under K
     :type n: int
     :type flights: List[List[int]]
     :type src: int
     :type dst: int
     :type K: int
     :rtype: int
     """
     graph = collections.defaultdict(dict)
     for u, v, w in flights:
         graph[u][v] = w
     best = dict()
     pq = [(0, 0, src)]
     while pq:
         curr_cost, curr_stop, curr_city = pq.heappop(pq)
         if curr_stop > K+1 or curr_cost > best.get((curr_stop, curr_city), float('inf')):
             continue
         if curr_city == dst:
             return curr_cost
         for next_stop, cost in graph[curr_city].iteritems():
             new_cost = cost + curr_cost
             if new_cost < best.get((curr_stop+1, dst), float('inf')):
                 best[(curr_stop+1, next_stop)] = new_cost
                 pq.heappush(pq, (new_cost, curr_stop + 1, next_stop))
     return -1
Пример #4
0
 def minPathSum(self, grid):
     """
     Solution: Dijkestra
     Time Complexity:
     Space Complexity: O(m*n)
     Inspired By: MySELF!!
     TP:
     - In this question we are not allowed to go up or left
     :type grid: List[List[int]]
     :rtype: int
     """
     pq = []
     pq.heappush(pq, (grid[0][0], (0, 0)))
     visited = set()
     m = len(grid)
     n = len(grid[0])
     #directions = [(-1, 0),(0, -1), (1, 0), (0, 1)]
     directions = [(1, 0), (0, 1)]
     while pq:
         cost, cord = pq.heappop(pq)
         i, j = cord
         if not (i, j) in visited:
             visited.add(cord)
             if (i, j) == (m - 1, n - 1):
                 return cost
             else:
                 for x_dir, y_dir in directions:
                     x = x_dir + cord[0]
                     y = y_dir + cord[1]
                     if 0 <= x < m and 0 <= y < n:
                         pq.heappush(pq, (cost + grid[x][y], (x, y)))
Пример #5
0
    def trapRainWater(self, heightMap):
        """
        Solution: Heap (Priority Q)
        Time Complexity: O(m*n)
        Space Complexity: O(m*n)
        Inspired By:
        - https://leetcode.com/problems/trapping-rain-water-ii/discuss/89466/python-solution-with-heap
        - https://www.youtube.com/watch?time_continue=7&v=cJayBq38VYw
        TP:
        - first we have to define "how to trap a water"
            - since all border can't "trap" any water, we can put all border elements into the heapQ
        - The we go through the following procedure:
            - pop from heapQ (the pop will give us lowest height cell)
            - visit all its 'unvisited neighbor'
                - if neighbor's height is smaller than 'pop' height, means we can trap water, so add the height diff to res
                - then we push this neighbor into heap
                    - !!! Tricky: we need to update this neighbor's height with max(height_of_neighbor, height_pop)
                    - WHY ?? --> if neighbor's height is smaller, then we already add the 'trap' water during this iteration
                        thus next time when its 'neighbor' turn from heapQ we can have correct amount of water
                    - consider this:
                        5 7 3 <-- current pop is 7
                        4 6 1 <-- visit neighbor 6, collect water 7-6 = 1, push 6 with height of 7 into heap
                        6 5 7 <-- next time when pop 6 and visit neighbor 5, neighbor should able to trap water 7 - 5 = 2
                        7 7 8
        - Since we start from lowest point from all borders, we can guarantee for following procedure the water will be trapped correctly
        :type heightMap: List[List[int]]
        :rtype: int
        """
        if not heightMap or not heightMap[0]: return 0
        import pq
        m = len(heightMap)
        n = len(heightMap[0])
        visited = [[False for _ in range(n)] for _ in range(m)]
        res = 0
        heap = []
        for i in range(m):
            for j in range(n):
                if i == 0 or i == m-1 or j == 0 or j == n-1:
                    pq.heappush(heap, (heightMap[i][j], i, j))
                    visited[i][j] = True
        while heap:
            height, i, j = pq.heappop(heap)
            for x, y in [(i-1, j), (i+1, j), (i, j-1), (i, j+1)]:
                if 0 <= x < m and 0 <= y < n and not visited[x][y]:
                    res += max(0, height - heightMap[x][y])
                    pq.heappush(heap, (max(heightMap[x][y], height), x, y))
                    visited[x][y] = True

        return res
Пример #6
0
 def findMinCost(self, numTotalAvailableCities, numTotalAvailableRoads, roadsAvailable, numNewRoadsConstruct, costNewRoadsConstruct):
     UF = UnionFind(numTotalAvailableCities, roadsAvailable)
     candidate_road = []
     for city1, city2, cost in costNewRoadsConstruct:
         pq.heappush(candidate_road, (cost, city1, city2))
     res = 0
     while numTotalAvailableRoads < numTotalAvailableCities-1:
         cost, city1, city2 = pq.heappop(candidate_road)
         r1 = UF.find(city1)
         r2 = UF.find(city2)
         if r1 != r2:
             UF.union(city1, city2)
             numTotalAvailableRoads += 1
             res += cost
     return res
Пример #7
0
 def mergeKSortedLists(self, lists):
     """
     Time: O(nlog(k))
     Space: O(n)
     :param lists:
     :return:
     """
     pq = []
     res = []
     for idx, list in enumerate(lists):
         pq.heappush(pq, (list.pop(0), idx))
     while pq:
         val, idx = pq.heappop(pq)
         res.append(val)
         if lists[idx]:
             pq.heappush(pq, (lists[idx].pop(0), idx))
     return res
Пример #8
0
 def minMeetingRooms(self, intervals):
     """
     Solution: Heapq + Sorting
     Time Complexity: O(nlog(n))
     Space Complexity: O(n)
     Perf: Runtime: 80 ms, faster than 22.20% / Memory Usage: 17.9 MB, less than 5.35%
     Inspired By: https://leetcode.com/problems/meeting-rooms-ii/solution/
     :type intervals: List[Interval]
     :rtype: int
     """
     intervals.sort(key=lambda x: x.start)
     schedule = []
     for interval in intervals:
         if not schedule:
             schedule.append(interval.end)
         else:
             if interval.start >= schedule[0]:
                 pq.heappushpop(schedule, interval.end)
             else:
                 pq.heappush(schedule, interval.end)
     return len(schedule)
Пример #9
0
 def mergeKLists(self, lists):
     """
     Time: O(nlog(k)) n: number of nodes, k: len of lists
     Perf: Runtime: 108 ms, faster than 57.15% / Memory Usage: 17.6 MB, less than 38.93%
     :type lists: List[ListNode]
     :rtype: ListNode
     """
     if not lists:
         return None
     stack = []
     head = ListNode(None)
     start = head
     for node in lists:
         if node:
             pq.heappush(stack, (node.val, node))
     while stack:
         val, curNode = pq.heappop(stack)
         head.next = curNode
         if curNode.next:
             pq.heappush(stack, (curNode.next.val, curNode.next))
         head = head.next
     return start.next
Пример #10
0
 def nthUglyNumber(self, n):
     """
     Facebook
     T:O(nlogn) S:O(n)
     Solution: heapq (priority queue)
     Time Complexity: O(3*n)
     Space Complexity: O(3*n)
     Perf: Runtime: 896 ms, faster than 8.14% / Memory Usage: 10.9 MB, less than 35.21%
     Inspired By: MySELF!!
     :type n: int
     :rtype: int
     """
     cand = [1]
     for i in range(n - 1):
         k = pq.heappop(cand)
         if k * 2 not in cand:
             pq.heappush(cand, k * 2)
         if k * 3 not in cand:
             pq.heappush(cand, k * 3)
         if k * 5 not in cand:
             pq.heappush(cand, k * 5)
     return pq.heappop(cand)
Пример #11
0
 def sortNArray(self, nums1, nums2, nums3):
     """
     Time Complexity: O(nlog(k))
     Space Complexity: O(k)
     :param nums1:
     :param nums2:
     :param nums3:
     :return:
     """
     pq = []
     res = []
     if nums1:
         pq.heappush(pq, (nums1.pop(0), 1))
     if nums2:
         pq.heappush(pq, (nums2.pop(0), 2))
     if nums3:
         pq.heappush(pq, (nums3.pop(0), 3))
     while pq:
         num, arrayIdx = pq.heappop(pq)
         if num not in res:
             res.append(num)
         if arrayIdx == 1:
             if nums1:
                 pq.heappush(pq, (nums1.pop(0), 1))
         elif arrayIdx == 2:
             if nums2:
                 pq.heappush(pq, (nums2.pop(0), 2))
         else:
             if nums3:
                 pq.heappush(pq, (nums3.pop(0), 3))
     return res