给两个字符串s1和s2,给出一个算法来查找S1中的所有字符,这些字符也在S2中

时间:2010-09-21 09:17:11

标签: algorithm

示例:

S1:abcde S2:cdef

答案:cde

10 个答案:

答案 0 :(得分:6)

假设与潜在的字符串长度相比,字符集很小且有限,这是合理的。因此,例如处理8位字符(在粗略的C ++伪代码中):

bool in_a[256] = { false };
bool in_b[256] = { false };
for (int i = 0; i < a.size(); ++i)
    in_a[a[i]] = true;
for (int i = 0; i < b.size(); ++i)
    in_b[b[i]] = true;
// and in_a and in_b
for (int i = 0; i < b.size(); ++i)
    if (in_a[i] && in_b[i])
    {
        std::cout << i;
        if (isprint(i)) std::cout << '\'' << (char)i << '\'';
        std::cout << ' ';
    }
std::cout << '\n';

请注意,使用哈希表而不是数组是一个巨大的浪费时间(除非处理说32位字符表示)。

Yordan的评论中提出的简化实现如下。这避免了最终循环从0..255并且只需要一个跟踪数组。结果的顺序是未排序的。

#include <vector>
#include <iostream>

int main()
{
    std::string a = "abdcdefg";
    std::string b = "byfdz";
    bool track[256] = { false };
    for (int i = 0; i < a.size(); ++i)
        track[a[i]] = true;
    for (int i = 0; i < b.size(); ++i)
        if (track[b[i]])
        {
            track[b[i]] = false; // don't match again
            std::cout << (int)b[i];
            if (isprint(b[i])) std::cout << " \'" << (char)(b[i]) << "\'";
            std::cout << ' ';
        }
    std::cout << '\n';
}

答案 1 :(得分:4)

使用某种set data structure:用S1的每个字符填充集合。然后检查S2中的每个字符是否在集合中。

根据实现情况,集合上的插入和查找仅花费O(1)。

答案 2 :(得分:1)

将两个字符串排序为相同的顺序,然后在比较每个项目的同时线性扫描两个序列,如果不相同,则使用较低值字符递增序列。它应该是O(N log N)。

答案 3 :(得分:1)

离开我的头顶,我将两个字符串分成一个字符数组并对它们进行排序。然后,我将通过一个数组,并检查每个字符是否在另一个数组中。将两个数组排序意味着在获得结果时只需要遍历每个数组一次。我不确定排序的开销是否会使它更有效率。

我认为可能相关的事情是:

1)字符串中的重复字符 - 被解雇,因为我无法想到一个过滤掉重复项的有效方法。

2)不同的案例可能被认为是平等的(例如A和a被认为是相同的) - 没有被要求,但是一个toupper或tolower将解决这个问题。

答案 4 :(得分:0)

在ruby中,使用哈希表的算法O(len(s1)+ len(s2))

require 'jcode'
def toto(s1, s2)
    contains={}
    s2.each_char { |x| contains[x]=1 }
    res=""
    s1.each_char do |x|
        if contains[x]==1
            res<<=x
        end
    end
    return res
end

puts toto("abcde","cdef")

答案 5 :(得分:0)

使用哈希映射,其中键是第一个字符串的字符,值是从零开始的int。然后只需查找S2中的每个字符,如果查找成功,则递增该值。设置哈希映射是O(n),每个查找都是O(1)。最坏情况表现为O(2n),相当于O(n)。

仅供参考,你可以在现实世界中Boost unordered_map container

答案 6 :(得分:0)

var commonChars = S1.Intersect(S2);

编辑:这是来自System.Linq - 它是一种算法 - 它是单一的单行算法。 : - )

答案 7 :(得分:0)

另一种方法现在向我表明......在伪代码中,因为它更容易解释:

for each (character in stringA)
{
    charHashTable[character] = 1

}
for each (character in stringB)
{
    if (charHashTable[character]==1)
        if (!OutputArray.Contains(character))
            OutputArray.Add(character)
}

我不是百分之百确定将内容放入哈希数组的性能特征,但我发现这可能是一种更好的方法来有效地查找字符是否在一个数组中而不是对其进行排序并以此方式进行。如果有人可以评论这种方法对两种字符串的排序的性能优势,我会非常感兴趣。

答案 8 :(得分:0)

如果您知道字符串组成的唯一字符数(例如:如果仅使用小写字符,则a-z表示26个唯一符号),则使用符号作为索引,使用该大小的数组。迭代每个字符串,并为每个字符串增加相应的数组位置(比如你找到b然后是[1] ++)。最后计算具有值2的阵列位置的数量。当然,该解决方案具有更大的空间复杂度。

编辑:计算具有2个或更多值的数组位置数。 (感谢Chris指出早期答案中的缺陷)

答案 9 :(得分:0)

尝试在Python中执行此操作:

char_in_s2=''

for char in s1:

      if char in s2:
         char_in_s2=char_in_s2+char

print(char_in_s2)