Ejemplo n.º 1
0
    def slidingPuzzle(self, board):
        self.goal = [[1,2,3], [4,5,0]]
        self.score = [0] * 6

        self.score[0] = [[3, 2, 1], [2, 1, 0]]
        self.score[1] = [[0, 1, 2], [1, 2, 3]]
        self.score[2] = [[1, 0, 1], [2, 1, 2]]
        self.score[3] = [[2, 1, 0], [3, 2, 1]]
        self.score[4] = [[1, 2, 3], [0, 1, 2]]
        self.score[5] = [[2, 1, 2], [1, 0, 1]]

        heap = [(0, 0, board)]
        closed = []

        while len(heap) > 0:
            node = heapq.heappop(heap)
            if node[2] == self.goal:
                return node[1]
            elif node[2] in closed:
                continue
            else:
                for next in self.get_neighbors(node[2]):
                    if next in closed: continue
                    heapq.heappush(heap, (node[1] + 1 + self.get_score(next), node[1] + 1, next))
            closed.append(node[2])
        return -1
Ejemplo n.º 2
0
def dijkstra_heap(s, edge, n):
    """
    ヒープ式高速ダイクストラ
    n:頂点数
    0-indexed
    edges[頂点番号]=[(cost,to)]
    """
    # 始点sから各頂点への最短距離
    d = [INF] * n
    used = [True] * n  # True:未確定
    d[s] = 0
    used[s] = False
    edgelist = []
    frm = [-1] * n
    for a, b in edge[s]:
        heapq.heappush(edgelist, (a * (10**6) + b, -1))
    while len(edgelist):
        minedge = heapq.heappop(edgelist)
        froom = minedge[1]
        minedge = minedge[0]
        # まだ使われてない頂点の中から最小の距離のものを探す
        if not used[minedge % (10**6)]:
            continue
        v = minedge % (10**6)
        d[v] = minedge // (10**6)
        frm[v] = froom
        used[v] = False
        for e in edge[v]:
            if used[e[1]]:
                heapq.heappush(edgelist, ((e[0] + d[v]) * (10**6) + e[1], v))
    return (d, frm)
Ejemplo n.º 3
0
def findShortestWay(self, A, ball, hole):
    ball, hole = tuple(ball), tuple(hole)
    R, C = len(A), len(A[0])
    
    def neighbors(r, c):
        for dr, dc, di in [(-1, 0, 'u'), (0, 1, 'r'), 
                           (0, -1, 'l'), (1, 0, 'd')]:
            cr, cc, dist = r, c, 0
            while (0 <= cr + dr < R and 
                    0 <= cc + dc < C and
                    not A[cr+dr][cc+dc]):
                cr += dr
                cc += dc
                dist += 1
                if (cr, cc) == hole:
                    break
            yield (cr, cc), di, dist
    
    pq = [(0, '', ball)]
    seen = set()
    while pq:
        dist, path, node = heapq.heappop(pq)
        if node in seen: continue
        if node == hole: return path
        seen.add(node)
        for nei, di, nei_dist in neighbors(*node):
            heapq.heappush(pq, (dist+nei_dist, path+di, nei) )
        
    return "impossible"
Ejemplo n.º 4
0
def top(mat, k):
    m, n = len(mat), len(mat[0])
    h = []
    temp = [sum(row[0] for row in mat)] + [0] * m
    temp = tuple(temp)
    h = [temp]
    check = set(tuple([0] * m))

    count = 0
    while h:
        #print(h, h[0])
        t = heapq.heappop(h)
        count += 1
        s = t[0]
        if count == k:
            return s
        cur = list(t[1:])
        for i, v in enumerate(cur):
            if v < n - 1:
                cur[i] += 1
                if tuple(cur) not in check:
                    check.add(tuple(cur))
                    heapq.heappush(
                        h,
                        tuple([
                            t[0] + mat[i - 1][cur[i]] - mat[i - 1][cur[i] - 1]
                        ] + cur))
                cur[i] -= 1
