给你三个 正整数 n
、x
和 y
。
在城市中,存在编号从 1
到 n
的房屋,由 n
条街道相连。对所有 1 <= i < n
,都存在一条街道连接编号为 i
的房屋与编号为 i + 1
的房屋。另存在一条街道连接编号为 x
的房屋与编号为 y
的房屋。
对于每个 k
(1 <= k <= n
),你需要找出所有满足要求的 房屋对 [house1, house2]
,即从 house1
到 house2
需要经过的 最少 街道数为 k
。
返回一个下标从 1 开始且长度为 n
的数组 result
,其中 result[k]
表示所有满足要求的房屋对的数量,即从一个房屋到另一个房屋需要经过的 最少 街道数为 k
。
注意,x
与 y
可以 相等 。
示例 1:
输入:n = 3, x = 1, y = 3 输出:[6,0,0] 解释:让我们检视每个房屋对 - 对于房屋对 (1, 2),可以直接从房屋 1 到房屋 2。 - 对于房屋对 (2, 1),可以直接从房屋 2 到房屋 1。 - 对于房屋对 (1, 3),可以直接从房屋 1 到房屋 3。 - 对于房屋对 (3, 1),可以直接从房屋 3 到房屋 1。 - 对于房屋对 (2, 3),可以直接从房屋 2 到房屋 3。 - 对于房屋对 (3, 2),可以直接从房屋 3 到房屋 2。
示例 2:
输入:n = 5, x = 2, y = 4 输出:[10,8,2,0,0] 解释:对于每个距离 k ,满足要求的房屋对如下: - 对于 k == 1,满足要求的房屋对有 (1, 2), (2, 1), (2, 3), (3, 2), (2, 4), (4, 2), (3, 4), (4, 3), (4, 5), 以及 (5, 4)。 - 对于 k == 2,满足要求的房屋对有 (1, 3), (3, 1), (1, 4), (4, 1), (2, 5), (5, 2), (3, 5), 以及 (5, 3)。 - 对于 k == 3,满足要求的房屋对有 (1, 5),以及 (5, 1) 。 - 对于 k == 4 和 k == 5,不存在满足要求的房屋对。
示例 3:
输入:n = 4, x = 1, y = 1 输出:[6,4,2,0] 解释:对于每个距离 k ,满足要求的房屋对如下: - 对于 k == 1,满足要求的房屋对有 (1, 2), (2, 1), (2, 3), (3, 2), (3, 4), 以及 (4, 3)。 - 对于 k == 2,满足要求的房屋对有 (1, 3), (3, 1), (2, 4), 以及 (4, 2)。 - 对于 k == 3,满足要求的房屋对有 (1, 4), 以及 (4, 1)。 - 对于 k == 4,不存在满足要求的房屋对。
提示:
2 <= n <= 100
1 <= x, y <= n
提示 1
Start from each house, run a BFS to get all the distances from this house to all the other houses.
解法1:Floyd算法求最短路径
Java版:
class Solution {
public int[] countOfPairs(int n, int x, int y) {
int[][] weight = new int[n + 1][n + 1];
int maxinf = 100;
// 初始化 邻接矩阵
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
weight[i][j] = i == j ? 0 : maxinf;
}
}
// 额外的捷径的权值是1,但不能是自身到自身,因为自身到自身的权值本来就是0
if (x != y) {
weight[x][y] = 1;
weight[y][x] = 1;
}
// 建图,前后相邻 权值都是1
for (int i = 1; i < n; i++) {
weight[i][i + 1] = 1;
weight[i + 1][i] = 1;
}
// 弗洛依德算法求最短路径
for (int mid = 1; mid <= n; mid++) {
for (int l = 1; l <= n; l++) {
for (int r = 1; r <= n; r++) {
weight[l][r] = Math.min(weight[l][r], weight[l][mid] + weight[mid][r]);
}
}
}
int[] ans = new int[n];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (weight[i][j] > 0 && weight[i][j] < maxinf) {
ans[weight[i][j] - 1]++;
}
}
}
return ans;
}
}
另一种写法:
class Solution {
public int[] countOfPairs(int n, int x, int y) {
int maxinf = 100;
int[][] weight = new int[n + 1][n + 1];
for (int i = 1; i <= n; i++) {
Arrays.fill(weight[i], maxinf);
weight[i][i] = 0;
}
for (int i = 1; i < n; i++) {
weight[i][i + 1] = 1;
weight[i + 1][i] = 1;
}
if (x != y) {
weight[x][y] = 1;
weight[y][x] = 1;
}
for (int mid = 1; mid <= n; mid++) {
for (int l = 1; l <= n; l++) {
for (int r = 1; r <= n; r++) {
weight[l][r] = Math.min(weight[l][r], weight[l][mid] + weight[mid][r]);
}
}
}
int[] ans = new int[n];
for (int i = 1; i < n; i++) {
for (int j = i + 1; j <= n; j++) {
if (weight[i][j] > 0 && weight[i][j] < maxinf) {
ans[weight[i][j] - 1] += 2;
}
}
}
return ans;
}
}
Python3版:
class Solution:
def countOfPairs(self, n: int, x: int, y: int) -> List[int]:
weight = [[0] * (n + 1) for _ in range(n + 1)]
maxinf = 100
# 初始化邻接矩阵
for i in range (1, n + 1):
for j in range(1, n + 1):
weight[i][j] = 0 if i == j else maxinf
# 额外的捷径的权值是1,但不能是自身到自身,因为自身到自身的权值本来就是0
if x != y:
weight[x][y] = 1
weight[y][x] = 1
# 建图,前后相邻 权值都是1
for i in range(1, n):
weight[i][i + 1] = 1
weight[i + 1][i] = 1
# 弗洛依德算法求最短路径
for mid in range(1, n + 1):
for l in range(1, n + 1):
for r in range(1, n + 1):
weight[l][r] = min(weight[l][r], weight[l][mid] + weight[mid][r])
ans = [0] * n
for i in range(1, n + 1):
for j in range(1, n + 1):
if weight[i][j] > 0 and weight[i][j] < maxinf:
ans[weight[i][j] - 1] += 1
return ans
另一种写法:
class Solution:
def countOfPairs(self, n: int, x: int, y: int) -> List[int]:
maxinf = 100
weight = [[maxinf] * (n + 1) for _ in range(n + 1)]
for i in range(1, n):
weight[i][i] = 0
weight[i][i + 1] = 1
weight[i + 1][i] = 1
if x != y:
weight[x][y] = 1
weight[y][x] = 1
for mid in range(1, n + 1):
for l in range(1, n + 1):
for r in range(1, n + 1):
weight[l][r] = min(weight[l][r], weight[l][mid] + weight[mid][r])
ans = [0] * n
for i in range(1, n):
for j in range(i + 1, n + 1):
if weight[i][j] > 0 and weight[i][j] < maxinf:
ans[weight[i][j] - 1] += 2
return ans
复杂度分析
- 时间复杂度:O(n^3),其中 n 是给定的房屋数。
- 空间复杂度:O(n),其中 n 是给定的房屋数。
解法2:Dijkstar算法求最短路径 + 优先队列 小顶堆
Java版:
class Solution {
public int[] countOfPairs(int n, int x, int y) {
int maxinf = 100;
List<List<Integer>> vertex = new ArrayList<>();
for (int i = 0; i <= n; i++) {
vertex.add(new ArrayList<>());
}
for (int i = 1; i < n; i++) {
vertex.get(i).add(i + 1);
vertex.get(i + 1).add(i);
}
if (x != y) {
vertex.get(x).add(y);
vertex.get(y).add(x);
}
int[] ans = new int[n];
for (int i = 1; i < n; i++) {
for (int j = i + 1; j <= n; j++) {
ans[dijkstra(i, j, vertex, maxinf, n) - 1] += 2;
}
}
return ans;
}
private int dijkstra(int a, int b, List<List<Integer>> vertex, int maxinf, int n) {
PriorityQueue<int[]> heap = new PriorityQueue<>(new Comparator<int[]>() {
public int compare(int[] p1, int[] p2) {
return p1[0] - p2[0];
}
});
heap.add(new int[]{0, a});
int[] weight = new int[n + 1];
Arrays.fill(weight, maxinf);
while (heap.size() > 0) {
int[] h = heap.poll();
int w = h[0];
int v = h[1];
if (v == b) {
return w;
}
for (Integer k : vertex.get(v)) {
if (weight[k] > w + 1) {
weight[k] = w + 1;
heap.add(new int[]{w + 1, k});
}
}
}
return 0;
}
}
Python3版:
class Solution:
def countOfPairs(self, n: int, x: int, y: int) -> List[int]:
maxinf = 100
vertex = [[] for _ in range(n + 1)]
# 初始化邻接顶点
for i in range(1, n):
vertex[i].append(i + 1)
vertex[i + 1].append(i)
if x != y:
vertex[x].append(y)
vertex[y].append(x)
def dijkstra(a, b):
heap = []
heap.append([0, a])
weight = [maxinf] * (n + 1)
while heap:
w, v = heappop(heap)
if v == b:
return w
for k in vertex[v]:
if weight[k] > w + 1:
weight[k] = w + 1
heappush(heap, [w + 1, k])
ans = [0] * n
for i in range(1, n):
for j in range(i + 1, n + 1):
ans[dijkstra(i, j) - 1] += 2
return ans
复杂度分析
- 时间复杂度:O(n^2 logn),其中 n 是给定的房屋数。
- 空间复杂度:O(n),其中 n 是给定的房屋数。