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:
@@ -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")
|
||||
|
||||
@@ -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'))
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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]]")
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ class Solution:
|
||||
|
||||
思路:
|
||||
1. 直接用两个指针,sPtr指向短串s,tPtr指向长串t;
|
||||
2. 依次按需再长串中找到子串中的每一个字符,都找到返回true,否则返回false
|
||||
2. 依次按需在长串中找到子串中的每一个字符,都找到返回true,否则返回false
|
||||
"""
|
||||
if len(s) > len(t):
|
||||
return False
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
|
||||
|
||||
@@ -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的虚拟阶梯,代表楼顶,我们的目标就是要到达这个楼顶
|
||||
|
||||
Reference in New Issue
Block a user