Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Move from brute-force thinking to an efficient approach using array strategy.
A robot on an infinite XY-plane starts at point (0, 0) facing north. The robot receives an array of integers commands, which represents a sequence of moves that it needs to execute. There are only three possible types of instructions the robot can receive:
-2: Turn left 90 degrees.-1: Turn right 90 degrees.1 <= k <= 9: Move forward k units, one unit at a time.Some of the grid squares are obstacles. The ith obstacle is at grid point obstacles[i] = (xi, yi). If the robot runs into an obstacle, it will stay in its current location (on the block adjacent to the obstacle) and move onto the next command.
Return the maximum squared Euclidean distance that the robot reaches at any point in its path (i.e. if the distance is 5, return 25).
Note:
(0, 0). If this happens, the robot will ignore the obstacle until it has moved off the origin. However, it will be unable to return to (0, 0) due to the obstacle.Example 1:
Input: commands = [4,-1,3], obstacles = []
Output: 25
Explanation:
The robot starts at (0, 0):
(0, 4).(3, 4).The furthest point the robot ever gets from the origin is (3, 4), which squared is 32 + 42 = 25 units away.
Example 2:
Input: commands = [4,-1,4,-2,4], obstacles = [[2,4]]
Output: 65
Explanation:
The robot starts at (0, 0):
(0, 4).(2, 4), robot is at (1, 4).(1, 8).The furthest point the robot ever gets from the origin is (1, 8), which squared is 12 + 82 = 65 units away.
Example 3:
Input: commands = [6,-1,-1,6], obstacles = [[0,0]]
Output: 36
Explanation:
The robot starts at (0, 0):
(0, 6).(0,0), robot is at (0, 1).The furthest point the robot ever gets from the origin is (0, 6), which squared is 62 = 36 units away.
Constraints:
1 <= commands.length <= 104commands[i] is either -2, -1, or an integer in the range [1, 9].0 <= obstacles.length <= 104-3 * 104 <= xi, yi <= 3 * 104231.Problem summary: A robot on an infinite XY-plane starts at point (0, 0) facing north. The robot receives an array of integers commands, which represents a sequence of moves that it needs to execute. There are only three possible types of instructions the robot can receive: -2: Turn left 90 degrees. -1: Turn right 90 degrees. 1 <= k <= 9: Move forward k units, one unit at a time. Some of the grid squares are obstacles. The ith obstacle is at grid point obstacles[i] = (xi, yi). If the robot runs into an obstacle, it will stay in its current location (on the block adjacent to the obstacle) and move onto the next command. Return the maximum squared Euclidean distance that the robot reaches at any point in its path (i.e. if the distance is 5, return 25). Note: There can be an obstacle at (0, 0). If this happens, the robot will ignore the obstacle until it has moved off the origin. However, it will be unable
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array · Hash Map
[4,-1,3] []
[4,-1,4,-2,4] [[2,4]]
[6,-1,-1,6] [[0,0]]
walking-robot-simulation-ii)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #874: Walking Robot Simulation
class Solution {
public int robotSim(int[] commands, int[][] obstacles) {
int[] dirs = {0, 1, 0, -1, 0};
Set<Integer> s = new HashSet<>(obstacles.length);
for (var e : obstacles) {
s.add(f(e[0], e[1]));
}
int ans = 0, k = 0;
int x = 0, y = 0;
for (int c : commands) {
if (c == -2) {
k = (k + 3) % 4;
} else if (c == -1) {
k = (k + 1) % 4;
} else {
while (c-- > 0) {
int nx = x + dirs[k], ny = y + dirs[k + 1];
if (s.contains(f(nx, ny))) {
break;
}
x = nx;
y = ny;
ans = Math.max(ans, x * x + y * y);
}
}
}
return ans;
}
private int f(int x, int y) {
return x * 60010 + y;
}
}
// Accepted solution for LeetCode #874: Walking Robot Simulation
func robotSim(commands []int, obstacles [][]int) (ans int) {
dirs := [5]int{0, 1, 0, -1, 0}
type pair struct{ x, y int }
s := map[pair]bool{}
for _, e := range obstacles {
s[pair{e[0], e[1]}] = true
}
var x, y, k int
for _, c := range commands {
if c == -2 {
k = (k + 3) % 4
} else if c == -1 {
k = (k + 1) % 4
} else {
for ; c > 0 && !s[pair{x + dirs[k], y + dirs[k+1]}]; c-- {
x += dirs[k]
y += dirs[k+1]
ans = max(ans, x*x+y*y)
}
}
}
return
}
# Accepted solution for LeetCode #874: Walking Robot Simulation
class Solution:
def robotSim(self, commands: List[int], obstacles: List[List[int]]) -> int:
dirs = (0, 1, 0, -1, 0)
s = {(x, y) for x, y in obstacles}
ans = k = 0
x = y = 0
for c in commands:
if c == -2:
k = (k + 3) % 4
elif c == -1:
k = (k + 1) % 4
else:
for _ in range(c):
nx, ny = x + dirs[k], y + dirs[k + 1]
if (nx, ny) in s:
break
x, y = nx, ny
ans = max(ans, x * x + y * y)
return ans
// Accepted solution for LeetCode #874: Walking Robot Simulation
struct Solution;
#[derive(Debug, PartialEq, Eq, Hash, Default)]
struct Point {
x: i32,
y: i32,
}
impl Point {
fn new(x: i32, y: i32) -> Self {
Point { x, y }
}
fn from(v: Vec<i32>) -> Self {
Point { x: v[0], y: v[1] }
}
fn square_distance(&self) -> i32 {
self.x * self.x + self.y * self.y
}
}
#[derive(Default)]
struct Robot {
position: Point,
direction: usize,
}
impl Robot {
fn new() -> Self {
Robot {
position: Point { x: 0, y: 0 },
direction: 0,
}
}
fn left(&mut self) {
self.direction = (self.direction + 1) % 4;
}
fn right(&mut self) {
self.direction = (self.direction + 3) % 4;
}
fn next(&self) -> Point {
let x = self.position.x;
let y = self.position.y;
match self.direction {
0 => Point::new(x, y + 1),
1 => Point::new(x - 1, y),
2 => Point::new(x, y - 1),
3 => Point::new(x + 1, y),
_ => unreachable!(),
}
}
fn walk(&mut self, step: usize, grid: &Grid) {
let mut i = 0;
while i < step && !grid.obstacles.contains(&self.next()) {
self.position = self.next();
i += 1;
}
}
}
use std::collections::HashSet;
struct Grid {
obstacles: HashSet<Point>,
}
impl Grid {
fn new(obstacles: Vec<Point>) -> Self {
let mut hs: HashSet<Point> = HashSet::new();
for x in obstacles {
hs.insert(x);
}
Grid { obstacles: hs }
}
}
impl Solution {
fn robot_sim(commands: Vec<i32>, obstacles: Vec<Vec<i32>>) -> i32 {
let grid: Grid = Grid::new(obstacles.iter().map(|v| Point::new(v[0], v[1])).collect());
let mut robot = Robot::new();
let mut max = 0;
for command in commands {
match command {
-2 => robot.left(),
-1 => robot.right(),
_ => {
robot.walk(command as usize, &grid);
max = i32::max(robot.position.square_distance(), max);
}
}
}
max as i32
}
}
#[test]
fn test() {
let commands: Vec<i32> = vec![4, -1, 3];
let obstacles: Vec<Vec<i32>> = vec![];
assert_eq!(Solution::robot_sim(commands, obstacles), 25);
let commands: Vec<i32> = vec![4, -1, 4, -2, 4];
let obstacles: Vec<Vec<i32>> = vec![vec![2, 4]];
assert_eq!(Solution::robot_sim(commands, obstacles), 65);
}
// Accepted solution for LeetCode #874: Walking Robot Simulation
function robotSim(commands: number[], obstacles: number[][]): number {
const dirs = [0, 1, 0, -1, 0];
const s: Set<number> = new Set();
const f = (x: number, y: number) => x * 60010 + y;
for (const [x, y] of obstacles) {
s.add(f(x, y));
}
let [ans, x, y, k] = [0, 0, 0, 0];
for (let c of commands) {
if (c === -2) {
k = (k + 3) % 4;
} else if (c === -1) {
k = (k + 1) % 4;
} else {
while (c-- > 0) {
const [nx, ny] = [x + dirs[k], y + dirs[k + 1]];
if (s.has(f(nx, ny))) {
break;
}
[x, y] = [nx, ny];
ans = Math.max(ans, x * x + y * y);
}
}
}
return ans;
}
Use this to step through a reusable interview workflow for this problem.
Two nested loops check every pair or subarray. The outer loop fixes a starting point, the inner loop extends or searches. For n elements this gives up to n²/2 operations. No extra space, but the quadratic time is prohibitive for large inputs.
Most array problems have an O(n²) brute force (nested loops) and an O(n) optimal (single pass with clever state tracking). The key is identifying what information to maintain as you scan: a running max, a prefix sum, a hash map of seen values, or two pointers.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
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.