【Leetcode】675. Cut Off Trees for Golf Event

题目地址:

https://leetcode.com/problems/cut-off-trees-for-golf-event/

给定一个 m × n m\times n m×n的二维矩阵 A A A 0 0 0表示障碍物, 1 1 1表示空地,大于 1 1 1的数表示要砍掉的树的高度。一开始从 ( 0 , 0 ) (0,0) (0,0)开始出发,每次只能走到非 0 0 0的位置,并且要按照树的高度从小到大依次走到每一个树将其砍掉。问总共至少要走多少步。如果某棵树走不到,则直接返回 − 1 -1 1

可以先将所有的树的位置连同其高度存进一个最小堆,然后依次pop堆顶,接着用BFS求一下从当前位置走到这棵树的最短路,累加步数即可。如果发现走不到,则直接返回 − 1 -1 1。代码如下:

import java.util.*;

public class Solution {
    public int cutOffTree(List<List<Integer>> forest) {
        int m = forest.size(), n = forest.get(0).size();
        // 第一维存高度,后面两维存树的坐标
        PriorityQueue<int[]> minHeap = new PriorityQueue<>((x, y) -> Integer.compare(x[0], y[0]));
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                int h = forest.get(i).get(j);
                if (h > 1) {
                    minHeap.offer(new int[]{h, i, j});
                }
            }
        }
        
        int res = 0;
        int[] cur = {forest.get(0).get(0), 0, 0};
        while (!minHeap.isEmpty()) {
            int[] next = minHeap.poll();
            int steps = bfs(cur, next, forest);
            if (steps == -1) {
                return -1;
            }
            
            res += steps;
            cur = next;
        }
        
        return res;
    }
    
    private int bfs(int[] cur, int[] next, List<List<Integer>> forest) {
        if (Arrays.equals(cur, next)) {
            return 0;
        }
        
        int m = forest.size(), n = forest.get(0).size();
        int[] d = {1, 0, -1, 0, 1};
        Queue<int[]> queue = new LinkedList<>();
        queue.offer(cur);
        boolean[][] vis = new boolean[m][n];
        vis[cur[1]][cur[2]] = true;
        
        int res = 0;
        while (!queue.isEmpty()) {
            res++;
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                cur = queue.poll();
                for (int j = 0; j < 4; j++) {
                    int nextX = cur[1] + d[j], nextY = cur[2] + d[j + 1];
                    if (0 <= nextX && nextX < m && 0 <= nextY && nextY < n) {
                        if (nextX == next[1] && nextY == next[2]) {
                            return res;
                        }
    
                        int h = forest.get(nextX).get(nextY);
                        if (h >= 1 && !vis[nextX][nextY]) {
                            queue.offer(new int[]{h, nextX, nextY});
                            vis[nextX][nextY] = true;
                        }
                    }
                }
            }
        }
        
        return -1;
    }
}

时间复杂度 O ( k ( m n + log ⁡ k ) ) O(k(mn+\log k)) O(k(mn+logk)),空间 O ( k + m n ) O(k+mn) O(k+mn) k k k是树的个数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值