diff --git a/chapter12/2_shortest-bridge.py b/chapter12/2_shortest-bridge.py index fa4c3f9..44f3028 100644 --- a/chapter12/2_shortest-bridge.py +++ b/chapter12/2_shortest-bridge.py @@ -27,6 +27,7 @@ from typing import List + class Solution: def shortestBridge(self, A: List[List[int]]) -> int: """ @@ -55,7 +56,6 @@ class Solution: dfs(i, j + 1, queue) return - # 通过dfs找到第一座岛屿 find = False for i in range(n): @@ -68,7 +68,7 @@ class Solution: break # 通过BFS搜索另一个岛屿 - s = 0 # 轮数 + s = 0 # 轮数 while queue: for _ in range(len(queue)): i, j = queue.pop(0) @@ -87,6 +87,8 @@ class Solution: if __name__ == '__main__': solution = Solution() - print(solution.shortestBridge([[0 ,1], [1, 0]]), "= 1") - print(solution.shortestBridge([[0 ,1, 0], [0, 0, 0], [0, 0, 1]]), "= 2") - print(solution.shortestBridge([[1, 1, 1, 1, 1], [1, 0, 0, 0, 1], [1, 0, 1, 0, 1], [1, 0, 0, 0, 1], [1, 1, 1, 1, 1]]), "= 1") + print(solution.shortestBridge([[0, 1], [1, 0]]), "= 1") + print(solution.shortestBridge([[0, 1, 0], [0, 0, 0], [0, 0, 1]]), "= 2") + print( + solution.shortestBridge([[1, 1, 1, 1, 1], [1, 0, 0, 0, 1], [1, 0, 1, 0, 1], [1, 0, 0, 0, 1], [1, 1, 1, 1, 1]]), + "= 1") diff --git a/chapter12/4_dijkstra.py b/chapter12/4_dijkstra.py new file mode 100644 index 0000000..f52e420 --- /dev/null +++ b/chapter12/4_dijkstra.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python +# coding=utf-8 + +####################################################################################### +# Dijkstra 单源最短路径算法 +####################################################################################### + +from typing import Dict +import heapq + + +def dijkstra(distances: Dict, origin: str) -> Dict: + """ + :type distances: Dict[Dict] 表示所有的带权边 + :type origin: str 起点 + :rtype Dict + """ + + # visited => 记录节点源节点到它的最短路径(已经在visited里面的点都是已确定最短路径的点) + # pq => 一个最小堆,用来存放候选节点 + visited, pq = {}, [(0, origin)] + + while pq: + distance, node = heapq.heappop(pq) + + # 跳过已遍历的节点 + if node in visited: + continue + + # 将当前节点放入已确定最短距离的集合中 + visited[node] = distance + + # 遍历当前节点所有的邻居,如果该邻居不在visited里面,则将通过当前节点到达该邻居的距离以及邻居的名字放入堆中 + for neighbour, cost in distances[node].items(): + if neighbour not in visited: + heapq.heappush(pq, (distance + cost, neighbour)) + return visited + + +if __name__ == '__main__': + distances = { + 'S': {'A': 6, 'B': 2}, + 'A': {'E': 1}, + 'B': {'A': 3, 'E': 5}, + 'E': {'E': 0} + } + print(dijkstra(distances, 'S')) diff --git a/chapter13/1_network-delay-time.py b/chapter13/1_network-delay-time.py index 9b011f4..960319d 100644 --- a/chapter13/1_network-delay-time.py +++ b/chapter13/1_network-delay-time.py @@ -11,8 +11,10 @@ # ####################################################################################### +import collections +import heapq from typing import List -import collections, heapq + class Solution: def networkDelayTime(self, times: List[List[int]], N: int, K: int) -> int: @@ -34,11 +36,10 @@ class Solution: for u, v, w in times: graph[u][v] = w - visited = {} # 一个最小堆,用来存储Dijkstra算法执行过程中的候选节点 - pq = [(0, K)] + pq = [(0, K)] while pq: distance, node = heapq.heappop(pq) @@ -60,4 +61,4 @@ class Solution: if __name__ == '__main__': solution = Solution() - print(solution.networkDelayTime([[2,1,1],[2,3,1],[3,4,1]], 4, 2), "= 2") + print(solution.networkDelayTime([[2, 1, 1], [2, 3, 1], [3, 4, 1]], 4, 2), "= 2") diff --git a/chapter13/2_shortest-path-visiting-all-nodes.py b/chapter13/2_shortest-path-visiting-all-nodes.py index e111741..58ec497 100644 --- a/chapter13/2_shortest-path-visiting-all-nodes.py +++ b/chapter13/2_shortest-path-visiting-all-nodes.py @@ -55,7 +55,7 @@ class Solution: # 结束标记 END = (1 << N) - 1 - + # 初始以图中所有节点为出发点 queue = [(1 << i, i) for i in range(N)] @@ -90,5 +90,5 @@ class Solution: if __name__ == '__main__': solution = Solution() - print(solution.shortestPathLength([[1,2,3],[0],[0],[0]]), "= 4") - print(solution.shortestPathLength([[1],[0,2,4],[1,3,4],[2],[1,2]]), "= 4") + print(solution.shortestPathLength([[1, 2, 3], [0], [0], [0]]), "= 4") + print(solution.shortestPathLength([[1], [0, 2, 4], [1, 3, 4], [2], [1, 2]]), "= 4") diff --git a/chapter3/13_sliding-window-maximum.py b/chapter3/13_sliding-window-maximum.py index f36c434..d011901 100644 --- a/chapter3/13_sliding-window-maximum.py +++ b/chapter3/13_sliding-window-maximum.py @@ -117,7 +117,7 @@ class Solution: if i >= k and window[0] <= i - k: window.pop(0) - # 将比待插入值小的都右出队 + # 将比待插入值小的右出队 while window and nums[window[-1]] <= x: window.pop() window.append(i) diff --git a/chapter6/1_merge-intervals.py b/chapter6/1_merge-intervals.py index 9f8fd65..a23794d 100644 --- a/chapter6/1_merge-intervals.py +++ b/chapter6/1_merge-intervals.py @@ -42,7 +42,7 @@ class Solution: while next < len(intervals): if intervals[next][0] > intervals[cur][1]: # 处理没有重叠的情况 intervals[cur + 1], cur, next = intervals[next], cur + 1, next + 1 - else: # 处理有重叠的情况 + else: # 处理有重叠的情况 intervals[cur][1], next = max(intervals[cur][1], intervals[next][1]), next + 1 return intervals[:cur + 1] @@ -52,4 +52,3 @@ if __name__ == '__main__': solution = Solution() print(solution.merge([[1, 3], [2, 6], [8, 10], [15, 18]]), "= [[1, 6], [8, 10], [15, 18]]") print(solution.merge([[1, 4], [4, 5]]), "= [[1, 5]]") - diff --git a/chapter6/2_sort-list.py b/chapter6/2_sort-list.py index 3166acf..8df5477 100644 --- a/chapter6/2_sort-list.py +++ b/chapter6/2_sort-list.py @@ -19,7 +19,7 @@ class ListNode: def __init__(self, x): self.val = x self.next = None - + def __repr__(self): if self: return "{}->{}".format(self.val, repr(self.next)) @@ -41,7 +41,7 @@ class Solution: # 链表为空或者只有一个元素,直接返回 if not head or not head.next: return head - + # low -> 右子链的头部 # pre -> 左子链最后一个节点(未断开之前,指向low) low, fast, pre = head, head, None @@ -58,7 +58,7 @@ class Solution: # 对排好序的两部分进行归并 if not low: return head - + result, cur = self, None while head and low: if head.val <= low.val: @@ -83,9 +83,3 @@ if __name__ == '__main__': h1.next.next = ListNode(1) h1.next.next.next = ListNode(3) print(solution.sortList(h1), "= 1->2->3->4") - - - - - - diff --git a/chapter6/4_best-time-to-buy-and-sell-stock-ii.py b/chapter6/4_best-time-to-buy-and-sell-stock-ii.py index 80999b7..5e3db89 100644 --- a/chapter6/4_best-time-to-buy-and-sell-stock-ii.py +++ b/chapter6/4_best-time-to-buy-and-sell-stock-ii.py @@ -52,5 +52,3 @@ if __name__ == '__main__': print(solution.maxProfit([7, 1, 5, 3, 6, 4]), "= 7") print(solution.maxProfit([1, 2, 3, 4, 5]), "= 4") print(solution.maxProfit([7, 6, 4, 3, 1]), "= 0") - - diff --git a/chapter6/5_is-subsequence.py b/chapter6/5_is-subsequence.py index 244d040..e665d75 100644 --- a/chapter6/5_is-subsequence.py +++ b/chapter6/5_is-subsequence.py @@ -33,7 +33,7 @@ class Solution: 思路: 1. 直接用两个指针,sPtr指向短串s,tPtr指向长串t; - 2. 依次按需再长串中找到子串中的每一个字符,都找到返回true,否则返回false + 2. 依次按需在长串中找到子串中的每一个字符,都找到返回true,否则返回false """ if len(s) > len(t): return False diff --git a/chapter6/7_coin-change.py b/chapter6/7_coin-change.py index f2e50cd..0ed059b 100644 --- a/chapter6/7_coin-change.py +++ b/chapter6/7_coin-change.py @@ -34,7 +34,7 @@ class Solution: 0 n == 0 min{f(n - c) + 1 | c ∈ coins} """ - + dp = [amount + 1 for i in range(amount + 1)] dp[0] = 0 @@ -51,4 +51,3 @@ if __name__ == '__main__': solution = Solution() print(solution.coinChange([1, 2, 5], 11), "= 3") print(solution.coinChange([2], 3), "= -1") - diff --git a/chapter6/9_unique-paths-ii.py b/chapter6/9_unique-paths-ii.py index 2b31049..64e28b0 100644 --- a/chapter6/9_unique-paths-ii.py +++ b/chapter6/9_unique-paths-ii.py @@ -38,7 +38,6 @@ class Solution: 思路: 1. 动态规划 2. dp[i][j] => 第处于第i + 1行第j + 1列的方格,到目的地可走的路径数量 - 3. 3. 状态转移方程: f(i, j) = f(i + 1, j) + f(i, j + 1) i+1 < m && j+1 < n && obstacleGrid[i][j] != 1 f(i + 1, j) i+1 < m && j+1 == n && obstacleGrid[i][j] != 1 diff --git a/chapter7/2_minimum-path-sum.py b/chapter7/2_minimum-path-sum.py index c41cb35..2482f97 100644 --- a/chapter7/2_minimum-path-sum.py +++ b/chapter7/2_minimum-path-sum.py @@ -45,7 +45,6 @@ class Solution: for j in range(n - 2, -1, -1): grid[m - 1][j] += grid[m - 1][j + 1] - for i in range(m - 2, -1, -1): for j in range(n - 2, -1, -1): grid[i][j] += min(grid[i + 1][j], grid[i][j + 1]) diff --git a/chapter7/4_best-time-to-buy-and-sell-stock-iii.py b/chapter7/4_best-time-to-buy-and-sell-stock-iii.py index 721c4f4..00f0529 100644 --- a/chapter7/4_best-time-to-buy-and-sell-stock-iii.py +++ b/chapter7/4_best-time-to-buy-and-sell-stock-iii.py @@ -42,9 +42,9 @@ class Solution: - maxV => 在反向遍历过程中,记录的已遍历部分的最高价格 - 状态转移方程: dp[i] = 0 i == n - 1 - = max(dp[i + 1], max - prices[i]) i < n - 1 + = max(dp[i + 1], maxV - prices[i]) i < n - 1 2. 接着进行正向遍历, 计算[0:i]范围内完成一次交易最多可得多少收益: - - min => 记录在正向遍历过程中,已遍历部分的最低价格 + - minV => 记录在正向遍历过程中,已遍历部分的最低价格 - last => 记录[0:i-1]范围内完成一次交易最多可得多少收益 - 状态转移方程: cur = 0 i == 0 @@ -67,12 +67,12 @@ class Solution: maxV = prices[i] # 正向遍历初始化 - last, min, result = 0, prices[0], 0 + last, minV, result = 0, prices[0], 0 for i in range(1, len(prices)): - cur = max(last, prices[i] - min) + cur = max(last, prices[i] - minV) last, result = cur, max(result, cur + dp[i + 1]) - if prices[i] < min: - min = prices[i] + if prices[i] < minV: + minV = prices[i] return result diff --git a/chapter8/1_knapsack-problem.py b/chapter8/1_knapsack-problem.py index ac31c7a..3a0b6d0 100644 --- a/chapter8/1_knapsack-problem.py +++ b/chapter8/1_knapsack-problem.py @@ -35,7 +35,7 @@ class Solution: if wt[i - 1] > w: dp[i][w] = dp[i - 1][w] else: - dp[i][w] = max(dp[i - 1][w], dp[i - 1][w - wt[i - 1]] + val[i - 1]); + dp[i][w] = max(dp[i - 1][w], dp[i - 1][w - wt[i - 1]] + val[i - 1]) return dp[N][W] diff --git a/chapter8/3_min-cost-climbing-stairs.py b/chapter8/3_min-cost-climbing-stairs.py index 76ccedd..c48d11d 100644 --- a/chapter8/3_min-cost-climbing-stairs.py +++ b/chapter8/3_min-cost-climbing-stairs.py @@ -36,7 +36,7 @@ class Solution: 3. base case => dp[0] = cost[0], dp[1] = cost[1] 4. 状态转移方程: f(i) = cost[i] i == 0 || i == 1 - min{cost[i - 1] + cost[i], cost[i - 2] + cost[i]} i > 1 + cost[i] + min{cost[i - 1], cost[i - 2]} i > 1 """ # 最末尾添加一个开销为0的虚拟阶梯,代表楼顶,我们的目标就是要到达这个楼顶