1496. Path Crossing - Explanation
Description
You are 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: falseExplanation: Notice that the path doesn't cross any point more than once.
Example 2:
Input: path = "NESWW"
Output: trueExplanation: Notice that the path visits the origin twice.
Constraints:
1 <= path.length <= 10,000- path[i] is either
'N','S','E', or'W'.
Topics
Prerequisites
Before attempting this problem, you should be comfortable with:
- Hash Set - Used for O(1) lookups to check if a coordinate has been visited
- Coordinate Systems - Understanding how to represent and track 2D positions
1. Hash Set
Intuition
We start at the origin and follow the path character by character. At each step, we move in the indicated direction. The path crosses itself if we visit a position we've been to before. A hash set provides O(1) lookups to check if a coordinate has been visited.
Algorithm
- Initialize a set
visitand add the starting position(0, 0). - Initialize coordinates
x = 0,y = 0. - For each character in the path:
- Update
xorybased on the direction (N, S, E, W). - If the new position exists in
visit, returntrue. - Otherwise, add the new position to
visit.
- Update
- If we finish the path without revisiting any position, return
false.
class Solution:
def isPathCrossing(self, path: str) -> bool:
dir = {
'N': [0, 1],
'S': [0, -1],
'E': [1, 0],
'W': [-1, 0]
}
visit = set()
x, y = 0, 0
for c in path:
visit.add((x, y))
dx, dy = dir[c]
x, y = x + dx, y + dy
if (x, y) in visit:
return True
return FalseTime & Space Complexity
- Time complexity:
- Space complexity:
2. Hash Set (Custom Hash)
Intuition
Instead of storing coordinates as strings or tuples, we can encode them into a single integer. By shifting one coordinate (e.g., x << 32) and adding the other, we create a unique hash for each position. This can improve performance by avoiding string concatenation overhead.
Algorithm
- Define a hash function:
hash(x, y) = (x << 32) + y. - Initialize a set and add
hash(0, 0). - Track position with
x = 0,y = 0. - For each character in the path:
- Update coordinates based on direction.
- Compute the
hashof the new position. - If it exists in the set, return
true. - Otherwise, add the
hashto the set.
- Return
falseif no crossing is found.
class Solution:
def isPathCrossing(self, path: str) -> bool:
visit = set()
x, y = 0, 0
visit.add(self.hash(x, y))
for c in path:
if c == 'N':
y += 1
elif c == 'S':
y -= 1
elif c == 'E':
x += 1
elif c == 'W':
x -= 1
pos = self.hash(x, y)
if pos in visit:
return True
visit.add(pos)
return False
def hash(self, x: int, y: int) -> int:
return (x << 32) + yTime & Space Complexity
- Time complexity:
- Space complexity:
Common Pitfalls
Forgetting to Add the Starting Position
A common mistake is forgetting to add the origin (0, 0) to the visited set before processing the path. The path can cross the starting point, so it must be tracked from the beginning. If you only add positions after moving, you will miss cases where the path returns to the origin.
Incorrect Coordinate Representation
When storing coordinates in a hash set, using improper representations can cause collisions or misses. For example, concatenating coordinates as x + y instead of x + "," + y can produce identical strings for different coordinate pairs (e.g., (1, 23) and (12, 3) both become "123"). Always use a delimiter or tuple representation to ensure uniqueness.
Sign in to join the discussion