Ejemplo n.º 5
0
 def largestSumAfterKNegations(self, A: List[int], K: int) -> int:
     _sum = sum(A)
     heapq.heapify(A)
     while K > 0:
         curmin = heapq.heappop(A)
         heapq.heappush(A, -curmin)
         K -= 1
         _sum += -curmin * 2
     return _sum
 def findCheapestPrice(self, n, flights, src, dst, k):
     f = collections.defaultdict(dict)
     for a, b, p in flights:
         f[a][b] = p
     heap = [(0, src, k + 1)]
     while heap:
         p, i, k = heapq.heappop(heap)
         if i == dst:
             return p
         if k > 0:
             for j in f[i]:
                 heapq.heappush(heap, (p + f[i][j], j, k - 1))
     return -1
Ejemplo n.º 7
0
 def frequencySort(self, s: str) -> str:
     counter = Counter(s)
     heap = []
     
     for key,value in counter.items():
         heapq.heappush(heap, (-value, key))
         
     result = []
     while heap:
         value, char = heapq.heappop(heap)
         result.append(-value * char) 
         
     return "".join(result)
 def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
     hp = [(node.val, i, node) for i, node in enumerate(lists) if node]
     heapq.heapify(hp)
     counter = len(lists)
     dummy_head = curr = ListNode()
     while hp:
         _, _, node = heapq.heappop(hp)
         curr.next = node
         if node.next:
             heapq.heappush(hp, (node.next.val, counter, node.next))
             counter += 1
         curr = curr.next
     return dummy_head.next
Ejemplo n.º 9
0
 def maximumMinimumPath(self, A: List[List[int]]):
     d = [(0, 1), (1, 0), (0, -1), (-1, 0)]
     row, col = len(A), len(A[0])
     maxHeap = [(-A[0][0], 0, 0)]
     visited = [[0 for _ in range(col)] for _ in range(row)]
     while maxHeap:
         curr, x, y = heapq.heappop(maxHeap)
         if x == row - 1 and y == col - 1:
             return -curr
         for dx, dy in d:
             nx, ny = x + dx, y + dy
             if 0 <= nx < row and 0 <= ny < col and not visited[nx][ny]:
                 visited[nx][ny] = 1
                 heapq.heappush(maxHeap, (max(curr, -A[nx][ny]), nx, ny))
     return -1
Ejemplo n.º 10
0
    def networkDelayTime(self, times, N, K):
        graph = collections.defaultdict(list)
        for u, v, w in times:
            graph[u].append((v, w))

        pq = [(0, K)]
        dist = {}
        while pq:
            d, node = heapq.heappop(pq)
            if node in dist: continue
            dist[node] = d
            for nei, d2 in graph[node]:
                if nei not in dist:
                    heapq.heappush(pq, (d+d2, nei))

        return max(dist.values()) if len(dist) == N else -1
Ejemplo n.º 11
0
    def minMeetingRooms(self, intervals):
        if not intervals:
            return 0
        # heap
        rooms = []
        intervals.sort(key=lambda x: x[0])
        # heap is storing the end time.
        heapq.heappush(rooms, intervals[0][1])

        for interval in intervals[1:]:
            # room[0] means the top of the heap
            # if both pop and push executed. that means no room. If pop not excuted, that menas new room added
            if rooms[0] <= interval[0]:
                heapq.heappop(rooms)
            heapq.heappush(rooms, interval[1])

        return len(rooms)
Ejemplo n.º 12
0
    def kClosest(self, points: List[List[int]], K: int) -> List[List[int]]:
        # 방법1: list sort
        dist = [int(i[0])**2 + int(i[1])**2 for i in points]
        idxs = sorted(range(len(dist)), key=lambda k: dist[k])[:K]
        return np.array(points)[idxs]

        # 방법2: priority queue
        heap = []
        for x, y in points:
            dist = x**2 + y**2
            heapq.heappush(heap, (dist, x, y))  # (우선순위, 값)

        result = []
        for _ in range(K):
            (dist, x, y) = heapq.heappop(heap)
            result.append((x, y))
        return result
Ejemplo n.º 13
0
    def minSetSize(self, arr: List[int]) -> int:
        count_dict = Counter(arr)  # O(n)
        min_size = 1
        heap = []
        total = 0
        max_count = max(count_dict.values())
        for key, value in count_dict.items():  # O(n)
            heapq.heappush(heap, (-value, key))

        total = (-1 * heap[0][0])
        while total < len(arr) // 2:  # O(n/2)

            min_size += 1
            heapq.heappop(heap)
            total += (-1 * heap[0][0])

        return min_size
