LeetCode 1138. 字母板上的路径
Posted Tisfy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 1138. 字母板上的路径相关的知识,希望对你有一定的参考价值。
【LetMeFly】1138.字母板上的路径
力扣题目链接:https://leetcode.cn/problems/alphabet-board-path/
我们从一块字母板上的位置 (0, 0)
出发,该坐标对应的字符为 board[0][0]
。
在本题里,字母板为board = ["abcde", "fghij", "klmno", "pqrst", "uvwxy", "z"]
,如下所示。
我们可以按下面的指令规则行动:
- 如果方格存在,
'U'
意味着将我们的位置上移一行; - 如果方格存在,
'D'
意味着将我们的位置下移一行; - 如果方格存在,
'L'
意味着将我们的位置左移一列; - 如果方格存在,
'R'
意味着将我们的位置右移一列; '!'
会把在我们当前位置(r, c)
的字符board[r][c]
添加到答案中。
(注意,字母板上只存在有字母的位置。)
返回指令序列,用最小的行动次数让答案和目标 target
相同。你可以返回任何达成目标的路径。
示例 1:
输入:target = "leet" 输出:"DDR!UURRR!!DDD!"
示例 2:
输入:target = "code" 输出:"RR!DDRR!UUL!R!"
提示:
1 <= target.length <= 100
target
仅含有小写英文字母。
方法一:计算坐标
我们以字母a为原点,右为x轴正方向,下为y轴正方向建立坐标轴,单位长度为题目描述中字母表中的一个字母。
O--------> x
|
|
↓
y
这样,只要知道起点和终点的坐标,就能很方便地得出要移动的方向。
怎么由字符映射为坐标呢?很简单,假设字符c是字母表中的第3个字母,我们从0开始计数,则c的位次为2。
那么, 2 / / 6 = 2 2 // 6 = 2 2//6=2即为字符c的纵坐标, 2 % 6 = 0 2\\%6=0 2%6=0即为字符c的横坐标
那么剩下的问题就是知道起点和终点的坐标,怎么得到移动路径
很简单,如果终点坐标的纵坐标小于起点的纵坐标,则向上移动二者的差值次;否则向下移动这么多次。如果终点坐标的横坐标小于起点的横坐标,则向左移动二者的差值次;否则向右移动这么多次。
细节问题:题目中字母表不是规则的矩形,怎么保证移动过程中不会超出字母表的边界呢?
有两种方法:
- 特判终点是否为z。如果终点为z则先左右移动后上下移动,否则先上下移动后左右移动即可
- 不论何时都先尽量向左上移动(如果需要),后向右下移动(如果需要)
复杂度分析:
- 时间复杂度 O ( l e n ( t a r g e t ) × C ) O(len(target)\\times C) O(len(target)×C),其中 C C C为平均每次的移动次数
- 空间复杂度 O ( 1 ) O(1) O(1)或 O ( l e n ( t a r g e t ) ) O(len(target)) O(len(target))。对于字符串可变的编程语言(例如C/C++),只需要每次将移动路径添加到字符串末尾;对于字符串不可变的编程语言(例如Python),则需要额外开辟一个空间存储每次的移动路径,或者每次复制字符串并结合为一个新的字符串。
AC代码
C++
特判终点是否为z:
// 特判是否终点是z,如果终点是z则先左右移动后上下移动;否则先上下移动后左右移动即可
typedef pair<int, int> pii;
inline pii c2p(char c)
int th = c - 'a';
return th / 5, th % 5;
class Solution
public:
string alphabetBoardPath(string& target)
string ans;
pii nowLoc = 0, 0;
for (char c : target)
pii newLoc = c2p(c);
if (c == 'z')
ans += string(abs(newLoc.second - nowLoc.second), newLoc.second > nowLoc.second ? 'R' : 'L');
ans += string(abs(newLoc.first - nowLoc.first), newLoc.first > nowLoc.first ? 'D' : 'U');
else
ans += string(abs(newLoc.first - nowLoc.first), newLoc.first > nowLoc.first ? 'D' : 'U');
ans += string(abs(newLoc.second - nowLoc.second), newLoc.second > nowLoc.second ? 'R' : 'L');
ans += '!';
nowLoc = newLoc;
return ans;
;
先尽量左上移后右下移:
// 四个方向分别判断,优先先左上移动后右下移动即可
typedef pair<int, int> pii;
inline pii c2p(char c)
int th = c - 'a';
return th / 5, th % 5;
class Solution
public:
string alphabetBoardPath(string& target)
string ans;
pii nowLoc = 0, 0;
for (char c : target)
pii newLoc = c2p(c);
if (newLoc.first < nowLoc.first)
ans += string(nowLoc.first - newLoc.first, 'U');
if (newLoc.second < nowLoc.second)
ans += string(nowLoc.second - newLoc.second, 'L');
if (newLoc.first > nowLoc.first)
ans += string(newLoc.first - nowLoc.first, 'D');
if (newLoc.second > nowLoc.second)
ans += string(newLoc.second - nowLoc.second, 'R');
ans += '!';
nowLoc = newLoc;
return ans;
;
Python
先尽量左上移后右下移:
# from typing import Tuple
def c2p(c: str) -> Tuple[int, int]:
th = ord(c) - ord('a')
return th // 5, th % 5
class Solution:
def alphabetBoardPath(self, target: str) -> str:
ans = []
nowY, nowX = 0, 0
for c in target:
newY, newX = c2p(c)
if newY < nowY:
ans.append('U' * (nowY - newY))
if newX < nowX:
ans.append('L' * (nowX - newX))
if newY > nowY:
ans.append('D' * (newY - nowY))
if newX > nowX:
ans.append('R' * (newX - nowX))
ans.append('!')
nowY, nowX = newY, newX
return "".join(ans)
同步发文于CSDN,原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/128992281
以上是关于LeetCode 1138. 字母板上的路径的主要内容,如果未能解决你的问题,请参考以下文章
[LeetCode] 1249. Minimum Remove to Make Valid Parentheses