你可以采用几种方法,这里提供了两个选项:
- 构建第一个字符串的一组字符,并检查第二个字符串是否包含该组字符中的任何一个[O(n + m)]
- 迭代第一个字符串的字符,并检查第二个字符串是否包含其中任何一个[O(n * m)]
我决定使用
HashSet
,但如果你只关心ascii(因此限制在256个可能性内),你可以使用基本数组。
use std::collections::HashSet;
fn share_char(a: &str, b: &str) -> bool {
let (shorter, longer) = if a.len() > b.len() {
(b, a)
} else {
(a, b)
};
let set: HashSet<char> = shorter.chars().collect();
longer.chars().any(|c| set.contains(&c))
}
#[test]
fn test() {
let str1 = "abcdef";
let str2 = "the quick brown fox";
let str3 = "hijk";
assert!(share_char(str1, str2));
assert!(!share_char(str1, str3));
}
https://play.rust-lang.org/?version=stable&mode=debug&edition=2015&gist=76567b94d3bd15b37e33acb9a8d701d5
编辑:改用collect。
编辑2:我想解释一下为什么我做了较短/较长的检查,以及为什么我没有建立两个集合。
将元素插入到HashSet
中比仅迭代字符串的字符更耗费资源。这意味着从长字符串构建集合与从短字符串构建集合之间存在差异。很可能这种差异是可以忽略不计的,因为您的字符串长度很可能相似。
这种资源消耗的差异也是我不建立第二个集合的原因。我们不仅节省了插入成本,还可以节省一些迭代次数,因为如果找到匹配项,我们的any
将会短路。
编辑3:另外,如果您只想检查一个字符串是否包含给定字符集中的任何字符,则应使用模式匹配。
str1.chars().any(|c| match c {
'a' | 'd' | 'f' | 'e' => true,
_ => false,
});
这将比使用静态Set甚至更高效。
结尾而不是
!= 0`。 - Sven Marnach