将单词恢复初始状态所需的最短时间 I
难度:
标签:
题目描述
You are given a 0-indexed string word
and an integer k
.
At every second, you must perform the following operations:
- Remove the first
k
characters ofword
. - Add any
k
characters to the end ofword
.
Note that you do not necessarily need to add the same characters that you removed. However, you must perform both operations at every second.
Return the minimum time greater than zero required for word
to revert to its initial state.
Example 1:
Input: word = "abacaba", k = 3 Output: 2 Explanation: At the 1st second, we remove characters "aba" from the prefix of word, and add characters "bac" to the end of word. Thus, word becomes equal to "cababac". At the 2nd second, we remove characters "cab" from the prefix of word, and add "aba" to the end of word. Thus, word becomes equal to "abacaba" and reverts to its initial state. It can be shown that 2 seconds is the minimum time greater than zero required for word to revert to its initial state.
Example 2:
Input: word = "abacaba", k = 4 Output: 1 Explanation: At the 1st second, we remove characters "abac" from the prefix of word, and add characters "caba" to the end of word. Thus, word becomes equal to "abacaba" and reverts to its initial state. It can be shown that 1 second is the minimum time greater than zero required for word to revert to its initial state.
Example 3:
Input: word = "abcbabcd", k = 2 Output: 4 Explanation: At every second, we will remove the first 2 characters of word, and add the same characters to the end of word. After 4 seconds, word becomes equal to "abcbabcd" and reverts to its initial state. It can be shown that 4 seconds is the minimum time greater than zero required for word to revert to its initial state.
Constraints:
1 <= word.length <= 50
1 <= k <= word.length
word
consists only of lowercase English letters.
代码结果
运行时间: 15 ms, 内存: 16.2 MB
// Java Stream Solution
// 思路:利用流操作进行字符串转换和比较。
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class SolutionStream {
public int shortestTimeToRestore(String word, int k) {
int n = word.length();
return IntStream.rangeClosed(1, n)
.filter(t -> IntStream.range(0, n)
.mapToObj(i -> word.charAt((i + k * t) % n))
.collect(Collectors.joining())
.equals(word))
.findFirst()
.orElse(-1);
}
}
解释
方法:
本题解通过判断字符串的旋转周期来解决问题。首先计算将整个字符串翻转一遍所需要的最少次数,即 n / k 上取整。然后,从 k 位置开始,以 k 为步长,检查 word 的后缀是否与 word 的前缀相匹配。如果在某个点 i 处,word[i:](即从 i 开始到末尾的子串)与 word[:n-i](即从开头到 n-i 位置的子串)相同,这说明找到了一个周期,word 可以在 i // k 次操作后恢复到初始状态。如果没有找到这样的周期,返回 n / k 的上取整结果。
时间复杂度:
O(n^2 / k)
空间复杂度:
O(1)
代码细节讲解
🦆
为什么在每次操作后选择在字符串末尾添加与移除的字符数量相同的任意字符,并不要求与移除的字符相同?
▷🦆
算法中使用的`math.ceil(n / k)`是基于什么考虑?为什么不是`n % k == 0`时直接使用`n / k`?
▷🦆
在算法中,是如何确定从`k`位置开始,以`k`为步长进行检查的?这种方法是否可能遗漏某些周期性的匹配可能?
▷