【Leetcode】1765. Map of Highest Peak

题目地址:

https://leetcode.com/problems/map-of-highest-peak/

给定一个 m × n m\times n m×n 0 − 1 0-1 01矩阵 A A A,要求构造一个新的矩阵 C C C满足如下要求:
1、 C C C的所有元素都非负;
2、若 A [ i ] [ j ] = 1 A[i][j]=1 A[i][j]=1 C [ i ] [ j ] = 0 C[i][j]=0 C[i][j]=0
3、对于 C C C中相邻的元素,它们的差的绝对值最多是 1 1 1。这里的相邻指的是四相邻。
同时要求 C C C的最大值最大,求 C C C

其实只需要从 C [ i ] [ j ] = 0 C[i][j]=0 C[i][j]=0的位置做BFS即可,第一次接触的位置为它的前驱的数加 1 1 1。我们稍微说明一下正确性。首先如果某两个相邻格子元素之差大于 1 1 1了,比如 C [ x 1 ] [ y 1 ] > C [ x 2 ] [ y 2 ] + 1 C[x_1][y_1]> C[x_2][y_2]+1 C[x1][y1]>C[x2][y2]+1那么说明 ( x 1 , y 1 ) (x_1,y_1) (x1,y1)这个位置应该由 ( x 2 , y 2 ) (x_2,y_2) (x2,y2)这个位置扩展而来(因为 ( x 2 , y 2 ) (x_2,y_2) (x2,y2)入队之后下一层BFS就会拓展到 ( x 1 , y 1 ) (x_1,y_1) (x1,y1)),这就矛盾了,因为我们不允许同一个位置被BFS到两次。至于最大值最大这一点,可以反证法,如果某个位置的能达到更大值,那么考虑BFS树从树根走到这个位置的路径(可以想象树根是个虚拟节点),这个路径必然存在相邻两个位置差大于 1 1 1,矛盾。代码如下:

import java.util.LinkedList;
import java.util.Queue;

public class Solution {
    public int[][] highestPeak(int[][] A) {
        int m = A.length, n = A[0].length;
        Queue<int[]> queue = new LinkedList<>();
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (A[i][j] == 1) {
                    A[i][j] = 0;
                    queue.offer(new int[]{i, j});
                } else {
                    A[i][j] = -1;
                }
            }
        }
        
        int[] d = {1, 0, -1, 0, 1};
        
        for (int h = 1; !queue.isEmpty(); h++) {
            for (int i = queue.size() - 1; i >= 0; i--) {
                int[] cur = queue.poll();
                int x = cur[0], y = cur[1];
                for (int k = 0; k < 4; k++) {
                    int nextX = x + d[k], nextY = y + d[k + 1];
                    if (0 <= nextX && nextX < m && 0 <= nextY && nextY < n && A[nextX][nextY] == -1) {
                        A[nextX][nextY] = h;
                        queue.offer(new int[]{nextX, nextY});
                    }
                }
            }
        }
        
        return A;
    }
}

时空复杂度 O ( m n ) O(mn) O(mn)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值