Medium
题目描述
给你一个字符串 word 和一个整数 numFriends。
Alice 为她的 numFriends 个朋友组织了一个游戏。游戏有多轮,每轮中:
word被分割成numFriends个非空字符串,且与之前任何一轮的分割方式都不相同。- 所有分割后的字符串都被放入一个盒子中。
请找出所有轮次结束后,盒子中字典序最大的字符串。
示例 1:
输入:word = "dbca", numFriends = 2
输出:"dbc"
解释:
所有可能的分割方式为:
- "d" 和 "bca"
- "db" 和 "ca"
- "dbc" 和 "a"
示例 2:
输入:word = "gggg", numFriends = 4
输出:"g"
解释:
唯一可能的分割方式为:"g", "g", "g", "g"
约束条件:
1 <= word.length <= 5 * 10³word仅由小写英文字母组成1 <= numFriends <= word.length
提示:
- 找到从每个索引开始的长度不超过
n - numFriends + 1的字典序最大子字符串。
解题思路
这道题的关键是理解分割的规律和找到最优策略。
解题思路
当我们将长度为 n 的字符串分割成 numFriends 段时,为了让某一段尽可能长(从而可能获得字典序更大的字符串),我们需要让其他段尽可能短。由于每段至少要有一个字符,所以某一段的最大长度为 n - numFriends + 1。
关键观察:
- 如果
numFriends = 1,整个字符串就是答案 - 否则,我们可以选择任意起始位置,然后取长度不超过
n - numFriends + 1的子字符串 - 为了得到字典序最大的结果,我们需要遍历所有可能的起始位置
具体策略:
- 对于每个可能的起始位置 i,我们可以取从位置 i 开始、长度为
min(maxLen, n - i)的子字符串 - 其中
maxLen = n - numFriends + 1 - 在所有这些子字符串中选择字典序最大的
优化:我们可以先找到字符串中最大的字符,只考虑以该字符开头的子字符串,这样可以减少比较次数。
代码实现
class Solution {
public:
string answerString(string word, int numFriends) {
int n = word.length();
if (numFriends == 1) {
return word;
}
int maxLen = n - numFriends + 1;
string result = "";
// 找到最大字符
char maxChar = *max_element(word.begin(), word.end());
for (int i = 0; i < n; i++) {
if (word[i] == maxChar) {
int len = min(maxLen, n - i);
string candidate = word.substr(i, len);
if (candidate > result) {
result = candidate;
}
}
}
return result;
}
};
class Solution:
def answerString(self, word: str, numFriends: int) -> str:
n = len(word)
if numFriends == 1:
return word
max_len = n - numFriends + 1
result = ""
# 找到最大字符
max_char = max(word)
for i in range(n):
if word[i] == max_char:
length = min(max_len, n - i)
candidate = word[i:i + length]
if candidate > result:
result = candidate
return result
public class Solution {
public string AnswerString(string word, int numFriends) {
int n = word.Length;
if (numFriends == 1) {
return word;
}
int maxLen = n - numFriends + 1;
string result = "";
// 找到最大字符
char maxChar = word.Max();
for (int i = 0; i < n; i++) {
if (word[i] == maxChar) {
int len = Math.Min(maxLen, n - i);
string candidate = word.Substring(i, len);
if (string.Compare(candidate, result) > 0) {
result = candidate;
}
}
}
return result;
}
}
var answerString = function(word, numFriends) {
if (numFriends === 1) {
return word;
}
const n = word.length;
const maxLen = n - numFriends + 1;
let result = "";
for (let i = 0; i < n; i++) {
const substring = word.substring(i, Math.min(i + maxLen, n));
if (substring > result) {
result = substring;
}
}
return result;
};
复杂度分析
| 复杂度类型 | 分析 |
|---|---|
| 时间复杂度 | O(n²),其中 n 是字符串长度。需要遍历字符串找到最大字符的所有位置,对于每个位置可能需要O(n)时间进行字符串比较 |
| 空间复杂度 | O(n),用于存储候选字符串和结果字符串 |