vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights) {
int rows = heights.size(), cols = heights[0].size();
auto flows = [&](int sr, int sc) -> bool {
bool pacific = false, atlantic = false;
set<int> seen = {sr * cols + sc};
vector<pair<int, int>> stack = {{sr, sc}};
while (!stack.empty()) {
auto [r, c] = stack.back(); stack.pop_back();
if (r == 0 || c == 0) pacific = true;
if (r == rows - 1 || c == cols - 1) atlantic = true;
int dirs[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
for (auto& d : dirs) {
int nr = r + d[0], nc = c + d[1];
if (nr < 0 || nc < 0 || nr >= rows || nc >= cols) continue;
if (heights[nr][nc] > heights[r][c] || seen.count(nr * cols + nc)) continue;
seen.insert(nr * cols + nc);
stack.push_back({nr, nc});
}
}
return pacific && atlantic;
};
vector<vector<int>> result;
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
if (flows(r, c)) result.push_back({r, c});
}
}
return result;
}
public List<List<Integer>> pacificAtlantic(int[][] heights) {
int rows = heights.length, cols = heights[0].length;
List<List<Integer>> result = new ArrayList<>();
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
if (flows(heights, r, c)) result.add(Arrays.asList(r, c));
}
}
return result;
}
private boolean flows(int[][] heights, int sr, int sc) {
int rows = heights.length, cols = heights[0].length;
boolean pacific = false, atlantic = false;
Set<Integer> seen = new HashSet<>(); seen.add(sr * cols + sc);
Deque<int[]> stack = new ArrayDeque<>(); stack.push(new int[]{sr, sc});
int[][] dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
while (!stack.isEmpty()) {
int[] cell = stack.pop(); int r = cell[0], c = cell[1];
if (r == 0 || c == 0) pacific = true;
if (r == rows - 1 || c == cols - 1) atlantic = true;
for (int[] d : dirs) {
int nr = r + d[0], nc = c + d[1];
if (nr < 0 || nc < 0 || nr >= rows || nc >= cols) continue;
if (heights[nr][nc] > heights[r][c] || seen.contains(nr * cols + nc)) continue;
seen.add(nr * cols + nc);
stack.push(new int[]{nr, nc});
}
}
return pacific && atlantic;
}
def pacific_atlantic(heights):
rows, cols = len(heights), len(heights[0])
def flows(sr, sc):
pacific = atlantic = False
seen = {sr * cols + sc}
stack = [(sr, sc)]
while stack:
r, c = stack.pop()
if r == 0 or c == 0: pacific = True
if r == rows - 1 or c == cols - 1: atlantic = True
for dr, dc in ((1, 0), (-1, 0), (0, 1), (0, -1)):
nr, nc = r + dr, c + dc
if nr < 0 or nc < 0 or nr >= rows or nc >= cols: continue
if heights[nr][nc] > heights[r][c] or nr * cols + nc in seen: continue
seen.add(nr * cols + nc)
stack.append((nr, nc))
return pacific and atlantic
result = []
for r in range(rows):
for c in range(cols):
if flows(r, c): result.append([r, c])
return result
function pacificAtlantic(heights: number[][]): number[][] {
const rows = heights.length, cols = heights[0].length;
const flows = (sr: number, sc: number): boolean => {
let pacific = false, atlantic = false;
const seen = new Set<number>([sr * cols + sc]);
const stack: number[][] = [[sr, sc]];
while (stack.length > 0) {
const [r, c] = stack.pop()!;
if (r === 0 || c === 0) pacific = true;
if (r === rows - 1 || c === cols - 1) atlantic = true;
for (const [dr, dc] of [[1, 0], [-1, 0], [0, 1], [0, -1]]) {
const nr = r + dr, nc = c + dc;
if (nr < 0 || nc < 0 || nr >= rows || nc >= cols) continue;
if (heights[nr][nc] > heights[r][c] || seen.has(nr * cols + nc)) continue;
seen.add(nr * cols + nc);
stack.push([nr, nc]);
}
}
return pacific && atlantic;
};
const result: number[][] = [];
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
if (flows(r, c)) result.push([r, c]);
}
}
return result;
}
vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights) {
int rows = heights.size(), cols = heights[0].size();
int dirs[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
auto bfs = [&](const vector<pair<int, int>>& starts) {
vector<vector<bool>> reach(rows, vector<bool>(cols, false));
vector<pair<int, int>> queue;
for (auto [r, c] : starts) {
reach[r][c] = true;
queue.push_back({r, c});
}
size_t head = 0;
while (head < queue.size()) {
auto [r, c] = queue[head++];
for (auto& d : dirs) {
int nr = r + d[0], nc = c + d[1];
if (nr < 0 || nc < 0 || nr >= rows || nc >= cols) continue;
if (reach[nr][nc] || heights[nr][nc] < heights[r][c]) continue;
reach[nr][nc] = true;
queue.push_back({nr, nc});
}
}
return reach;
};
vector<pair<int, int>> pacificStarts, atlanticStarts;
for (int r = 0; r < rows; r++) {
pacificStarts.push_back({r, 0});
atlanticStarts.push_back({r, cols - 1});
}
for (int c = 0; c < cols; c++) {
pacificStarts.push_back({0, c});
atlanticStarts.push_back({rows - 1, c});
}
auto pacific = bfs(pacificStarts), atlantic = bfs(atlanticStarts);
vector<vector<int>> result;
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
if (pacific[r][c] && atlantic[r][c]) result.push_back({r, c});
}
}
return result;
}
public List<List<Integer>> pacificAtlantic(int[][] heights) {
int rows = heights.length, cols = heights[0].length;
List<int[]> pacificStarts = new ArrayList<>(), atlanticStarts = new ArrayList<>();
for (int r = 0; r < rows; r++) {
pacificStarts.add(new int[]{r, 0});
atlanticStarts.add(new int[]{r, cols - 1});
}
for (int c = 0; c < cols; c++) {
pacificStarts.add(new int[]{0, c});
atlanticStarts.add(new int[]{rows - 1, c});
}
boolean[][] pacific = bfs(heights, pacificStarts), atlantic = bfs(heights, atlanticStarts);
List<List<Integer>> result = new ArrayList<>();
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
if (pacific[r][c] && atlantic[r][c]) result.add(Arrays.asList(r, c));
}
}
return result;
}
private boolean[][] bfs(int[][] heights, List<int[]> starts) {
int rows = heights.length, cols = heights[0].length;
int[][] dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
boolean[][] reach = new boolean[rows][cols];
List<int[]> queue = new ArrayList<>();
for (int[] s : starts) {
reach[s[0]][s[1]] = true;
queue.add(new int[]{s[0], s[1]});
}
int head = 0;
while (head < queue.size()) {
int[] cell = queue.get(head++); int r = cell[0], c = cell[1];
for (int[] d : dirs) {
int nr = r + d[0], nc = c + d[1];
if (nr < 0 || nc < 0 || nr >= rows || nc >= cols) continue;
if (reach[nr][nc] || heights[nr][nc] < heights[r][c]) continue;
reach[nr][nc] = true;
queue.add(new int[]{nr, nc});
}
}
return reach;
}
def pacific_atlantic(heights):
rows, cols = len(heights), len(heights[0])
def bfs(starts):
reach = [[False] * cols for _ in range(rows)]
queue = []
for r, c in starts:
reach[r][c] = True
queue.append((r, c))
head = 0
while head < len(queue):
r, c = queue[head]
head += 1
for dr, dc in ((1, 0), (-1, 0), (0, 1), (0, -1)):
nr, nc = r + dr, c + dc
if nr < 0 or nc < 0 or nr >= rows or nc >= cols: continue
if reach[nr][nc] or heights[nr][nc] < heights[r][c]: continue
reach[nr][nc] = True
queue.append((nr, nc))
return reach
pacific_starts, atlantic_starts = [], []
for r in range(rows):
pacific_starts.append((r, 0))
atlantic_starts.append((r, cols - 1))
for c in range(cols):
pacific_starts.append((0, c))
atlantic_starts.append((rows - 1, c))
pacific, atlantic = bfs(pacific_starts), bfs(atlantic_starts)
result = []
for r in range(rows):
for c in range(cols):
if pacific[r][c] and atlantic[r][c]: result.append([r, c])
return result
function pacificAtlantic(heights: number[][]): number[][] {
const rows = heights.length, cols = heights[0].length;
const bfs = (starts: number[][]): boolean[][] => {
const reach = Array.from({ length: rows }, () => new Array<boolean>(cols).fill(false));
const queue: number[][] = [];
for (const [r, c] of starts) {
reach[r][c] = true;
queue.push([r, c]);
}
let head = 0;
while (head < queue.length) {
const [r, c] = queue[head++];
for (const [dr, dc] of [[1, 0], [-1, 0], [0, 1], [0, -1]]) {
const nr = r + dr, nc = c + dc;
if (nr < 0 || nc < 0 || nr >= rows || nc >= cols) continue;
if (reach[nr][nc] || heights[nr][nc] < heights[r][c]) continue;
reach[nr][nc] = true;
queue.push([nr, nc]);
}
}
return reach;
};
const pacificStarts: number[][] = [], atlanticStarts: number[][] = [];
for (let r = 0; r < rows; r++) {
pacificStarts.push([r, 0]);
atlanticStarts.push([r, cols - 1]);
}
for (let c = 0; c < cols; c++) {
pacificStarts.push([0, c]);
atlanticStarts.push([rows - 1, c]);
}
const pacific = bfs(pacificStarts), atlantic = bfs(atlanticStarts);
const result: number[][] = [];
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
if (pacific[r][c] && atlantic[r][c]) result.push([r, c]);
}
}
return result;
}
vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights) {
int rows = heights.size(), cols = heights[0].size();
vector<vector<bool>> pacific(rows, vector<bool>(cols, false));
vector<vector<bool>> atlantic(rows, vector<bool>(cols, false));
function<void(int, int, vector<vector<bool>>&, int)> dfs = [&](int r, int c, vector<vector<bool>>& reach, int prev) {
if (r < 0 || c < 0 || r >= rows || c >= cols) return;
if (reach[r][c] || heights[r][c] < prev) return;
reach[r][c] = true;
dfs(r + 1, c, reach, heights[r][c]);
dfs(r - 1, c, reach, heights[r][c]);
dfs(r, c + 1, reach, heights[r][c]);
dfs(r, c - 1, reach, heights[r][c]);
};
for (int r = 0; r < rows; r++) {
dfs(r, 0, pacific, 0);
dfs(r, cols - 1, atlantic, 0);
}
for (int c = 0; c < cols; c++) {
dfs(0, c, pacific, 0);
dfs(rows - 1, c, atlantic, 0);
}
vector<vector<int>> result;
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
if (pacific[r][c] && atlantic[r][c]) result.push_back({r, c});
}
}
return result;
}
public List<List<Integer>> pacificAtlantic(int[][] heights) {
int rows = heights.length, cols = heights[0].length;
boolean[][] pacific = new boolean[rows][cols];
boolean[][] atlantic = new boolean[rows][cols];
for (int r = 0; r < rows; r++) {
dfs(heights, r, 0, pacific, 0);
dfs(heights, r, cols - 1, atlantic, 0);
}
for (int c = 0; c < cols; c++) {
dfs(heights, 0, c, pacific, 0);
dfs(heights, rows - 1, c, atlantic, 0);
}
List<List<Integer>> result = new ArrayList<>();
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
if (pacific[r][c] && atlantic[r][c]) result.add(Arrays.asList(r, c));
}
}
return result;
}
private void dfs(int[][] heights, int r, int c, boolean[][] reach, int prev) {
if (r < 0 || c < 0 || r >= heights.length || c >= heights[0].length) return;
if (reach[r][c] || heights[r][c] < prev) return;
reach[r][c] = true;
dfs(heights, r + 1, c, reach, heights[r][c]);
dfs(heights, r - 1, c, reach, heights[r][c]);
dfs(heights, r, c + 1, reach, heights[r][c]);
dfs(heights, r, c - 1, reach, heights[r][c]);
}
def pacific_atlantic(heights):
rows, cols = len(heights), len(heights[0])
pacific = [[False] * cols for _ in range(rows)]
atlantic = [[False] * cols for _ in range(rows)]
def dfs(r, c, reach, prev):
if r < 0 or c < 0 or r >= rows or c >= cols: return
if reach[r][c] or heights[r][c] < prev: return
reach[r][c] = True
dfs(r + 1, c, reach, heights[r][c])
dfs(r - 1, c, reach, heights[r][c])
dfs(r, c + 1, reach, heights[r][c])
dfs(r, c - 1, reach, heights[r][c])
for r in range(rows):
dfs(r, 0, pacific, 0)
dfs(r, cols - 1, atlantic, 0)
for c in range(cols):
dfs(0, c, pacific, 0)
dfs(rows - 1, c, atlantic, 0)
result = []
for r in range(rows):
for c in range(cols):
if pacific[r][c] and atlantic[r][c]: result.append([r, c])
return result
function pacificAtlantic(heights: number[][]): number[][] {
const rows = heights.length, cols = heights[0].length;
const pacific = Array.from({ length: rows }, () => new Array<boolean>(cols).fill(false));
const atlantic = Array.from({ length: rows }, () => new Array<boolean>(cols).fill(false));
const dfs = (r: number, c: number, reach: boolean[][], prev: number): void => {
if (r < 0 || c < 0 || r >= rows || c >= cols) return;
if (reach[r][c] || heights[r][c] < prev) return;
reach[r][c] = true;
dfs(r + 1, c, reach, heights[r][c]);
dfs(r - 1, c, reach, heights[r][c]);
dfs(r, c + 1, reach, heights[r][c]);
dfs(r, c - 1, reach, heights[r][c]);
};
for (let r = 0; r < rows; r++) {
dfs(r, 0, pacific, 0);
dfs(r, cols - 1, atlantic, 0);
}
for (let c = 0; c < cols; c++) {
dfs(0, c, pacific, 0);
dfs(rows - 1, c, atlantic, 0);
}
const result: number[][] = [];
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
if (pacific[r][c] && atlantic[r][c]) result.push([r, c]);
}
}
return result;
}
vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights) {
int rows = heights.size(), cols = heights[0].size();
vector<unsigned char> flags(rows * cols, 0);
auto fill = [&](const vector<int>& starts, int bit) {
vector<int> stack;
for (int s : starts) {
flags[s] |= bit;
stack.push_back(s);
}
while (!stack.empty()) {
int cell = stack.back(); stack.pop_back();
int r = cell / cols, c = cell % cols;
int h = heights[r][c];
if (r > 0 && !(flags[cell - cols] & bit) && heights[r - 1][c] >= h) {
flags[cell - cols] |= bit;
stack.push_back(cell - cols);
}
if (r + 1 < rows && !(flags[cell + cols] & bit) && heights[r + 1][c] >= h) {
flags[cell + cols] |= bit;
stack.push_back(cell + cols);
}
if (c > 0 && !(flags[cell - 1] & bit) && heights[r][c - 1] >= h) {
flags[cell - 1] |= bit;
stack.push_back(cell - 1);
}
if (c + 1 < cols && !(flags[cell + 1] & bit) && heights[r][c + 1] >= h) {
flags[cell + 1] |= bit;
stack.push_back(cell + 1);
}
}
};
vector<int> pacific, atlantic;
for (int r = 0; r < rows; r++) {
pacific.push_back(r * cols);
atlantic.push_back(r * cols + cols - 1);
}
for (int c = 0; c < cols; c++) {
pacific.push_back(c);
atlantic.push_back((rows - 1) * cols + c);
}
fill(pacific, 1);
fill(atlantic, 2);
vector<vector<int>> result;
for (int i = 0; i < rows * cols; i++) {
if (flags[i] == 3) result.push_back({i / cols, i % cols});
}
return result;
}
public List<List<Integer>> pacificAtlantic(int[][] heights) {
int rows = heights.length, cols = heights[0].length;
byte[] flags = new byte[rows * cols];
List<Integer> pacific = new ArrayList<>(), atlantic = new ArrayList<>();
for (int r = 0; r < rows; r++) {
pacific.add(r * cols);
atlantic.add(r * cols + cols - 1);
}
for (int c = 0; c < cols; c++) {
pacific.add(c);
atlantic.add((rows - 1) * cols + c);
}
fill(heights, flags, pacific, 1);
fill(heights, flags, atlantic, 2);
List<List<Integer>> result = new ArrayList<>();
for (int i = 0; i < rows * cols; i++) {
if (flags[i] == 3) result.add(Arrays.asList(i / cols, i % cols));
}
return result;
}
private void fill(int[][] heights, byte[] flags, List<Integer> starts, int bit) {
int rows = heights.length, cols = heights[0].length;
Deque<Integer> stack = new ArrayDeque<>();
for (int s : starts) {
flags[s] |= bit;
stack.push(s);
}
while (!stack.isEmpty()) {
int cell = stack.pop();
int r = cell / cols, c = cell % cols;
int h = heights[r][c];
if (r > 0 && (flags[cell - cols] & bit) == 0 && heights[r - 1][c] >= h) {
flags[cell - cols] |= bit;
stack.push(cell - cols);
}
if (r + 1 < rows && (flags[cell + cols] & bit) == 0 && heights[r + 1][c] >= h) {
flags[cell + cols] |= bit;
stack.push(cell + cols);
}
if (c > 0 && (flags[cell - 1] & bit) == 0 && heights[r][c - 1] >= h) {
flags[cell - 1] |= bit;
stack.push(cell - 1);
}
if (c + 1 < cols && (flags[cell + 1] & bit) == 0 && heights[r][c + 1] >= h) {
flags[cell + 1] |= bit;
stack.push(cell + 1);
}
}
}
def pacific_atlantic(heights):
rows, cols = len(heights), len(heights[0])
flags = [0] * (rows * cols)
def fill(starts, bit):
stack = []
for s in starts:
flags[s] |= bit
stack.append(s)
while stack:
cell = stack.pop()
r, c = divmod(cell, cols)
h = heights[r][c]
if r > 0 and not flags[cell - cols] & bit and heights[r - 1][c] >= h:
flags[cell - cols] |= bit
stack.append(cell - cols)
if r + 1 < rows and not flags[cell + cols] & bit and heights[r + 1][c] >= h:
flags[cell + cols] |= bit
stack.append(cell + cols)
if c > 0 and not flags[cell - 1] & bit and heights[r][c - 1] >= h:
flags[cell - 1] |= bit
stack.append(cell - 1)
if c + 1 < cols and not flags[cell + 1] & bit and heights[r][c + 1] >= h:
flags[cell + 1] |= bit
stack.append(cell + 1)
pacific, atlantic = [], []
for r in range(rows):
pacific.append(r * cols)
atlantic.append(r * cols + cols - 1)
for c in range(cols):
pacific.append(c)
atlantic.append((rows - 1) * cols + c)
fill(pacific, 1)
fill(atlantic, 2)
result = []
for i in range(rows * cols):
if flags[i] == 3: result.append([i // cols, i % cols])
return result
function pacificAtlantic(heights: number[][]): number[][] {
const rows = heights.length, cols = heights[0].length;
const flags = new Uint8Array(rows * cols);
const fill = (starts: number[], bit: number): void => {
const stack: number[] = [];
for (const s of starts) {
flags[s] |= bit;
stack.push(s);
}
while (stack.length > 0) {
const cell = stack.pop()!;
const r = Math.floor(cell / cols), c = cell % cols;
const h = heights[r][c];
if (r > 0 && !(flags[cell - cols] & bit) && heights[r - 1][c] >= h) {
flags[cell - cols] |= bit;
stack.push(cell - cols);
}
if (r + 1 < rows && !(flags[cell + cols] & bit) && heights[r + 1][c] >= h) {
flags[cell + cols] |= bit;
stack.push(cell + cols);
}
if (c > 0 && !(flags[cell - 1] & bit) && heights[r][c - 1] >= h) {
flags[cell - 1] |= bit;
stack.push(cell - 1);
}
if (c + 1 < cols && !(flags[cell + 1] & bit) && heights[r][c + 1] >= h) {
flags[cell + 1] |= bit;
stack.push(cell + 1);
}
}
};
const pacific: number[] = [], atlantic: number[] = [];
for (let r = 0; r < rows; r++) {
pacific.push(r * cols);
atlantic.push(r * cols + cols - 1);
}
for (let c = 0; c < cols; c++) {
pacific.push(c);
atlantic.push((rows - 1) * cols + c);
}
fill(pacific, 1);
fill(atlantic, 2);
const result: number[][] = [];
for (let i = 0; i < rows * cols; i++) {
if (flags[i] === 3) result.push([Math.floor(i / cols), i % cols]);
}
return result;
}