Ejemplo n.º 14
0
    def mergeKLists(self, lists: List[ListNode]) -> ListNode:
        head = ListNode(0)
        current = head
        heap = []
        for i, li in enumerate(lists):
            if li:
                heapq.heappush(heap, (li.val, i, li))

        while heap:
            val, idx, node = heapq.heappop(heap)
            current.next = node
            current = current.next
            node = node.next
            if node is None:
                continue
            heapq.heappush(heap, (node.val, idx, node))
        return head.next
Ejemplo n.º 15
0
 def findShortestWay(self, maze, ball, hole):
     m, n, q, stopped = len(maze), len(maze[0]), [(0, "", ball[0], ball[1])], {(ball[0], ball[1]): [0, ""]}
     while q:
         dist, pattern, x, y = heapq.heappop(q)
         if [x, y] == hole:
             return pattern
         for i, j, p in ((-1, 0, "u"), (1, 0, "d"), (0, -1, "l"), (0, 1, "r")):
             newX, newY, d = x, y, 0
             while 0 <= newX + i < m and 0 <= newY + j < n and maze[newX + i][newY + j] != 1:
                 newX += i
                 newY += j
                 d += 1
                 if [newX, newY] == hole:
                     break
             if (newX, newY) not in stopped or [dist + d, pattern + p] < stopped[(newX, newY)]:
                 stopped[(newX, newY)] = [dist + d, pattern + p]
                 heapq.heappush(q, (dist + d, pattern + p, newX, newY))
     return "impossible"
Ejemplo n.º 16
0
    def networkDelayTime(self, times, N, K):
        pq = []
        adj = [[] for _ in range(N+1)]
        for time in times:
            adj[time[0]].append((time[1], time[2]))

        fin, res = set(), 0
        heapq.heappush(pq, (0, K))

        while len(pq) and len(fin) != N:
            cur = heapq.heappop(pq)
            fin.add(cur[1])
            res = cur[0]
            for child, t in adj[cur[1]]:
                if child in fin: continue
                heapq.heappush(pq, (t+cur[0], child))

        return res if len(fin) == N else -1
    def shortestDistance(self, maze, start, destination):
        """
        :type maze: List[List[int]]
        :type start: List[int]
        :type destination: List[int]
        :rtype: int
        """
        # DFS 不撞南墙不回头,回头看看路近否

        self.m = len(maze)
        self.n = len(maze[0])
        distance = [[float('inf')] * self.n for _ in range(self.m)]

        queue = []
        heapq.heappush(queue, (0, start[0], start[1]))

        dir = ((0, 1), (0, -1), (1, 0), (-1, 0))

        while queue:

            curr, x, y = heapq.heappop(queue)
            if x == destination[0] and y == destination[1]:
                return curr
            else:
                for dx, dy in dir:
                    xn, yn = x + dx, y + dy
                    temp = curr

                    while 0 <= xn < self.m and 0 <= yn < self.n and maze[xn][
                            yn] != 1:
                        xn += dx
                        yn += dy
                        temp += 1

                    xn -= dx
                    yn -= dy

                    if distance[xn][yn] > temp:
                        distance[xn][yn] = temp
                        heapq.heappush(queue, (temp, xn, yn))

        return -1
 def minCost2(self, grid: List[List[int]]) -> int:
     RIGHT, LEFT, DOWN, UP = range(1, 5)
     R, C = len(grid), len(grid[0])
     
     dic = {(0, 0): 0}
     hp = [(0, 0, 0)]
     
     while hp:
         cost, r, c = heapq.heappop(hp)
         r, c = abs(r), abs(c)
         if r == R-1 and c == C-1:
             return cost
         
         for nr, nc, direc in ((r-1, c, UP), (r, c+1, RIGHT),
                                 (r+1, c, DOWN), (r, c-1, LEFT)):
             if nr < 0 or nr >= R or nc < 0 or nc >= C: continue # coords out of bound
             new_cost = cost+1 if direc != grid[r][c] else cost # cost increase if direction differs
             if (nr, nc) in dic and dic[(nr,nc)] <= new_cost: continue # we have visited this cell with smaller cost
             dic[(nr, nc)] = new_cost
             heapq.heappush(hp, (new_cost, -nr, -nc))
    def kWeakestRows(self, mat: List[List[int]], k: int) -> List[int]:
        count = {}
        heap = []
        result = []
        for i in range(len(mat)):
            for j in range(len(mat[0])):
                if mat[i][j] == 1:
                    if i in count:
                        count[i] += 1
                    else:
                        count[i] = 1
                else:
                    if i not in count:
                        count[i] = 0

        for key, value in count.items():
            heapq.heappush(heap, (value, key))
        for i in range(k):
            result.append(heapq.heappop(heap)[1])
        return result
    def findCheapestPrice(self, n, flights, src, dst, K):
        remain, ret, stop = [], float('inf'), 0
        weights = [sys.maxint for i in range(n)]
        graph = [{} for i in range(n)]
        for s,d,w in flights:
            graph[s][d]=w

        heapq.heappush(remain, (0, src))
        weights[src] = 0
        while remain and stop <= K:
            tmp, remain = remain, []
            while tmp:
                weight, node = heapq.heappop(tmp)
                for tonode, toweight in graph[node].items():
                    if weights[tonode] > weight + toweight:
                        weights[tonode] = weight + toweight
                        heapq.heappush(remain, (weights[tonode], tonode))    
                    # this two lines are important
                    if tonode == dst and weights[tonode]<ret:
                        ret = weights[tonode]
            stop+=1
        return ret if ret < float('inf') else -1
    def findCheapestPrice(self, n, flights, src, dst, K):
        graph = collections.defaultdict(dict)
        for u, v, w in flights:
            graph[u][v] = w

        best = {}
        pq = [(0, 0, src)]
        while pq:
            cost, k, place = heapq.heappop(pq)
            if k > K+1 or cost > best.get((k, place), float('inf')): continue
            if place == dst: return cost

            for nei, wt in graph[place].iteritems():
                newcost = cost + wt
                if newcost < best.get((k+1, nei), float('inf')):
                    heapq.heappush(pq, (newcost, k+1, nei))
                    best[k+1, nei] = newcost

        return -1

