题目地址:
https://leetcode.com/problems/alphabet-board-path/
给定如图所示的棋盘,左上角坐标视为
(
0
,
0
)
(0,0)
(0,0),向下和向右是正方向。给定一个长
n
n
n小写英文字符串
s
s
s,要求返回一个棋盘中的路径,路径中'U', 'D', 'L', 'R'
分别代表上下左右走一步,而'!'
代表取当前位置的字符,使得路径走完恰好就取到了整个字符串
s
s
s。返回长度最小的任意一条路径。路径不能走出界。
两个字母之间的最短路径其实是确定的(每一步的方向可能不同,但如果按照上下左右这四个方向的先后次序走,则路径是唯一的),主要需要注意的是出发或到达的点是'z'
的时候,路径要特殊构造一下(因为不能出界)。代码如下:
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class Solution {
public String alphabetBoardPath(String target) {
// 存一下每个字母的坐标
Map<Character, int[]> map = new HashMap<>();
for (char ch = 'a', i = 0; ch <= 'z'; ch++, i++) {
map.put(ch, new int[]{i / 5, i % 5});
}
int[] cur = {0, 0};
StringBuilder sb = new StringBuilder();
for (int i = 0; i < target.length(); i++) {
char ch = target.charAt(i);
int[] next = map.get(ch);
sb.append(buildPath(cur, next, map)).append('!');
cur = next;
}
return sb.toString();
}
private String buildPath(int[] cur, int[] next, Map<Character, int[]> map) {
if (Arrays.equals(cur, next)) {
return "";
}
char x = 0, y = 0;
x = cur[0] < next[0] ? 'D' : 'U';
y = cur[1] < next[1] ? 'R' : 'L';
StringBuilder sb = new StringBuilder();
// 如果起点是z,那么路径一定要先上下再左右;否则先左右后上下
if (Arrays.equals(map.get('z'), cur)) {
move(sb, Math.abs(cur[0] - next[0]), x);
move(sb, Math.abs(cur[1] - next[1]), y);
} else {
move(sb, Math.abs(cur[1] - next[1]), y);
move(sb, Math.abs(cur[0] - next[0]), x);
}
return sb.toString();
}
private void move(StringBuilder sb, int step, char l) {
for (int i = 0; i < step; i++) {
sb.append(l);
}
}
}
时间复杂度 O ( n ) O(n) O(n),空间 O ( 1 ) O(1) O(1)。