-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Description
Bug Report for https://neetcode.io/problems/number-of-distinct-islands
Issue Description:
The current test cases for this problem on Neetcode.io are insufficient. They accept a DFS serialization solution that records only the forward movements (U, D, L, R) without recording backtracking steps or using delimiters.
Without recording the return path (backtracking), distinct island shapes can produce identical path strings, leading to false positives (collisions) where two different islands are counted as one.
Reproduction Steps:
Submit the solution below.
Observed Result: The solution is Accepted.
Expected Result: The solution should fail (Wrong Answer) because it cannot distinguish between specific distinct shapes.
Counter-Example (Why this is a bug): Consider two distinct island shapes starting at S:
Shape A: S -> Right -> Down (A line)
Path String: "RD"
Shape B: S -> Right, backtrack to S, then S -> Down (A corner/triangle)
Path String: "RD"
Without a backtracking character (e.g., 'B') or coordinate offsets, both shapes generate the signature "RD". The provided solution fails to distinguish these, yet passes the current test suite.
The Flawed Solution (Currently Accepted):
class Solution {
private:
void dfsPathHelper(vector<vector<int>> &grid, int row, int col, string &currPath) {
int m = grid.size(), n = grid[0].size();
vector<char> pathOptions{'U', 'R', 'D', 'L'};
vector<int> dx{1, 0, 0, -1}, dy{0, 1, -1, 0};
grid[row][col] = 0;
for(int i=0; i<4; ++i) {
int x = row + dx[i], y = col + dy[i];
if(x >= 0 and x < m and y >= 0 and y < n and grid[x][y] == 1) {
currPath.push_back(pathOptions[i]);
dfsPathHelper(grid, x, y, currPath);
// MISSING: currPath.push_back('B');
}
}
}
public:
int countDistinctIslands(vector<vector<int>>& grid) {
unordered_set<string> paths;
int m = grid.size(), n = grid[0].size();
for(int i=0; i<m; ++i) {
for(int j=0; j<n; ++j) {
if(grid[i][j]) {
string currPath{};
dfsPathHelper(grid, i, j, currPath);
paths.insert(currPath);
}
}
}
return paths.size();
}
};