# Complexity Analysis
# Time Complexity: O(E + n \log n)O(E+nlogn), where EE is the total number of flights.
# Space Complexity: O(n)O(n), the size of the heap.
 def mostCommonWord(self, paragraph: str, banned: List[str]) -> str:
     paragraph = paragraph.lower()
     words = re.sub(r'[^\w]', ' ', paragraph).split(" ")
     heap = []
     word_count = {}
     for word in words:
         if word != "":
             if word in word_count:
                 word_count[word] += 1
             else:
                 word_count[word] = 1
     
     for key,value in word_count.items():
         heapq.heappush(heap,(-value,key))
   
     while heap:
         top = heapq.heappop(heap)
        
         if  top[1] not in banned:
             return top[1]
         continue
         
                                                              
Ejemplo n.º 23
0
    def slidingPuzzle(self, board):
        self.scores = [0] * 6
        goal_pos = {1:(0, 0), 2:(0, 1), 3: (0, 2), 4: (1,0), 5:(1,1), 0:(1, 2)}

        for num in range(6): # Pre calculate manhattan distances
            self.scores[num] = [[abs(goal_pos[num][0] - i) + abs(goal_pos[num][1] - j) for j in range(3)] for i in range(2)]

        Node = namedtuple('Node', ['heuristic_score', 'distance', 'board'])
        heap = [Node(0, 0, board)]
        closed = []

        while len(heap) > 0:
            node = heapq.heappop(heap)
            if self.get_score(node.board) == 0:
                return node.distance
            elif node.board in closed:
                continue
            else:
                for neighbor in self.get_neighbors(node.board):
                    if neighbor in closed: continue
                    heapq.heappush(heap, Node(node.distance + 1 + self.get_score(neighbor), node.distance + 1, neighbor))
            closed.append(node.board)
        return -1
Ejemplo n.º 24
0
    def reorganizeString2(self, S):
        pq = [(-S.count(x), x) for x in set(S)]
        heapq.heapify(pg)
        if any(-ct > (len(s) + 1) / 2 for ct, x in pg):
            return ""

        ans = []
        while len(pq) >= 2:
            freq1, ch1 = heapq.heappop(pq)
            freq2, ch2 = heapq.heappop(pq)
            #This code turns out to be superfluous, but explains what is happening
            #if not ans or ch1 != ans[-1]:
            #    ans.extend([ch1, ch2])
            #else:
            #    ans.extend([ch2, ch1])
            ans.extend([ch1, ch2])
            if freq1 + 1:  # notice the freq is negative here...
                heapq.heappush(pq, (freq1 + 1, ch1))
            if freq2 + 1:
                heapq.heappush(pq, (freq2 + 1, ch2))

        # second part is for single pair left in the heapq
        return "".join(ans) + (pq[0][1] if pq else '')
