从2个字符串中删除重复字符

时间:2014-12-15 00:20:25

标签: java algorithm

我需要从字符串中删除重复的字符。我使用像这样的BitSet实现了它

private static String removeDup(String s1, String s2) {
    BitSet bitSet = new BitSet(26);
    char[] s1Chars = s1.toCharArray();

    for (char s1Char : s1Chars) {
        bitSet.set(s1Char);
    }

    char[] s2Chars = s2.toCharArray();
    StringBuilder sb = new StringBuilder();
    for (char s2Char : s2Chars) {
        if (bitSet.get(s2Char)) {
            //System.out.println("Duplicate " + s2Char);
        } else {
            sb.append(s2Char);
        }
    }

    return sb.toString();
}

虽然这种方法有效,但在时间和空间复杂性方面还有更好和最佳的方法吗?感谢

E.g。

  • 输入:"hello", "world"
  • 输出:wrd

1 个答案:

答案 0 :(得分:1)

您的实现的一个问题是它需要多个存储位等于字符串中的最高字符值,并且仅适用于BMP字符。请注意,字符a实际上对应于char值97.在分配BitSet的地方,您传递的是大小参数26,但这没有意义;但是值256可能会给你一些小的性能提升。

如果您在包含CJK表意文字的字符串上使用此功能,则可能使用BitSet最多8 kiB的存储空间。

如果您使用稀疏查找表(例如Set<Character>),则可以显着降低存储要求,但这会将运行时间从O(n)增加到O(n log n)。

另一个可能的改进是并行算法。然而,添加并行化只会使非常大的字符串更快,并且对于较小的字符串可能会显着变慢。在中,可以将其作为:

private static String removeDup(String s1, String s2) {
    Set<Integer> points = s1.codePoints().collect(Collectors.toSet());
    return s2.codePoints().parallel().filter(c->!points.contains(c))
        .collect(StringBuilder::new, StringBuilder::appendCodePoint,
            StringBuilder::append).toString();
}

这也有为BMP之外的角色工作的优势。