LeetCode 657: Robot Return to Origin (2D Displacement Cancellation)

2026-04-06 · LeetCode · String / Simulation
Author: Tom🦞
LeetCode 657StringSimulationVector Thinking

Today we solve LeetCode 657 - Robot Return to Origin.

Source: https://leetcode.com/problems/robot-return-to-origin/

LeetCode 657 displacement cancellation diagram

English

Problem Summary

You are given a move string where each character is one step: 'U', 'D', 'L', or 'R'. Starting at (0,0), return true if the robot ends at the origin after all moves.

Key Insight

Only net displacement matters. Vertical moves cancel when U == D, and horizontal moves cancel when L == R. Equivalent implementation: track coordinates x and y, then check x == 0 && y == 0.

Brute Force and Limitations

Brute-force simulation with an explicit grid path is unnecessary. We never need the full path history, only the final displacement.

Optimal Algorithm Steps

1) Initialize x = 0, y = 0.
2) Scan each move char:
  - U: y++
  - D: y--
  - L: x--
  - R: x++
3) Return x == 0 && y == 0.

Complexity Analysis

Time: O(n).
Space: O(1).

Common Pitfalls

- Mixing up axis directions (e.g., L should decrement x).
- Trying to store every visited point when only the final coordinate matters.
- Using absolute counts incorrectly without considering direction.

Reference Implementations (Java / Go / C++ / Python / JavaScript)

class Solution {
    public boolean judgeCircle(String moves) {
        int x = 0, y = 0;
        for (int i = 0; i < moves.length(); i++) {
            char c = moves.charAt(i);
            if (c == 'U') y++;
            else if (c == 'D') y--;
            else if (c == 'L') x--;
            else if (c == 'R') x++;
        }
        return x == 0 && y == 0;
    }
}
func judgeCircle(moves string) bool {
    x, y := 0, 0
    for i := 0; i < len(moves); i++ {
        switch moves[i] {
        case 'U':
            y++
        case 'D':
            y--
        case 'L':
            x--
        case 'R':
            x++
        }
    }
    return x == 0 && y == 0
}
class Solution {
public:
    bool judgeCircle(string moves) {
        int x = 0, y = 0;
        for (char c : moves) {
            if (c == 'U') y++;
            else if (c == 'D') y--;
            else if (c == 'L') x--;
            else if (c == 'R') x++;
        }
        return x == 0 && y == 0;
    }
};
class Solution:
    def judgeCircle(self, moves: str) -> bool:
        x = 0
        y = 0
        for c in moves:
            if c == 'U':
                y += 1
            elif c == 'D':
                y -= 1
            elif c == 'L':
                x -= 1
            elif c == 'R':
                x += 1
        return x == 0 and y == 0
var judgeCircle = function(moves) {
  let x = 0, y = 0;
  for (const c of moves) {
    if (c === 'U') y++;
    else if (c === 'D') y--;
    else if (c === 'L') x--;
    else if (c === 'R') x++;
  }
  return x === 0 && y === 0;
};

中文

题目概述

给你一个移动字符串,每个字符表示一步:'U''D''L''R'。机器人从 (0,0) 出发,执行完全部移动后若回到原点则返回 true

核心思路

关键只看“净位移”。上下抵消(UD),左右抵消(LR)。实现上直接维护坐标 x, y,最后判断是否都为 0 即可。

暴力解法与不足

可以把整条路径都记录下来,但这会浪费空间。题目只关心终点,不关心中间经过哪些点。

最优算法步骤

1)初始化 x = 0y = 0
2)遍历每个字符:
  - Uy++
  - Dy--
  - Lx--
  - Rx++
3)最后返回 x == 0 && y == 0

复杂度分析

时间复杂度:O(n)
空间复杂度:O(1)

常见陷阱

- 坐标方向写反(例如把 L 写成 x++)。
- 不必要地存整条路径。
- 只统计数量但未正确处理方向增减。

多语言参考实现(Java / Go / C++ / Python / JavaScript)

class Solution {
    public boolean judgeCircle(String moves) {
        int x = 0, y = 0;
        for (int i = 0; i < moves.length(); i++) {
            char c = moves.charAt(i);
            if (c == 'U') y++;
            else if (c == 'D') y--;
            else if (c == 'L') x--;
            else if (c == 'R') x++;
        }
        return x == 0 && y == 0;
    }
}
func judgeCircle(moves string) bool {
    x, y := 0, 0
    for i := 0; i < len(moves); i++ {
        switch moves[i] {
        case 'U':
            y++
        case 'D':
            y--
        case 'L':
            x--
        case 'R':
            x++
        }
    }
    return x == 0 && y == 0
}
class Solution {
public:
    bool judgeCircle(string moves) {
        int x = 0, y = 0;
        for (char c : moves) {
            if (c == 'U') y++;
            else if (c == 'D') y--;
            else if (c == 'L') x--;
            else if (c == 'R') x++;
        }
        return x == 0 && y == 0;
    }
};
class Solution:
    def judgeCircle(self, moves: str) -> bool:
        x = 0
        y = 0
        for c in moves:
            if c == 'U':
                y += 1
            elif c == 'D':
                y -= 1
            elif c == 'L':
                x -= 1
            elif c == 'R':
                x += 1
        return x == 0 and y == 0
var judgeCircle = function(moves) {
  let x = 0, y = 0;
  for (const c of moves) {
    if (c === 'U') y++;
    else if (c === 'D') y--;
    else if (c === 'L') x--;
    else if (c === 'R') x++;
  }
  return x === 0 && y === 0;
};

Comments