我在Rust中学习字符串。我想实现函数来计算字符串列表中的长公共前缀。
我的准则
impl Solution {
pub fn get_common_prefix(s1: &String, s2: &String) -> String {
let mut idx: usize = 0;
if s1.len() > s2.len() {
std::mem::swap(&mut s1, &mut s2);
}
while idx < s1.len() && s1.chars().nth(idx) == s2.chars().nth(idx) {
idx += 1;
}
return s1[0..idx].to_string();
}
pub fn longest_common_prefix(mut strs: Vec<String>) -> String {
strs.sort();
let mut longest_pref = strs[0];
for i in 0..strs.len() {
longest_pref = Self::get_common_prefix(&longest_pref, &strs[i]);
}
return longest_pref;
}
}
我有一个错误。你能帮我修一下吗?
Line 5, Char 37: lifetime mismatch (solution.rs)
|
2 | pub fn get_common_prefix(s1: &String, s2: &String) -> String {
| ------- ------- these two types are declared with different lifetimes...
...
5 | std::mem::swap(&mut s1, &mut s2);
| ^^^^^^^ ...but data from `s2` flows into `s1` here
我在这里阅读了关于生命周期的文章https://doc.rust-lang.org/rust-by-example/scope/lifetime.html,但没有成功
2条答案
按热度按时间ffscu2ro1#
如果您尝试显式显示隐式生存期,您将获得
get_common_prefix
的以下签名:特别是,你不能交换这两个值,因为两个借款的持续时间都没有对方长。相反,你可以
这样做可以解决问题,但也会抛出许多其他错误,因为您的代码中还有其他问题。让我们一个一个地看。
首先,它现在会抱怨
std::mem::swap(&mut s1, &mut s2);
是非法的,因为然而,Rust非常好,它告诉你在这种情况下该怎么做,将
s1
和s2
都声明为可变的:函数
get_common_prefix
现在是正确的,但是在longest_common_prefix
中仍然有一个错误:问题是,您从
strs
中获取strs[0]
,但没有删除它,这是非法的,因为第一个字符串现在将被拥有两次(一次由longest_pref
拥有,一次由strs
拥有)。一种解决方案是实际使用
strs[0]
,其中swap_remove
(这在从向量中删除元素时非常有效,假设我们不关心元素的顺序):这个可以但是。。这是非常低效的,有几个原因。首先,即使它不是一个可怕的性能损失,但在函数签名中包含
&String
几乎总是错误的,因为您只能使用它(实际上,Rust会为你做这件事,所以你可能没有意识到)是将Deref
转换为&str
,这基本上是相同的,少了一个间接(因为你可以看到String
作为指向str
的指针)。所以我们应该直接写出来此外,返回
String
是没有意义的,因为它需要分配,当我们可以返回一个slice在该字符串上(因为我们取子字符串):现在,为了使其工作,我们还需要调整
longest_common_prefix
以使用字符串切片:我们回到了
strs
的第一个元素,而不是 * 获取它。此外,我们只执行一次分配到String
中,实际上我们必须返回String
。还有一些其他的优化工作要做。首先,排序
strs
是无用的,它不会改变longest_common_prefix
的结果,所以我们可以删除它接下来,
s1.chars().nth(i)
非常慢(Θ(i)
)。一种更有效的方法是重用相同的迭代器(s1.chars()
),并在每一步推进它,如下所示.zip()
不会从最长的字符串中取出任何剩余字符,因此我们实际上可以完全删除swap
,得到注意:如@SebastianRedi所示,
idx
不应该增加1
,而应该增加c1.len_utf8()
,因为在索引字符串时,索引是以字节表示的,而不是以字符表示的,并且某些字符的长度超过一个字节。yc0p9oo02#
作为对另一个答案的评论中的讨论的回应,下面是
longest_common_prefix()
的一个实现,它正确地使用了扩展的字素集群,并适用于字符串切片的任意迭代器:Unicode标准化仍然需要在此函数之外执行,例如就像这样:
上面的代码使用了这些依赖项: