1
0
mirror of https://github.com/SunnyQjm/algorithm-review.git synced 2026-06-03 08:16:43 +08:00

add: dijkstra

This commit is contained in:
2020-06-27 09:07:35 +08:00
parent a798d3272b
commit 99631c82e9
15 changed files with 77 additions and 39 deletions
+7 -5
View File
@@ -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")
+47
View File
@@ -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'))
+5 -4
View File
@@ -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")
@@ -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")
+1 -1
View File
@@ -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)
+1 -2
View File
@@ -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]]")
+3 -9
View File
@@ -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")
@@ -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")
+1 -1
View File
@@ -33,7 +33,7 @@ class Solution:
思路:
1. 直接用两个指针,sPtr指向短串s,tPtr指向长串t;
2. 依次按需长串中找到子串中的每一个字符,都找到返回true,否则返回false
2. 依次按需长串中找到子串中的每一个字符,都找到返回true,否则返回false
"""
if len(s) > len(t):
return False
+1 -2
View File
@@ -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")
-1
View File
@@ -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
-1
View File
@@ -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])
@@ -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
+1 -1
View File
@@ -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]
+1 -1
View File
@@ -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的虚拟阶梯,代表楼顶,我们的目标就是要到达这个楼顶