leetcode
leetcode 2701 ~ 2750
将单词恢复初始状态所需的最短时间 II

将单词恢复初始状态所需的最短时间 II

难度:

标签:

题目描述

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 of word.
  • Add any k characters to the end of word.

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 <= 106
  • 1 <= k <= word.length
  • word consists only of lowercase English letters.

代码结果

运行时间: 81 ms, 内存: 16.8 MB


/*
 * 思路:
 * 1. 利用Java Streams进行操作。
 * 2. 创建一个Stream来处理字符串操作并判断何时恢复到初始状态。
 */

import java.util.stream.Stream;

public class Solution {
    public int restoreWord(String word, int k) {
        final int n = word.length();
        return Stream.iterate(word, w -> w.substring(k) + w.substring(0, k))
                .limit(n)
                .mapToInt(w -> w.equals(word) ? 1 : 0)
                .reduce(0, Integer::sum);
    }
}

解释

方法:

此题解采用二分查找的方法来确定最短时间。首先,初始化时间的可能范围为 [1, ceil(n/k)],其中 n 是字符串长度。在每次迭代中,计算中间值 c 作为当前秒数尝试,计算剩余长度 t = n - c * k。接着,尝试在字符串中找到前缀 word[:t] 和后缀 word[-t:] 的匹配位置。如果找到合适的匹配,尝试缩小时间范围;如果没有找到,增加时间尝试。最终确定出最小时间。特别注意边界条件的处理,例如 t <= 0 的情况,以及在字符串中寻找匹配的过程中的边界检查。

时间复杂度:

O(n log(n/k))

空间复杂度:

O(n)

代码细节讲解

🦆
在解法中使用二分查找的思路是基于什么原理?为什么这种方法适用于这个问题?
二分查找的思路基于将问题的解空间分割成两部分,一部分保证不包含解,另一部分可能包含解,然后逐渐缩小可能包含解的空间。在本题中,解空间是可能的最短时间,范围从1到ceil(n/k)。二分查找适用于这个问题因为时间越长,恢复初始状态所需满足的条件就越容易达成,所以存在一个时间阈值,小于这个阈值的时间无法恢复到初始状态,而大于等于这个阈值的时间可以。这样,时间和是否能恢复状态之间存在一个单调关系,适合使用二分查找来快速定位到这个阈值,找到最短的时间。
🦆
在每次二分查找迭代中,如何确定是否已经找到了合适的匹配位置?
在每次二分查找迭代中,通过设定一个中间值c来尝试是否可以在c秒内恢复到初始状态。这通过计算剩余长度t = n - c * k,并检查字符串中是否存在与word[:t]和word[-t:]匹配的位置来决定。如果在当前时间c内可以找到这样的匹配位置,则尝试减小时间尝试,即调整上界b = c;如果找不到,则增加时间尝试,调整下界a = c + 1。这样不断调整搜索范围的上下界,直到找到最小的满足条件的c。
🦆
题解中提到的边界条件`t <= 0`的具体含义是什么?在这种情况下应该如何处理?
边界条件`t <= 0`表示试图在c秒内恢复单词到初始状态时,剩余的未处理长度t变成了非正数,即剩余的字符数量不足以进行进一步的比较。这种情况通常发生在c值过大时,说明试图在这么短的时间内完成任务是不可能的。在这种情况下,应该处理为直接返回当前的时间尝试值a,因为此时已经没有必要再寻找更大的时间值,而是应该确认在此时间内任务已经无法完成,因此返回当前最小尝试时间。

相关问题