数组中的最短非公共子字符串
难度:
标签:
题目描述
You are given an array arr
of size n
consisting of non-empty strings.
Find a string array answer
of size n
such that:
answer[i]
is the shortest substring ofarr[i]
that does not occur as a substring in any other string inarr
. If multiple such substrings exist,answer[i]
should be the lexicographically smallest. And if no such substring exists,answer[i]
should be an empty string.
Return the array answer
.
Example 1:
Input: arr = ["cab","ad","bad","c"] Output: ["ab","","ba",""] Explanation: We have the following: - For the string "cab", the shortest substring that does not occur in any other string is either "ca" or "ab", we choose the lexicographically smaller substring, which is "ab". - For the string "ad", there is no substring that does not occur in any other string. - For the string "bad", the shortest substring that does not occur in any other string is "ba". - For the string "c", there is no substring that does not occur in any other string.
Example 2:
Input: arr = ["abc","bcd","abcd"] Output: ["","","abcd"] Explanation: We have the following: - For the string "abc", there is no substring that does not occur in any other string. - For the string "bcd", there is no substring that does not occur in any other string. - For the string "abcd", the shortest substring that does not occur in any other string is "abcd".
Constraints:
n == arr.length
2 <= n <= 100
1 <= arr[i].length <= 20
arr[i]
consists only of lowercase English letters.
代码结果
运行时间: 125 ms, 内存: 16.7 MB
/*
* 思路:
* 使用Java Stream API来实现相同的逻辑。
* 对于每个字符串,找到它的所有子字符串,
* 然后检查这些子字符串是否存在于其他字符串中。
* 如果某个子字符串不在其他字符串中存在,
* 则为该字符串找到的最短且字典序最小的子字符串。
* 否则返回空字符串。
*/
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class UniqueSubstringStream {
public static String[] findShortestUniqueSubstring(String[] arr) {
return IntStream.range(0, arr.length)
.mapToObj(i -> findUniqueSubstring(arr, i))
.toArray(String[]::new);
}
private static String findUniqueSubstring(String[] arr, int index) {
String str = arr[index];
List<String> substrings = IntStream.range(0, str.length())
.boxed()
.flatMap(i -> IntStream.range(i + 1, str.length() + 1)
.mapToObj(j -> str.substring(i, j)))
.sorted(Comparator.comparingInt(String::length).thenComparing(Comparator.naturalOrder()))
.collect(Collectors.toList());
return substrings.stream()
.filter(sub -> isUnique(sub, arr, index))
.findFirst()
.orElse("");
}
private static boolean isUnique(String sub, String[] arr, int excludeIndex) {
return Arrays.stream(arr)
.filter(s -> !s.equals(arr[excludeIndex]))
.noneMatch(s -> s.contains(sub));
}
public static void main(String[] args) {
String[] arr = {"cab", "ad", "bad", "c"};
System.out.println(Arrays.toString(findShortestUniqueSubstring(arr)));
}
}
解释
方法:
此题解采用了一种有效的方法来查找每个字符串中最短的、不是其他任何字符串子串的子字符串。方法包括创建一个哈希表来存储每个子字符串及其所属的原始字符串索引。对于数组中的每个字符串,生成所有可能的子字符串,并使用哈希表记录它们。如果一个子字符串已经存在且来自不同的字符串,则标记为公共子串。遍历完所有字符串后,再次检查哈希表中记录的子字符串,为每个字符串选择最短且字典序最小的非公共子字符串。
时间复杂度:
O(n * L^2)
空间复杂度:
O(n * L^2)
代码细节讲解
🦆
为什么将所有可能的子字符串都添加到哈希表中,而不是仅添加特定长度的子字符串?
▷🦆
你是如何处理哈希表中已存在的子字符串来标记为公共子字符串的?详细解释一下这个过程。
▷🦆
在最后选取每个字符串的最短且字典序最小的非公共子字符串时,如何确保选取的是全局最优解?
▷