羡慕别人的,除了年终奖,还有开工红包

开工大吉

今天应该有一大批小伙伴开始复工了,祝大家新的一年工作顺利。

今天第一批因为「开工红包」冲上热搜的是:腾讯 & 小米

在小米,员工排长队在准备领取雷军发的开工红包,只要排队去领就有:

腾讯这边,据爆料也是排起了长龙,每位员工都期待领到鹅厂的开工红包:

评论区甚至有同学晒出领到的大额红包:

又是羡慕别人的一天。

...

回归主线,来一道小小模拟题"庆祝"一下复工。

题目描述

平台:LeetCode

题号:1041

在无限的平面上,机器人最初位于 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( 0 , 0 ) (0, 0) </math>(0,0) 处,面朝北方。注意:

  • 北方向 是 y 轴的正方向。
  • 南方向 是 y 轴的负方向。
  • 东方向 是 x 轴的正方向。
  • 西方向 是 x 轴的负方向。

机器人可以接受下列三条指令之一:

  • "G":直走 <math xmlns="http://www.w3.org/1998/Math/MathML"> 1 1 </math>1 个单位
  • "L":左转 <math xmlns="http://www.w3.org/1998/Math/MathML"> 90 90 </math>90 度
  • "R":右转 <math xmlns="http://www.w3.org/1998/Math/MathML"> 90 90 </math>90 度

机器人按顺序执行指令 instructions,并一直重复它们。

只有在平面中存在环使得机器人永远无法离开时,返回 true。否则,返回 false

示例 1:

makefile 复制代码
输入:instructions = "GGLLGG"

输出:true

解释:机器人最初在(0,0)处,面向北方。
"G":移动一步。位置:(0,1)方向:北。
"G":移动一步。位置:(0,2).方向:北。
"L":逆时针旋转90度。位置:(0,2).方向:西。
"L":逆时针旋转90度。位置:(0,2)方向:南。
"G":移动一步。位置:(0,1)方向:南。
"G":移动一步。位置:(0,0)方向:南。
重复指令,机器人进入循环:(0,0)------>(0,1)------>(0,2)------>(0,1)------>(0,0)。
在此基础上,我们返回true。

示例 2:

arduino 复制代码
输入:instructions = "GG"

输出:false

解释:机器人最初在(0,0)处,面向北方。
"G":移动一步。位置:(0,1)方向:北。
"G":移动一步。位置:(0,2).方向:北。
重复这些指示,继续朝北前进,不会进入循环。
在此基础上,返回false。

示例 3:

makefile 复制代码
输入:instructions = "GL"

输出:true

解释:机器人最初在(0,0)处,面向北方。
"G":移动一步。位置:(0,1)方向:北。
"L":逆时针旋转90度。位置:(0,1).方向:西。
"G":移动一步。位置:(- 1,1)方向:西。
"L":逆时针旋转90度。位置:(- 1,1)方向:南。
"G":移动一步。位置:(- 1,0)方向:南。
"L":逆时针旋转90度。位置:(- 1,0)方向:东方。
"G":移动一步。位置:(0,0)方向:东方。
"L":逆时针旋转90度。位置:(0,0)方向:北。
重复指令,机器人进入循环:(0,0)------>(0,1)------>(- 1,1)------>(- 1,0)------>(0,0)。
在此基础上,我们返回true。

提示:

  • <math xmlns="http://www.w3.org/1998/Math/MathML"> 1 < = i n s t r u c t i o n s . l e n g t h < = 100 1 <= instructions.length <= 100 </math>1<=instructions.length<=100
  • instructions[i] 仅包含 'G', 'L', 'R'

模拟

为了方便,将 instructions 记为 s,"北西南东"四个方向分别记为"上左下右"四个逆时针方向。

起始位置在 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( 0 , 0 ) (0,0) </math>(0,0),方向为上,我们可以将「位置 + 方向」统称为「状态」。

所谓"循环",则是指执行若干次的 s 后,会回到相同的状态。

