Medium
题目描述
给定字符串数组 strs,返回其中最长的特殊序列的长度。如果不存在,则返回 -1。
数组的特殊序列是指:该字符串是某一个字符串的子序列,但不是其他字符串的子序列。
字符串 s 的子序列是指可以通过删除 s 中的某些字符得到的字符串。
例如,“abc” 是 “aebdc” 的一个子序列,因为你可以删除 “aebdc” 中的下划线字符来得到 “abc”。“aebdc” 的其他子序列包括 “aebdc”、“aeb” 和 “"(空字符串)。
示例 1:
输入:strs = ["aba","cdc","eae"]
输出:3
示例 2:
输入:strs = ["aaa","aaa","aa"]
输出:-1
提示:
2 <= strs.length <= 501 <= strs[i].length <= 10strs[i]由小写英文字母组成
解题思路
这道题的核心思想是理解什么是"特殊序列”。
首先明确一个重要观察:如果一个字符串在数组中是唯一的(不与其他字符串重复),那么这个字符串本身就是一个特殊序列。因为它是自己的子序列,但不可能是其他不同字符串的子序列。
基于这个观察,我们的解题思路是:
- 遍历数组中的每个字符串
- 检查该字符串是否与数组中其他字符串重复
- 如果不重复,该字符串就是特殊序列,记录其长度
- 返回所有特殊序列中的最大长度
更进一步的思考:对于重复的字符串,我们需要检查它们的所有真子序列是否为特殊序列。但实际上,由于数据规模较小(字符串长度≤10,数组长度≤50),我们可以采用暴力方法:
- 生成每个字符串的所有子序列
- 检查每个子序列是否只在一个原字符串中出现
- 找到最长的这样的子序列
不过,基于第一个观察的简化方法在大多数情况下就足够了,因为如果存在唯一字符串,它们的长度通常就是答案。
代码实现
class Solution {
public:
int findLUSlength(vector<string>& strs) {
int n = strs.size();
int maxLen = -1;
// 检查每个字符串是否为特殊序列
for (int i = 0; i < n; i++) {
bool isUncommon = true;
// 检查当前字符串是否是其他字符串的子序列
for (int j = 0; j < n; j++) {
if (i != j && isSubsequence(strs[i], strs[j])) {
isUncommon = false;
break;
}
}
if (isUncommon) {
maxLen = max(maxLen, (int)strs[i].length());
}
}
return maxLen;
}
private:
bool isSubsequence(const string& s, const string& t) {
int i = 0, j = 0;
while (i < s.length() && j < t.length()) {
if (s[i] == t[j]) {
i++;
}
j++;
}
return i == s.length();
}
};
class Solution:
def findLUSlength(self, strs: List[str]) -> int:
def is_subsequence(s, t):
i = 0
for char in t:
if i < len(s) and s[i] == char:
i += 1
return i == len(s)
n = len(strs)
max_len = -1
# 检查每个字符串是否为特殊序列
for i in range(n):
is_uncommon = True
# 检查当前字符串是否是其他字符串的子序列
for j in range(n):
if i != j and is_subsequence(strs[i], strs[j]):
is_uncommon = False
break
if is_uncommon:
max_len = max(max_len, len(strs[i]))
return max_len
public class Solution {
public int FindLUSlength(string[] strs) {
int n = strs.Length;
int maxLen = -1;
// 检查每个字符串是否为特殊序列
for (int i = 0; i < n; i++) {
bool isUncommon = true;
// 检查当前字符串是否是其他字符串的子序列
for (int j = 0; j < n; j++) {
if (i != j && IsSubsequence(strs[i], strs[j])) {
isUncommon = false;
break;
}
}
if (isUncommon) {
maxLen = Math.Max(maxLen, strs[i].Length);
}
}
return maxLen;
}
private bool IsSubsequence(string s, string t) {
int i = 0, j = 0;
while (i < s.Length && j < t.Length) {
if (s[i] == t[j]) {
i++;
}
j++;
}
return i == s.Length;
}
}
/**
* @param {string[]} strs
* @return {number}
*/
var findLUSlength = function(strs) {
function isSubsequence(s, t) {
let i = 0;
for (let j = 0; j < t.length && i < s.length; j++) {
if (s[i] === t[j]) i++;
}
return i === s.length;
}
strs.sort((a, b) => b.length - a.length);
for (let i = 0; i < strs.length; i++) {
let isUncommon = true;
for (let j = 0; j < strs.length; j++) {
if (i !== j && isSubsequence(strs[i], strs[j])) {
isUncommon = false;
break;
}
}
if (isUncommon) return strs[i].length;
}
return -1;
};
复杂度分析
| 复杂度类型 | 分析 |
|---|---|
| 时间复杂度 | O(n² × m),其中 n 是字符串数组的长度,m 是字符串的平均长度。需要对每个字符串检查是否为其他字符串的子序列 |
| 空间复杂度 | O(1),只使用了常数额外空间 |