LeetCode 3015. 按距离统计房屋对数目 I

3015. 按距离统计房屋对数目 I

给你三个 正整数 n 、x 和 y 。

在城市中,存在编号从 1 到 n 的房屋,由 n 条街道相连。对所有 1 <= i < n ,都存在一条街道连接编号为 i 的房屋与编号为 i + 1 的房屋。另存在一条街道连接编号为 x 的房屋与编号为 y 的房屋。

对于每个 k1 <= 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 是给定的房屋数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值