Question

link

给一个矩阵,其中 0 代表海洋,其他数字代表高度,秉着水往低处流的原则,求出能够流向任意海洋的点。 比如说

0 0 0 1 2 3 0
0 1 2 2 4 3 2
2 1 1 3 3 2 0
0 3 3 3 2 3 3

那么就要给出 第二行的 4 (这有这点出发,能够找到连通道四个 0 的区域的一条非递增
路线
),当然也有可能找不到这样的点,或者找到多个点。

Solution

I read online and the best solution I come up with is Brute Force. I did not really understand the online discussions.

So if you are reading this and want to discuss with me, kindly leave me a comment!

Code

brute force

public void findSuperPeak(int[][] map) {
	int m = map.length;
	int n = map[0].length;
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < n; j++) {
			if (check(map, new Pair(i, j), m, n)) {
				System.out.println("Found point (" + i + ", " + j
						+ ") with height of " + map[i][j]);
			}
		}
	}
}

private boolean check(int[][] originalMap, Pair p, int m, int n) {
	// check if point can flow to all oceans
	if (originalMap[p.x][p.y] == 0) {
		return false;
	}

	int[][] map = new int[m][n];
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < n; j++) {
			map[i][j] = originalMap[i][j];
		}
	}

	Queue<Pair> q = new LinkedList<Pair>();
	q.offer(p);

	while (!q.isEmpty()) {
		Pair top = q.poll();
		int x = top.x;
		int y = top.y;
		if (map[x][y] == -1) {
			continue;
		}
		// add neighbor nodes who are visitable from here
		if (x - 1 >= 0 && map[x - 1][y] <= map[x][y]) {
			// water can flow from:
			// 1. high altitude to lower
			// 2. from ocean to ocean
			q.offer(new Pair(x - 1, y));
		}
		if (x + 1 < m && map[x + 1][y] <= map[x][y]) {
			q.offer(new Pair(x + 1, y));
		}
		if (y - 1 >= 0 && map[x][y - 1] <= map[x][y]) {
			q.offer(new Pair(x, y - 1));
		}
		if (y + 1 < n && map[x][y + 1] <= map[x][y]) {
			q.offer(new Pair(x, y + 1));
		}

		// visit this point
		map[x][y] = -1;
	}

	// now we finished BFS and the entire map with lower altitude is visited
	// (including all ocean points). We now check if there exists a 0 in map
	for (int[] arr : map)
		for (int i : arr)
			if (i == 0) // found an unvisited ocean point
				return false;
	return true;
}