675. 为高尔夫比赛砍树(JAVA代码详解)
你被请来给一个要举办高尔夫比赛的树林砍树. 树林由一个非负的二维数组表示, 在这个数组中:
0 表示障碍,无法触碰到.
1 表示可以行走的地面.
比1大的数 表示一颗允许走过的树的高度.
你被要求按照树的高度从低向高砍掉所有的树,每砍过一颗树,树的高度变为1。
你将从(0,0)点开始工作,你应该返回你砍完所有树需要走的最小步数。 如果你无法砍完所有的树,返回 -1 。
可以保证的是,没有两棵树的高度是相同的,并且至少有一颗树需要你砍。
示例 1:
输入:
[
[1,2,3],
[0,0,4],
[7,6,5]
]
输出: 6
示例 2:
输入:
[
[1,2,3],
[0,0,0],
[7,6,5]
]
输出: -1
示例 3:
输入:
[
[2,3,4],
[0,0,5],
[8,7,6]
]
输出: 6
解释: (0,0) 位置的树,你可以直接砍去,不用算步数
提示: 矩阵大小不会超过 50x50 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/cut-off-trees-for-golf-event
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
算法实现
package com.bean.leetcode;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;
public class Solution675_2 {
int row, col;
public int cutOffTree(List<List<Integer>> forest) {
// 先遍历矩阵,找到所有需要砍的树的位置,保存在最小堆中,按树高排序
// 建堆
PriorityQueue<int[]> minHeap = new PriorityQueue<>(new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return forest.get(o1[0]).get(o1[1]) - forest.get(o2[0]).get(o2[1]);
}
});
// 找到所有需要砍的树的位置
if (forest == null)
return 0;
row = forest.size();
if (row == 0)
return 0;
col = forest.get(0).size();
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (forest.get(i).get(j) > 1)
minHeap.add(new int[] { i, j });
}
}
// 开始从小砍到大
int count = 0;
int[] begin = new int[] { 0, 0 };
while (!minHeap.isEmpty()) {
int[] end = minHeap.poll();
int temp = cutOffTree(forest, begin, end, new int[row][col]);
if (temp == -1)
return -1;
count += temp;
begin = end;
}
return count;
}
/** 找到 begin -> end 的最短的路径,BFS
* @param forest >= 0 表示可以行走, 0 表示障碍
* @param begin 起始位置
* @param end 目标位置
* @return 最短的路径长度,原地 begin = end 为 0
*/
public int cutOffTree(List<List<Integer>> forest, int[] begin, int[] end, int[][] visited) {
if(end[0] == begin[0] && end[1] == begin[1]) return 0;
// BFS
Queue<int[]> queue = new LinkedList<>();
queue.add(begin);
int depth = 0;
while (!queue.isEmpty()) {
depth++;
for (int i = 0, len = queue.size(); i < len; i++) {
int[] pos = queue.poll();
// 再走一步
if(pos[0] > 0 && visited[pos[0] - 1][pos[1]] == 0) {
if(end[0] == pos[0] - 1 && end[1] == pos[1]) return depth;
if(forest.get(pos[0] - 1).get(pos[1]) != 0){
queue.add(new int[]{pos[0] - 1, pos[1]});
visited[pos[0] - 1][pos[1]] = 1;
}
}
if(pos[1] > 0 && visited[pos[0]][pos[1] - 1] == 0) {
if(end[0] == pos[0] && end[1] == pos[1] - 1) return depth;
if(forest.get(pos[0]).get(pos[1] - 1) != 0){
queue.add(new int[]{pos[0], pos[1] - 1});
visited[pos[0]][pos[1] - 1] = 1;
}
}
if(pos[0] + 1 < row && visited[pos[0] + 1][pos[1]] == 0) {
if(end[0] == pos[0] + 1 && end[1] == pos[1]) return depth;
if(forest.get(pos[0] + 1).get(pos[1]) != 0){
queue.add(new int[]{pos[0] + 1, pos[1]});
visited[pos[0] + 1][pos[1]] = 1;
}
}
if(pos[1] + 1 < col && visited[pos[0]][pos[1] + 1] == 0) {
if(end[0] == pos[0] && end[1] == pos[1] + 1) return depth;
if(forest.get(pos[0]).get(pos[1] + 1) != 0){
queue.add(new int[]{pos[0], pos[1] + 1});
visited[pos[0]][pos[1] + 1] = 1;
}
}
}
}
// 无法走到下一棵需要砍的树
return -1;
}
}
算法实现二
package com.bean.leetcode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
public class Solution675 {
int[][] dir = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };
public int cutOffTree(List<List<Integer>> forest) {
if (forest == null || forest.size() == 0)
return -1;
int m = forest.size(), n = forest.get(0).size(), res = 0;
// first step: sort the tree position based on its height
List<int[]> heights = new ArrayList<>();
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (forest.get(i).get(j) > 1)
heights.add(new int[] { forest.get(i).get(j), i, j });
}
}
Collections.sort(heights, new Comparator<int[]>() {
public int compare(int[] arr1, int[] arr2) {
return Integer.compare(arr1[0], arr2[0]);
}
});
// second step: accumulate the shortest steps between each two adajacent points
// in heights[].
int start_x = 0, start_y = 0;
for (int i = 0; i < heights.size(); i++) {
int cnt_steps = BFS(forest, m, n, start_x, start_y, heights.get(i)[1], heights.get(i)[2]);
if (cnt_steps == -1)
return -1;
res += cnt_steps;
start_x = heights.get(i)[1];
start_y = heights.get(i)[2];
}
return res;
}
public int BFS(List<List<Integer>> forest, int m, int n, int start_x, int start_y, int des_x, int des_y) {
if (start_x == des_x && start_y == des_y)
return 0;
int steps = 0;
Queue<int[]> q = new LinkedList<>();
q.add(new int[] { start_x, start_y });
int[][] visited = new int[m][n];
visited[start_x][start_y] = 1;
while (!q.isEmpty()) {
int qsize = q.size();
steps++;
while (qsize-- > 0) {
int[] cur = q.poll();
int cur_x = cur[0], cur_y = cur[1];
for (int k = 0; k < 4; k++) {
int x = cur_x + dir[k][0], y = cur_y + dir[k][1];
if (x >= 0 && x < m && y >= 0 && y < n && forest.get(x).get(y) > 0 && visited[x][y] == 0) {
if (x == des_x && y == des_y)
return steps;
visited[x][y] = 1;
q.add(new int[] { x, y });
}
}
}
}
return -1;
}
}
以上代码提交,都Accepted~