法1:DFS|顺流(从陆地到海洋)
想法:
- 遍历每一块陆地
- 对于某陆地:
- 进行DFS,符合下列条件则可达:
1)比当前陆地低/相等的陆地
2)上下左右相邻陆地 - 对可达陆地进行标记
- 标记结束之后:遍历上下左右边界,左上边界有标记则可达太平洋,右下边界可达大西洋
- 可达太平洋和大西洋,则存下该陆地坐标
- 另用以矩阵保存标记
/** * @param {number[][]} matrix * @return {number[][]} */
var pacificAtlantic = function(matrix) {
if(matrix.length == 0) {
return [];
}
var output = []; // 输出,存所求陆地坐标
var temp = [], temp1 = []; // temp为标记;temp1作用:方便标记;true可达,false不可达
var i = 0, j = 0, k = 0, l = 0; // 用于遍历
// 后续多次求以下两值,存在两个变量中,耗时更短
var row = matrix.length, column = matrix[0].length;
// temp:标记;矩阵matrix相应位置为false,不可达;为true,可达
for(i = 0; i < row; i++) {
for(j = 0; j < column; j++) {
temp1[temp1.length] = false;
}
temp.push(temp1);
temp1 = [];
}
for(i = 0; i < row; i++) {
for(j = 0; j < column; j++) {
dfs(matrix, i, j, temp);
if(arrived(temp)) { // arrived()检验标记结束之后的temp
output[output.length] = [i, j];
}
temp = [];
for(k = 0; k < row; k++) {
for(l = 0; l < column; l++) {
temp1[temp1.length] = false;
}
temp.push(temp1);
temp1 = [];
}
}
}
return output;
};
function dfs(matrix, r, c, temp) {
var i = 0, j = 0;
temp[r][c] = true; // 标记
for(i = -1; i < 2; i++) {
for(j = -1; j < 2; j++) {
if(i == j || i * j == -1) { // 只访问上下左右
continue;
}
if(r + i < 0 || r + i >= matrix.length ||
c + j < 0 || c + j >= matrix[0].length) { // 下标越界则continue
continue;
}
if((!temp[r + i][c + j]) &&
(matrix[r + i][c + j] <= matrix[r][c])) {
dfs(matrix, r + i, c + j, temp);
}
}
}
}
function arrived(temp) {
var i = 0, row = temp.length, column = temp[0].length;
var pacific = false, atlantic = false;
for(i = 0; i < column; i++) {
if(temp[0][i]) { // 上边界
pacific = true;
}
if(temp[row - 1][i]) { // 下边界
atlantic = true;
}
}
for(i = 0; i < row; i++) {
if(temp[i][0]) { // 左边界
pacific = true;
}
if(temp[i][column - 1]) { // 右边界
atlantic = true;
}
}
return pacific && atlantic; // 返回是否可达太平洋和大西洋
}
法2:DFS|逆流(从海洋到陆地)
-看了看题解,发现从边界到陆地可行。
想法:
- 从边界到中央:遍历边界陆地
- 上左边界为太平洋,从两边界开始遍历,得到矩阵 pacific:
- 进行DFS,符合下列条件则可达:
1)比当前陆地高/相等的陆地
2)上下左右相邻陆地 - 对可达陆地进行标记:true可达,false不可达
- 下右边界为大西洋,从两边界开始遍历,得到矩阵 atlantic(同2)
- 标记结束之后:遍历pacific和atlantic矩阵,同为true的坐标则存下
/** * @param {number[][]} matrix * @return {number[][]} */
var pacificAtlantic = function(matrix) {
// 法2 从边界到中央
// 上左边界为太平洋,从两边界开始遍历,得到矩阵 pacific
// 下右边界为大西洋,从两边界开始遍历,得到矩阵 atlantic
// 取pacific和atlantic的交集,即答案
if(matrix.length == 0) {
return [];
}
var pacific = [], atlantic = [], temp = [], output = [];
var i = 0, j = 0, row = matrix.length, column = matrix[0].length;
for(i = 0; i < row; i++) {
for(j = 0; j < column; j++) {
temp[temp.length] = false;
}
pacific[pacific.length] = temp; // 是否可达大平洋
temp = [];
}
for(i = 0; i < row; i++) {
for(j = 0; j < column; j++) {
temp[temp.length] = false;
}
atlantic[atlantic.length] = temp; // 是否可达大西洋
temp = [];
}
for(i = 0; i < row; i++) { // 左右边界
dfs(matrix, i, 0, pacific);
dfs(matrix, i, column - 1, atlantic);
}
for(i = 0; i < column; i++) { // 上下边界
dfs(matrix, 0, i, pacific);
dfs(matrix, row - 1, i, atlantic);
}
for(i = 0; i < row; i++) {
for(j = 0; j < column; j++) {
if(pacific[i][j] && atlantic[i][j]) {
output[output.length] = [i, j];
}
}
}
return output;
};
function dfs(matric, r, c, arrived) {
arrived[r][c] = true;
var i = 0, j = 0;
for(i = -1; i < 2; i++) {
for(j = -1; j < 2; j++) {
if(i == j || i * j == -1) {
continue;
}
if(r + i < 0 || r + i >= matric.length || c + j < 0
|| c + j >= matric[0].length) {
continue;
}
if(!arrived[r + i][c + j] &&
(matric[r + i][c + j] >= matric[r][c])) {
dfs(matric, r + i, c + j, arrived);
}
}
}
}