Ejemplo n.º 25
0
def dijkstra(graph, start):
    distance = {node: float("int") for node in graph}
    distance[start] = 0
    queue = []
    heapq.heappush(queue, [distance[start], start])
Ejemplo n.º 26
0
Tree & BFS & DFS    : 完成到250
Graph & Topological Sort & Trie & BIT(Indexed) & Segment Tree & BST(Search): 完成到332
Recursion & DP      : 完成到392
Sort & Searching    : 完成到392


# Data Structure:

from collections import deque
    lst = deque(lst)
    left_most = lst.popleft()
    right_most = lst.pop()

from collections import heapq
    heap = []
    heapq.heappush(heap, (key, stuff)) # Push the (key, stuff) pair sorted by key
    heapq.heappop(heap) # return the (key, stuff) pair with smallest

# Index
lst.index(val) -> index of val in the lst

# Random
random.randint(a, b) -> A random int value from a to b (Both inclusive)

# Linked List

# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None
Ejemplo n.º 27
0
class Solution:
	# maintain the heap
	# T: O(clogN), N as number of employees, C the number of all intervals/jobs
    # O(logN) for push and pop in heap of size N
    # O(c) as number of such operations
	def employeeFreeTime3(self, schedule: '[[Interval]]') -> '[Interval]':
		ans = []
		# (job_idx_th start time, user ID, job idx)
        pq = [(emp[0].start, empID, 0) for empID, emp in enumerate(schedule)]
        heapq.heapify(pq)
        # anchor: minimal start time for all employee
        prev_end = pq[0][0] # start time!
        while pq: # e_id: employee id; cur_jobId: current job ID
            start_time, e_id, cur_jobId = heapq.heappop(pq)
            # no overlap
            if start_time > prev_end:
                ans.append(Interval(prev_end, start_time))
            # overlap, update prev_end
            prev_end = max(prev_end, schedule[e_id][cur_jobId].end)
           	# # if there are more intervals available for the same employee, add their next interval
            if cur_jobId + 1 < len(schedule[e_id]): # push next job into it
                heapq.heappush(pq, (schedule[e_id][cur_jobId+1].start, e_id, cur_jobId+1))

        return ans



	# minheap, still not optimal since all intervals in heap
	# T: O(clogc), N as number of employees, C the number of all intervals
	# S: O(N)
	def employeeFreeTime2(self, schedule: '[[Interval]]') -> '[Interval]':
		res = []
        intervals = [(i.start, i.end) for emp in schedule for i in emp]
        heapify(intervals)

        start, end = heappop(intervals)
        prev_end = end
        while intervals:
            cur_start, cur_end = heappop(intervals)
            if cur_start > prev_end:
                res.append(Interval(prev_end, cur_start))
                prev_end = cur_end
            else:
                prev_end = max(cur_end, prev_end)
        return res



	# T: O(clogc), n as number of all intervals, not optimal
	def employeeFreeTime1(self, schedule: '[[Interval]]') -> '[Interval]':
		intervals = sorted([i for emp in schedule for i in emp], \
			key=lambda x: x.start)
	    res, pre = [], intervals[0]
	    for cur_interval in intervals[1:]:
	    	# overlap, extend/update the prev_end
	        if cur_interval.start <= pre.end and cur_interval.end > pre.end:
	            pre.end = cur_interval.end
	        # no overlap
	        elif cur_interval.start > pre.end:
	            res.append(Interval(pre.end, cur_interval.start))
	            pre = cur_interval
	    return res
Ejemplo n.º 28
0
'''
Ejemplo n.º 29
0
#! /usr/bin/env python3
# -*- coding: utf-8 -*-

# Source: https://leetcode.com/problems/meeting-rooms-ii/
# Author: Miao Zhang
# Date:   2021-01-28

class Solution:
    def minMeetingRooms(self, intervals: List[List[int]]) -> int:
	    from collections import heapq
		intervals.sort(key = lambda x: x[0})
        heap = []
		for it in intervals:
		if heap and it[0] >= heap[0]:
		    heapq.heapreplace(heap, it[2])
		else:
		    heapq.heappush(heap, it[2])
	    return len(heapq)