mirror of
https://github.com/SunnyQjm/algorithm-review.git
synced 2026-06-03 08:16:43 +08:00
add: chapter12
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env python
|
||||
# coding=utf-8
|
||||
|
||||
#######################################################################################
|
||||
# Leetcode 787 K 站中转内最便宜的航班
|
||||
#
|
||||
# 题目太长了,瞅这 => https://leetcode-cn.com/problems/cheapest-flights-within-k-stops/
|
||||
#######################################################################################
|
||||
|
||||
from typing import List
|
||||
import collections, heapq
|
||||
|
||||
class Solution:
|
||||
def findCheapestPrice(self, n: int, flights: List[List[int]], src: int, dst: int, K: int) -> int:
|
||||
"""
|
||||
:type n: int 城市个数
|
||||
:type flights: List[List[int]] m个航班
|
||||
:type src: int 出发城市
|
||||
:type dst: int 到达城市
|
||||
:type K: int 最大中转次数
|
||||
:rtype int
|
||||
|
||||
(knowledge)
|
||||
|
||||
思路:
|
||||
1. 执行Djikstra算法计算最短距离的算法,过程中传递当前的跳数,当跳数超过k+1时进行剪枝;
|
||||
2. 使用最小堆来简化Djikstra代码实现;
|
||||
3. 过程中一旦遍历到目的节点,就返回;
|
||||
"""
|
||||
|
||||
# 这边使用字典来统一表示图
|
||||
graph = collections.defaultdict(dict)
|
||||
|
||||
# 构建图
|
||||
for u, v, w in flights:
|
||||
graph[u][v] = w
|
||||
|
||||
# 最小堆中的每个元素为一个三元组,<源节点到当前节点的开销,源节点到当前节点走了几跳,当前节点编号>
|
||||
pq = [(0, 0, src)]
|
||||
|
||||
while pq:
|
||||
|
||||
# 从最小堆中取出cost最小的元素
|
||||
cost, step, place = heapq.heappop(pq)
|
||||
|
||||
# 如果到达当前节点的跳数大于K+1,则跳过
|
||||
if step > K + 1:
|
||||
continue
|
||||
|
||||
if place == dst:
|
||||
return cost
|
||||
|
||||
# 遍历当前节点的所有邻居
|
||||
for neighbour, weight in graph[place].items():
|
||||
heapq.heappush(pq, (cost + weight, step + 1, neighbour))
|
||||
return -1
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
solution = Solution()
|
||||
print(solution.findCheapestPrice(3, [[0, 1, 100], [1, 2, 100], [0, 2, 500]], 0, 2, 1), "= 200")
|
||||
print(solution.findCheapestPrice(3, [[0, 1, 100], [1, 2, 100], [0, 2, 500]], 0, 2, 0), "= 500")
|
||||
@@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env python
|
||||
# coding=utf-8
|
||||
|
||||
#######################################################################################
|
||||
# Leetcode 934 最短的桥
|
||||
#
|
||||
# 在给定的二维二进制数组 A 中,存在两座岛。(岛是由四面相连的 1 形成的一个最大组。)
|
||||
# 现在,我们可以将 0 变为 1,以使两座岛连接起来,变成一座岛。
|
||||
# 返回必须翻转的 0 的最小数目。(可以保证答案至少是 1。)
|
||||
#
|
||||
# 示例 1:
|
||||
# 输入:[[0,1],[1,0]]
|
||||
# 输出:1
|
||||
#
|
||||
# 示例 2:
|
||||
# 输入:[[0,1,0],[0,0,0],[0,0,1]]
|
||||
# 输出:2
|
||||
#
|
||||
# 示例 3:
|
||||
# 输入:[[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
|
||||
#
|
||||
# 提示:
|
||||
# 1. 1 <= A.length = A[0].length <= 100
|
||||
# 2. A[i][j] == 0 或 A[i][j] == 1
|
||||
#######################################################################################
|
||||
|
||||
from typing import List
|
||||
|
||||
class Solution:
|
||||
def shortestBridge(self, A: List[List[int]]) -> int:
|
||||
"""
|
||||
:type A: List[List[int]]
|
||||
:rtype int
|
||||
|
||||
(knowledge)
|
||||
|
||||
思路:
|
||||
1. 首先使用DFS的方式找到其中一座岛屿,并将该岛屿内所有块标记为2;
|
||||
2. 接着使用BFS的方式逐层向外探索:
|
||||
- 超出边界则忽略;
|
||||
- 探索到海域,则将其标记为2,表示已经探索过;
|
||||
- 当探索到1即终止,返回当前的轮数
|
||||
"""
|
||||
n, queue = len(A), []
|
||||
|
||||
def dfs(i, j, queue):
|
||||
if i < 0 or j < 0 or i >= n or j >= n or A[i][j] != 1:
|
||||
return
|
||||
A[i][j] = 2
|
||||
queue.append((i, j))
|
||||
dfs(i - 1, j, queue)
|
||||
dfs(i + 1, j, queue)
|
||||
dfs(i, j - 1, queue)
|
||||
dfs(i, j + 1, queue)
|
||||
return
|
||||
|
||||
|
||||
# 通过dfs找到第一座岛屿
|
||||
find = False
|
||||
for i in range(n):
|
||||
for j in range(n):
|
||||
if A[i][j] == 1:
|
||||
dfs(i, j, queue)
|
||||
find = True
|
||||
break
|
||||
if find:
|
||||
break
|
||||
|
||||
# 通过BFS搜索另一个岛屿
|
||||
s = 0 # 轮数
|
||||
while queue:
|
||||
for _ in range(len(queue)):
|
||||
i, j = queue.pop(0)
|
||||
for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
|
||||
x, y = i + dx, j + dy
|
||||
if x < 0 or y < 0 or x >= n or y >= n or A[x][y] == 2:
|
||||
continue
|
||||
if A[x][y] == 1:
|
||||
return s
|
||||
|
||||
# 经过海域,则将其标记为2,表示已经探索过
|
||||
A[x][y] = 2
|
||||
queue.append((x, y))
|
||||
s += 1
|
||||
|
||||
|
||||
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")
|
||||
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env python
|
||||
# coding=utf-8
|
||||
|
||||
#######################################################################################
|
||||
# Leetcode 692 前K个高频单词
|
||||
#
|
||||
# 给一非空的单词列表,返回前 k 个出现次数最多的单词。
|
||||
# 返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率,按字母顺序排序。
|
||||
#
|
||||
# 示例 1:
|
||||
# 输入: ["i", "love", "leetcode", "i", "love", "coding"], k = 2
|
||||
# 输出: ["i", "love"]
|
||||
# 解析: "i" 和 "love" 为出现次数最多的两个单词,均为2次。
|
||||
# 注意,按字母顺序 "i" 在 "love" 之前。
|
||||
#
|
||||
# 示例 2:
|
||||
# 输入: ["the", "day", "is", "sunny", "the", "the", "the", "sunny", "is", "is"], k = 4
|
||||
# 输出: ["the", "is", "sunny", "day"]
|
||||
# 解析: "the", "is", "sunny" 和 "day" 是出现次数最多的四个单词,
|
||||
# 出现次数依次为 4, 3, 2 和 1 次。
|
||||
#
|
||||
# 注意:
|
||||
# 1. 假定 k 总为有效值, 1 ≤ k ≤ 集合元素数。
|
||||
# 2. 输入的单词均由小写字母组成。
|
||||
#
|
||||
# 扩展练习:
|
||||
# 尝试以 O(n log k) 时间复杂度和 O(n) 空间复杂度解决。
|
||||
#######################################################################################
|
||||
|
||||
from typing import List
|
||||
import collections
|
||||
|
||||
class Solution:
|
||||
def topKFrequent(self, words: List[str], k: int) -> List[str]:
|
||||
"""
|
||||
:type words: List[str]
|
||||
:type k: int
|
||||
:rtype List[str]
|
||||
|
||||
(knowledge)
|
||||
|
||||
思路:
|
||||
1. 统计每个单词出现的频率;
|
||||
2. 然后按照词频和字母序排序(首先按照词频排序,然后如果词频相同就按字母序排序);
|
||||
3. 最后返回排序后前k个元素
|
||||
"""
|
||||
count = collections.Counter(words)
|
||||
candidates = list(count.keys())
|
||||
candidates.sort(key=lambda w: (-count[w], w))
|
||||
return candidates[:k]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
solution = Solution()
|
||||
print(solution.topKFrequent(["i", "love", "leetcode", "i", "love", "coding"], 2), "= [\"i\", \"love\"]")
|
||||
Reference in New Issue
Block a user