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.
Move from brute-force thinking to an efficient approach using hash map strategy.
You are given a string s consisting of characters 'U', 'D', 'L', and 'R', representing moves on an infinite 2D Cartesian grid.
'U': Move from (x, y) to (x, y + 1).'D': Move from (x, y) to (x, y - 1).'L': Move from (x, y) to (x - 1, y).'R': Move from (x, y) to (x + 1, y).You are also given a positive integer k.
You must choose and remove exactly one contiguous substring of length k from s. Then, start from coordinate (0, 0) and perform the remaining moves in order.
Return an integer denoting the number of distinct final coordinates reachable.
Example 1:
Input: s = "LUL", k = 1
Output: 2
Explanation:
After removing a substring of length 1, s can be "UL", "LL" or "LU". Following these moves, the final coordinates will be (-1, 1), (-2, 0) and (-1, 1) respectively. There are two distinct points (-1, 1) and (-2, 0) so the answer is 2.
Example 2:
Input: s = "UDLR", k = 4
Output: 1
Explanation:
After removing a substring of length 4, s can only be the empty string. The final coordinates will be (0, 0). There is only one distinct point (0, 0) so the answer is 1.
Example 3:
Input: s = "UU", k = 1
Output: 1
Explanation:
After removing a substring of length 1, s becomes "U", which always ends at (0, 1), so there is only one distinct final coordinate.
Constraints:
1 <= s.length <= 105s consists of only 'U', 'D', 'L', and 'R'.1 <= k <= s.lengthProblem summary: You are given a string s consisting of characters 'U', 'D', 'L', and 'R', representing moves on an infinite 2D Cartesian grid. 'U': Move from (x, y) to (x, y + 1). 'D': Move from (x, y) to (x, y - 1). 'L': Move from (x, y) to (x - 1, y). 'R': Move from (x, y) to (x + 1, y). You are also given a positive integer k. You must choose and remove exactly one contiguous substring of length k from s. Then, start from coordinate (0, 0) and perform the remaining moves in order. Return an integer denoting the number of distinct final coordinates reachable.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Hash Map · Sliding Window
"LUL" 1
"UDLR" 4
"UU" 1
Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #3694: Distinct Points Reachable After Substring Removal
class Solution {
public int distinctPoints(String s, int k) {
int n = s.length();
int[] f = new int[n + 1];
int[] g = new int[n + 1];
int x = 0, y = 0;
for (int i = 1; i <= n; ++i) {
char c = s.charAt(i - 1);
if (c == 'U') {
++y;
} else if (c == 'D') {
--y;
} else if (c == 'L') {
--x;
} else {
++x;
}
f[i] = x;
g[i] = y;
}
Set<Long> st = new HashSet<>();
for (int i = k; i <= n; ++i) {
int a = f[n] - (f[i] - f[i - k]);
int b = g[n] - (g[i] - g[i - k]);
st.add(1L * a * n + b);
}
return st.size();
}
}
// Accepted solution for LeetCode #3694: Distinct Points Reachable After Substring Removal
func distinctPoints(s string, k int) int {
n := len(s)
f := make([]int, n+1)
g := make([]int, n+1)
x, y := 0, 0
for i := 1; i <= n; i++ {
c := s[i-1]
if c == 'U' {
y++
} else if c == 'D' {
y--
} else if c == 'L' {
x--
} else {
x++
}
f[i] = x
g[i] = y
}
st := make(map[int64]struct{})
for i := k; i <= n; i++ {
a := f[n] - (f[i] - f[i-k])
b := g[n] - (g[i] - g[i-k])
key := int64(a)*int64(n) + int64(b)
st[key] = struct{}{}
}
return len(st)
}
# Accepted solution for LeetCode #3694: Distinct Points Reachable After Substring Removal
class Solution:
def distinctPoints(self, s: str, k: int) -> int:
n = len(s)
f = [0] * (n + 1)
g = [0] * (n + 1)
x = y = 0
for i, c in enumerate(s, 1):
if c == "U":
y += 1
elif c == "D":
y -= 1
elif c == "L":
x -= 1
else:
x += 1
f[i] = x
g[i] = y
st = set()
for i in range(k, n + 1):
a = f[n] - (f[i] - f[i - k])
b = g[n] - (g[i] - g[i - k])
st.add((a, b))
return len(st)
// Accepted solution for LeetCode #3694: Distinct Points Reachable After Substring Removal
use std::collections::HashSet;
impl Solution {
pub fn distinct_points(s: String, k: i32) -> i32 {
let n = s.len();
let mut f = vec![0; n + 1];
let mut g = vec![0; n + 1];
let mut x = 0;
let mut y = 0;
let bytes = s.as_bytes();
for i in 1..=n {
match bytes[i - 1] as char {
'U' => y += 1,
'D' => y -= 1,
'L' => x -= 1,
_ => x += 1,
}
f[i] = x;
g[i] = y;
}
let mut st = HashSet::new();
let k = k as usize;
for i in k..=n {
let a = f[n] - (f[i] - f[i - k]);
let b = g[n] - (g[i] - g[i - k]);
st.insert((a as i64) * (n as i64) + (b as i64));
}
st.len() as i32
}
}
// Accepted solution for LeetCode #3694: Distinct Points Reachable After Substring Removal
function distinctPoints(s: string, k: number): number {
const n = s.length;
const f = new Array(n + 1).fill(0);
const g = new Array(n + 1).fill(0);
let x = 0,
y = 0;
for (let i = 1; i <= n; ++i) {
const c = s[i - 1];
if (c === 'U') ++y;
else if (c === 'D') --y;
else if (c === 'L') --x;
else ++x;
f[i] = x;
g[i] = y;
}
const st = new Set<number>();
for (let i = k; i <= n; ++i) {
const a = f[n] - (f[i] - f[i - k]);
const b = g[n] - (g[i] - g[i - k]);
st.add(a * n + b);
}
return st.size;
}
Use this to step through a reusable interview workflow for this problem.
For each starting index, scan the next k elements to compute the window aggregate. There are n−k+1 starting positions, each requiring O(k) work, giving O(n × k) total. No extra space since we recompute from scratch each time.
The window expands and contracts as we scan left to right. Each element enters the window at most once and leaves at most once, giving 2n total operations = O(n). Space depends on what we track inside the window (a hash map of at most k distinct elements, or O(1) for a fixed-size window).
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.
Wrong move: Using `if` instead of `while` leaves the window invalid for multiple iterations.
Usually fails on: Over-limit windows stay invalid and produce wrong lengths/counts.
Fix: Shrink in a `while` loop until the invariant is valid again.