第一题:查询网格图中每一列的宽度
给你一个下标从 0 开始的 m x n
整数矩阵 grid
。矩阵中某一列的宽度是这一列数字的最大 字符串长度 。
- 比方说,如果
grid = [[-10], [3], [12]]
,那么唯一一列的宽度是3
,因为-10
的字符串长度为3
。
请你返回一个大小为 n
的整数数组 ans
,其中 ans[i]
是第 i
列的宽度。
一个有 len
个数位的整数 x
,如果是非负数,那么 字符串长度 为 len
,否则为 len + 1
。
示例 1:
输入:grid = [[1],[22],[333]] 输出:[3] 解释:第 0 列中,333 字符串长度为 3 。
示例 2:
输入:grid = [[-15,1,3],[15,7,12],[5,6,-2]] 输出:[3,1,2] 解释: 第 0 列中,只有 -15 字符串长度为 3 。 第 1 列中,所有整数的字符串长度都是 1 。 第 2 列中,12 和 -2 的字符串长度都为 2
m == grid.length
n == grid[i].length
1 <= m, n <= 100
-109 <= grid[r][c] <= 109
class Solution: def findColumnWidth(self, grid: List[List[int]]) -> List[int]: ans = [] n, m = len(grid), len(grid[0]) for i in range(m): res = 0 for j in range(n): res = max(res, len(str(grid[j][i]))) ans.append(res) return ans
第二题:一个数组所有前缀的分数
给你一个下标从 0 开始的 m x n 整数矩阵 grid 。矩阵中某一列的宽度是这一列数字的最大 字符串长度 。
比方说,如果 grid = [[-10], [3], [12]] ,那么唯一一列的宽度是 3 ,因为 -10 的字符串长度为 3 。
请你返回一个大小为 n 的整数数组 ans ,其中 ans[i] 是第 i 列的宽度。
一个有 len 个数位的整数 x ,如果是非负数,那么 字符串长度 为 len ,否则为 len +1。
示例 1:
输入:grid = [[1],[22],[333]]
输出:[3]
解释:第 0 列中,333 字符串长度为 3 。
示例 2:
输入:grid = [[-15,1,3],[15,7,12],[5,6,-2]]
输出:[3,1,2]
解释:
第 0 列中,只有 -15 字符串长度为 3 。
第 1 列中,所有整数的字符串长度都是 1 。
第 2 列中,12 和 -2 的字符串长度都为 2
class Solution:
def findPrefixScore(self, nums: List[int]) -> List[int]:
pref_max = list(accumulate(nums, max))
trans = [x + y for x, y in zip(pref_max, nums)]
return list(accumulate(trans))
第三题:二叉树的堂兄弟节点 II
给你一棵二叉树的根 root ,请你将每个节点的值替换成该节点的所有 堂兄弟节点值的和 。
如果两个节点在树中有相同的深度且它们的父节点不同,那么它们互为 堂兄弟 。
请你返回修改值之后,树的根 root 。
注意,一个节点的深度指的是从树根节点到这个节点经过的边数。
示例 1:
输入:root = [5,4,9,1,10,null,7]
输出:[0,0,0,7,7,null,11]
解释:上图展示了初始的二叉树和修改每个节点的值之后的二叉树。
- 值为 5 的节点没有堂兄弟,所以值修改为 0 。
- 值为 4 的节点没有堂兄弟,所以值修改为 0 。
- 值为 9 的节点没有堂兄弟,所以值修改为 0 。
- 值为 1 的节点有一个堂兄弟,值为 7 ,所以值修改为 7 。
- 值为 10 的节点有一个堂兄弟,值为 7 ,所以值修改为 7 。
- 值为 7 的节点有两个堂兄弟,值分别为 1 和 10 ,所以值修改为 11 。
示例 2:
输入:root = [3,1,2]
输出:[0,0,0]
解释:上图展示了初始的二叉树和修改每个节点的值之后的二叉树。
- 值为 3 的节点没有堂兄弟,所以值修改为 0 。
- 值为 1 的节点没有堂兄弟,所以值修改为 0 。
- 值为 2 的节点没有堂兄弟,所以值修改为 0 。
提示:
树中节点数目的范围是 [1, 105] 。
1 <= Node.val <= 104
class Solution:
def replaceValueInTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
tmp = []
dq = deque([root])
while dq:
res = 0
for _ in range(len(dq)):
rt = dq.popleft()
res += rt.val
if rt.left: dq.append(rt.left)
if rt.right: dq.append(rt.right)
tmp.append(res)
# 根节点单独处理
root.val = 0
def dfs(rt, depth):
if depth + 1 < len(tmp):
# 下一层的和,这样方便找兄弟
tot = tmp[depth + 1]
# 去掉下一层的子节点和
if rt.left: tot -= rt.left.val
if rt.right: tot -= rt.right.val
# 赋值并继续向下遍历
if rt.left:
rt.left.val = tot
dfs(rt.left, depth+1)
if rt.right:
rt.right.val = tot
dfs(rt.right, depth+1)
dfs(root, 0)
return root
第四题:设计可以求最短路径的图类
给你一个有 n 个节点的 有向带权 图,节点编号为 0 到 n - 1 。图中的初始边用数组 edges 表示,其中 edges[i] = [fromi, toi, edgeCosti] 表示从 fromi 到 toi 有一条代价为 edgeCosti 的边。
请你实现一个 Graph 类:
Graph(int n, int[][] edges) 初始化图有 n 个节点,并输入初始边。
addEdge(int[] edge) 向边集中添加一条边,其中 edge = [from, to, edgeCost] 。数据保证添加这条边之前对应的两个节点之间没有有向边。
int shortestPath(int node1, int node2) 返回从节点 node1 到 node2 的路径 最小 代价。如果路径不存在,返回 -1 。一条路径的代价是路径中所有边代价之和。
示例 1:
输入:
["Graph", "shortestPath", "shortestPath", "addEdge", "shortestPath"]
[[4, [[0, 2, 5], [0, 1, 2], [1, 2, 1], [3, 0, 3]]], [3, 2], [0, 3], [[1, 3, 4]], [0, 3]]
输出:
[null, 6, -1, null, 6]
解释:
Graph g = new Graph(4, [[0, 2, 5], [0, 1, 2], [1, 2, 1], [3, 0, 3]]);
g.shortestPath(3, 2); // 返回 6 。从 3 到 2 的最短路径如第一幅图所示:3 -> 0 -> 1 -> 2 ,总代价为 3 + 2 + 1 = 6 。
g.shortestPath(0, 3); // 返回 -1 。没有从 0 到 3 的路径。
g.addEdge([1, 3, 4]); // 添加一条节点 1 到节点 3 的边,得到第二幅图。
g.shortestPath(0, 3); // 返回 6 。从 0 到 3 的最短路径为 0 -> 1 -> 3 ,总代价为 2 + 4 = 6 。
提示:
1 <= n <= 100
0 <= edges.length <= n * (n - 1)
edges[i].length == edge.length == 3
0 <= fromi, toi, from, to, node1, node2 <= n - 1
1 <= edgeCosti, edgeCost <= 106
图中任何时候都不会有重边和自环。
调用 addEdge 至多 100 次。
调用 shortestPath 至多 100 次。
class Graph:
def __init__(self, n: int, edges: List[List[int]]):
g = [[inf] * n for _ in range(n)] # 邻接矩阵(初始化为无穷大,表示 i 到 j 没有边)
for x, y, w in edges:
g[x][y] = w # 添加一条边(输入保证没有重边)
self.g = g
def addEdge(self, e: List[int]) -> None:
self.g[e[0]][e[1]] = e[2] # 添加一条边(输入保证这条边之前不存在)
def shortestPath(self, node1: int, node2: int) -> int:
ans = self._dijkstra(node1)[node2]
return ans if ans < inf else -1
# Dijkstra 算法的邻接矩阵版本
# 返回从 start 出发,到各个点的最短路,如果不存在则为无穷大
def _dijkstra(self, start: int) -> List[int]:
n = len(self.g)
dis = [inf] * n
dis[start] = 0
vis = [False] * n
while True:
# 找到当前最短路,去更新它的邻居的最短路
# 根据数学归纳法,dis[x] 一定是最短路长度
x = -1
for i, (b, d) in enumerate(zip(vis, dis)):
if not b and (x < 0 or d < dis[x]):
x = i
if x < 0 or dis[x] == inf: # 所有从 start 能到达的点都被更新了
return dis
vis[x] = True # 标记,在后续的循环中无需反复更新 x 到其余点的最短路长度
for y, w in enumerate(self.g[x]):
if dis[x] + w < dis[y]:
dis[y] = dis[x] + w # 更新最短路长度
来源:力扣(LeetCode)
https://leetcode.cn/problems/design-graph-with-shortest-path-calculator
https://leetcode.cn/circle/discuss/PJYuMG/view/TeA5eD/
。