Mutating counts without cleanup
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.
Build confidence with an intuition-first walkthrough focused on hash map fundamentals.
Given a string path, where path[i] = 'N', 'S', 'E' or 'W', each representing moving one unit north, south, east, or west, respectively. You start at the origin (0, 0) on a 2D plane and walk on the path specified by path.
Return true if the path crosses itself at any point, that is, if at any time you are on a location you have previously visited. Return false otherwise.
Example 1:
Input: path = "NES" Output: false Explanation: Notice that the path doesn't cross any point more than once.
Example 2:
Input: path = "NESWW" Output: true Explanation: Notice that the path visits the origin twice.
Constraints:
1 <= path.length <= 104path[i] is either 'N', 'S', 'E', or 'W'.Problem summary: Given a string path, where path[i] = 'N', 'S', 'E' or 'W', each representing moving one unit north, south, east, or west, respectively. You start at the origin (0, 0) on a 2D plane and walk on the path specified by path. Return true if the path crosses itself at any point, that is, if at any time you are on a location you have previously visited. Return false otherwise.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Hash Map
"NES"
"NESWW"
Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #1496: Path Crossing
class Solution {
public boolean isPathCrossing(String path) {
int i = 0, j = 0;
Set<Integer> vis = new HashSet<>();
vis.add(0);
for (int k = 0, n = path.length(); k < n; ++k) {
switch (path.charAt(k)) {
case 'N' -> --i;
case 'S' -> ++i;
case 'E' -> ++j;
case 'W' -> --j;
}
int t = i * 20000 + j;
if (!vis.add(t)) {
return true;
}
}
return false;
}
}
// Accepted solution for LeetCode #1496: Path Crossing
func isPathCrossing(path string) bool {
i, j := 0, 0
vis := map[int]bool{0: true}
for _, c := range path {
switch c {
case 'N':
i--
case 'S':
i++
case 'E':
j++
case 'W':
j--
}
if vis[i*20000+j] {
return true
}
vis[i*20000+j] = true
}
return false
}
# Accepted solution for LeetCode #1496: Path Crossing
class Solution:
def isPathCrossing(self, path: str) -> bool:
i = j = 0
vis = {(0, 0)}
for c in path:
match c:
case 'N':
i -= 1
case 'S':
i += 1
case 'E':
j += 1
case 'W':
j -= 1
if (i, j) in vis:
return True
vis.add((i, j))
return False
// Accepted solution for LeetCode #1496: Path Crossing
struct Solution;
use std::collections::HashSet;
impl Solution {
fn is_path_crossing(path: String) -> bool {
let mut hs: HashSet<(i32, i32)> = HashSet::new();
hs.insert((0, 0));
let mut x = 0;
let mut y = 0;
for c in path.chars() {
match c {
'N' => {
y += 1;
}
'S' => {
y -= 1;
}
'E' => {
x += 1;
}
_ => {
x -= 1;
}
}
if !hs.insert((x, y)) {
return true;
}
}
false
}
}
#[test]
fn test() {
let path = "NES".to_string();
let res = false;
assert_eq!(Solution::is_path_crossing(path), res);
let path = "NESWW".to_string();
let res = true;
assert_eq!(Solution::is_path_crossing(path), res);
}
// Accepted solution for LeetCode #1496: Path Crossing
function isPathCrossing(path: string): boolean {
let [i, j] = [0, 0];
const vis: Set<number> = new Set();
vis.add(0);
for (const c of path) {
if (c === 'N') {
--i;
} else if (c === 'S') {
++i;
} else if (c === 'E') {
++j;
} else if (c === 'W') {
--j;
}
const t = i * 20000 + j;
if (vis.has(t)) {
return true;
}
vis.add(t);
}
return false;
}
Use this to step through a reusable interview workflow for this problem.
For each element, scan the rest of the array looking for a match. Two nested loops give n × (n−1)/2 comparisons = O(n²). No extra space since we only use loop indices.
One pass through the input, performing O(1) hash map lookups and insertions at each step. The hash map may store up to n entries in the worst case. This is the classic space-for-time tradeoff: O(n) extra memory eliminates an inner loop.
Review these before coding to avoid predictable interview regressions.
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.