题目链接:1320. Minimum Distance to Type a Word Using Two Fingers
You have a keyboard layout as shown above in the XY plane, where each English uppercase letter is located at some coordinate, for example, the letter A is located at coordinate (0,0), the letter B is located at coordinate (0,1), the letter P is located at coordinate (2,3) and the letter Z is located at coordinate (4,1).@pfdvnah
Given the string word, return the minimum total distance to type such string using only two fingers. The distance between coordinates (x1,y1) and (x2,y2) is |x1 - x2| + |y1 - y2|.
Note that the initial positions of your two fingers are considered free so don’t count towards your total distance, also your two fingers do not have to start at the first letter or the first two letters.
Example 1:
Input: word = "CAKE"
Output: 3
Explanation:
Using two fingers, one optimal way to type "CAKE" is:
Finger 1 on letter 'C' -> cost = 0
Finger 1 on letter 'A' -> cost = Distance from letter 'C' to letter 'A' = 2
Finger 2 on letter 'K' -> cost = 0
Finger 2 on letter 'E' -> cost = Distance from letter 'K' to letter 'E' = 1
Total distance = 3
Example 2:
Input: word = "HAPPY"
Output: 6
Explanation:
Using two fingers, one optimal way to type "HAPPY" is:
Finger 1 on letter 'H' -> cost = 0
Finger 1 on letter 'A' -> cost = Distance from letter 'H' to letter 'A' = 2
Finger 2 on letter 'P' -> cost = 0
Finger 2 on letter 'P' -> cost = Distance from letter 'P' to letter 'P' = 0
Finger 1 on letter 'Y' -> cost = Distance from letter 'A' to letter 'Y' = 4
Total distance = 6
Example 3:
Input: word = "NEW"
Output: 3
Example 4:
Input: word = "YEAR"
Output: 7
Constraints:
2 <= word.length <= 300
- Each
word[i]
is an English uppercase letter.
题解
输入一个字符有两种情况:左指输入,右指输入。@wowpH
每次输入时的两指有 26×26 种情况当要输入一个字符时,遍历这 26×26 种情况,在加上当前移动的距离即可得到当前情况的总距离。以此推出所有字符的总距离。
用一个三维数组 dp[i][L][R]
表示输入第 i
个字符后,左指在键位 L
的位置,右指在键位 R
的位置时的已经移动的总距离。
例如:输入的字符串为 CAKE
,
dp[1][2][R]
表示左指输入 C
,右指在键位 R
时的总距离。在左指输入 C
之前,左指有26种情况,右指也有26种情况,由于是左指输入,所以右指位置不影响此次结果,显然当左指在 C
键位时输入 C
是最小距离为0(dp[1][2][R] = dp[0][2][R] + distance(2, 2)
)
状态转移方程:
左指:
d
p
[
i
]
[
v
]
[
R
]
=
d
p
[
i
−
1
]
[
L
]
[
R
]
+
d
i
s
t
a
n
c
e
(
L
,
v
)
dp[i][v][R] = dp[i - 1][L][R] + distance(L, v)
dp[i][v][R]=dp[i−1][L][R]+distance(L,v)
右指:
d
p
[
i
]
[
L
]
[
v
]
=
d
p
[
i
−
1
]
[
L
]
[
R
]
+
d
i
s
t
a
n
c
e
(
R
,
v
)
dp[i][L][v] = dp[i - 1][L][R] + distance(R, v)
dp[i][L][v]=dp[i−1][L][R]+distance(R,v)
v v v 表示当前字符, d i s t a n c e ( a , b ) distance(a, b) distance(a,b) 表示从键位 a a a 到键位 b b b 移动的距离。
时间复杂度:三层for循环,
O
(
N
∗
26
∗
26
)
O(N*26*26)
O(N∗26∗26)
空间复杂度:
O
(
1
)
O(1)
O(1)
Java代码
// 2020-1-15 12:14:33
class Solution {
public int minimumDistance(String word) {
int[][][] dp = new int[300][26][26];
// 输入0个字符的时候距离为0,不用赋值为Integer.MAX_VALUE
for (int i = 1; i < 300; ++i) {
for (int L = 0; L < 26; ++L) {
for (int R = 0; R < 26; ++R) {
dp[i][L][R] = Integer.MAX_VALUE;// 初始化为最大值
}
}
}
char[] arr = word.toCharArray();// 转成数组
int v = 0;
// 遍历所有字符
for (int i = 1; i <= arr.length; ++i) {
v = arr[i - 1] - 'A';
// 遍历左指所在的键位
for (int L = 0; L < 26; ++L) {
// 遍历右指所在的键位
for (int R = 0; R < 26; ++R) {
// 检查手指的这种情况是否存在
if (dp[i - 1][L][R] != Integer.MAX_VALUE) {
// 移动左指
dp[i][v][R] = Math.min(dp[i][v][R],
dp[i - 1][L][R] + distance(L, v));
// 移动右指
dp[i][L][v] = Math.min(dp[i][L][v],
dp[i - 1][L][R] + distance(R, v));
}
}
}
}
int res = Integer.MAX_VALUE;
for (int L = 0; L < 26; ++L) {
for (int R = 0; R < 26; ++R) {
// 最后一个字符由左指输入
res = Math.min(res, dp[arr.length][v][R]);
// 最后一个字符由右指输入
res = Math.min(res, dp[arr.length][L][v]);
}
}
return res;
}
// 计算距离
private int distance(int a, int b) {
return Math.abs(a / 6 - b / 6) + Math.abs(a % 6 - b % 6);
}
}
原文链接:https://blog.csdn.net/pfdvnah/article/details/103984775