我们可以按 s 执行一遍,假设执行完所在位置为 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( x , y ) (x, y) </math>(x,y),所在位置为 <math xmlns="http://www.w3.org/1998/Math/MathML"> k k </math>k,先根据 位置 分情况讨论:

  1. <math xmlns="http://www.w3.org/1998/Math/MathML"> ( x , y ) (x, y) </math>(x,y) 为 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( 0 , 0 ) (0, 0) </math>(0,0),此时无论执行一遍后的方向为何值,必然能在若干次执行后回到起始状态。

    即只需要确保 (n * k) % 4 为 <math xmlns="http://www.w3.org/1998/Math/MathML"> 0 0 </math>0 即可,机器人会陷入循环;

  2. <math xmlns="http://www.w3.org/1998/Math/MathML"> ( x , y ) (x, y) </math>(x,y) 不为 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( 0 , 0 ) (0, 0) </math>(0,0),再根据 方向 进一步分情况讨论:

    • 方向为上:每执行一遍 s 指令,位置变化为 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( x , y ) (x, y) </math>(x,y),方向不变。

      那么执行 <math xmlns="http://www.w3.org/1998/Math/MathML"> n n </math>n 遍后位置为 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( n × x , n × y ) (n \times x, n \times y) </math>(n×x,n×y),其中 <math xmlns="http://www.w3.org/1998/Math/MathML"> n n </math>n 为正整数,并且 <math xmlns="http://www.w3.org/1998/Math/MathML"> x x </math>x 和 <math xmlns="http://www.w3.org/1998/Math/MathML"> y y </math>y 不同时为 <math xmlns="http://www.w3.org/1998/Math/MathML"> 0 0 </math>0,因此随着执行次数增加,位置会离 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( 0 , 0 ) (0, 0) </math>(0,0) 越来越远,机器人不会陷入循环;

    • 方向为下:每执行一遍 s 指令,位置变化为 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( x , y ) (x, y) </math>(x,y),方向翻转。

      如果再执行一遍,由于再次执行时的方向与起始方向相反,因此位置变化为 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( − x , − y ) (-x, -y) </math>(−x,−y),同时方向再次翻转(与起始方向一致)。即执行偶数次后,会回到起始状态,机器人会陷入循环;

    • 方向为左:每执行一遍 s 指令,位置变化为 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( x , y ) (x, y) </math>(x,y),方向为逆时针 <math xmlns="http://www.w3.org/1998/Math/MathML"> 90 90 </math>90 度。

      如果执行第二次,位置变化为 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( − y , x ) (-y, x) </math>(−y,x),方向再逆时针 <math xmlns="http://www.w3.org/1998/Math/MathML"> 90 90 </math>90 度(与起始方向相反);执行第三次,位置变化为 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( − x , − y ) (-x, -y) </math>(−x,−y),方向再逆时针 <math xmlns="http://www.w3.org/1998/Math/MathML"> 90 90 </math>90 度(与起始方向呈顺时针 <math xmlns="http://www.w3.org/1998/Math/MathML"> 90 90 </math>90 度),该次变化会和首次执行相互抵消;执行第四次,位置变化为 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( y , − x ) (y, -x) </math>(y,−x),方向再逆时针 <math xmlns="http://www.w3.org/1998/Math/MathML"> 90 90 </math>90 度(与起始方向相同),该次变化与第二次执行相互抵消。总的位置变化为 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( 0 , 0 ) (0, 0) </math>(0,0),同时方向与起始方向一致,机器人会陷入循环;

    • 方向为右:与「方向为左」同理,机器人会陷入循环。

综上,只要执行一遍 s 后所在位置为 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( 0 , 0 ) (0, 0) </math>(0,0) 或方向不为上,均可确保循环发生。

Java 代码:

Java 复制代码
class Solution {
    public boolean isRobotBounded(String s) {
        int x = 0, y = 0, d = 0;
        int[][] dirs = new int[][]{{0,1}, {-1,0}, {0,-1}, {1,0}};
        for (char c : s.toCharArray()) {
            if (c == 'G') {
                x += dirs[d][0]; y += dirs[d][1];
            } else if (c == 'L') {
                d = (d + 1) % 4;
            } else {
                d = ((d - 1) % 4 + 4) % 4;
            }
        }
        return (x == 0 && y == 0) || d != 0;
    }
}

C++ 代码:

C++ 复制代码
class Solution {
public:
    bool isRobotBounded(string s) {
        int x = 0, y = 0, d = 0;
        int dirs[4][2] = {{0, 1}, {-1, 0}, {0, -1}, {1, 0}};
        for (char c : s) {
            if (c == 'G') {
                x += dirs[d][0]; y += dirs[d][1];
            } else if (c == 'L') {
                d = (d + 1) % 4;
            } else {
                d = ((d - 1) % 4 + 4) % 4;
            }
        }
        return (x == 0 && y == 0) || d != 0;
    }
};

Python 代码:

Python 复制代码
class Solution:
    def isRobotBounded(self, s: str) -> bool:
        x, y, d = 0, 0, 0
        dirs = [[0, 1], [-1, 0], [0, -1], [1, 0]]
        for c in s:
            if c == 'G':
                x += dirs[d][0]
                y += dirs[d][1]
            elif c == 'L':
                d = (d + 1) % 4
            else:
                d = ((d - 1) % 4 + 4) % 4
        return (x == 0 and y == 0) or d != 0

Go 代码:

Go 复制代码
func isRobotBounded(s string) bool {
    x, y, d := 0, 0, 0
    dirs := [][]int{{0, 1}, {-1, 0}, {0, -1}, {1, 0}}
    for _, c := range s {
        if c == 'G' {
            x += dirs[d][0]
            y += dirs[d][1]
        } else if c == 'L' {
            d = (d + 1) % 4
        } else {
            d = ((d - 1) % 4 + 4) % 4
        }
    }
    return (x == 0 && y == 0) || d != 0
}

TypeScript 代码:

TypeScript 复制代码
function isRobotBounded(s: string): boolean {
    let x = 0, y = 0, d = 0;
    const dirs: number[][] = [[0, 1], [-1, 0], [0, -1], [1, 0]];
    for (const c of s) {
        if (c === 'G') {
            x += dirs[d][0];
            y += dirs[d][1];
        } else if (c === 'L') {
            d = (d + 1) % 4;
        } else {
            d = ((d - 1) % 4 + 4) % 4;
        }
    }
    return (x === 0 && y === 0) || d !== 0;
};
  • 时间复杂度: <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( n ) O(n) </math>O(n)
  • 空间复杂度: <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( 1 ) O(1) </math>O(1)

我是宫水三叶,每天都会分享算法知识,并和大家聊聊近期的所见所闻。

欢迎关注,明天见。

更多更全更热门的「笔试/面试」相关资料可访问排版精美的 合集新基地 🎉🎉

相关推荐
LCG元1 小时前
【面试问题】JIT 是什么?和 JVM 什么关系?
面试·职场和发展
迷雾漫步者1 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-2 小时前
验证码机制
前端·后端
燃先生._.3 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
超爱吃士力架3 小时前
邀请逻辑
java·linux·后端
高山我梦口香糖4 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
m0_748235244 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
m0_748240255 小时前
前端如何检测用户登录状态是否过期
前端
black^sugar5 小时前
纯前端实现更新检测
开发语言·前端·javascript