LeetCode刷题:675. 为高尔夫比赛砍树(JAVA代码详解)

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~

发布了619 篇原创文章 · 获赞 185 · 访问量 66万+

猜你喜欢

转载自blog.csdn.net/seagal890/article/details/100908986
今日推荐