在Python中删除字符串中的重复项

时间:2010-02-18 07:09:37

标签: python algorithm

删除字符串中所有重复项的有效算法是什么?

例如: aaaabbbccdbdbcd

必填结果: abcd

19 个答案:

答案 0 :(得分:19)

您使用哈希表来存储当前发现的密钥(访问O(1)),然后循环遍历该数组。如果一个字符在哈希表中,则将其丢弃。如果没有将它添加到哈希表和结果字符串中。

总体而言:O(n)时间(和空间)。

天真的解决方案是在处理每个字符时搜索字符是结果字符串。那个O(n 2 )。

答案 1 :(得分:5)

这与问题密切相关:Detecting repetition with infinite input

根据您的输入,哈希表方法可能不是最佳的。 Hashtables有一定的开销(存储桶,入口对象)。与实际存储的char相比,这是一个巨大的开销。 (如果您的目标环境是Java,则更糟糕的是HashMap的类型为Map<Character,?>。)由于冲突,Hashtable访问的最坏情况运行时为O(n)。

您只需 8kb 也代表普通 BitSet 中的所有2字节unicode字符。如果您的输入字符集受到更多限制或使用压缩的BitSet(只要您有稀疏的BitSet),则可以优化此选项。对于BitSet,运行时性能将是有利的,它是O(1)。

答案 2 :(得分:4)

Python

>>> ''.join(set("aaaabbbccdbdbcd"))
'acbd'

如果需要保留订单

>>> q="aaaabbbccdbdbcd"                    # this one is not
>>> ''.join(sorted(set(q),key=q.index))    # so efficient
'abcd'

>>> S=set()
>>> res=""
>>> for c in "aaaabbbccdbdbcd":
...  if c not in S:
...   res+=c
...   S.add(c)
... 
>>> res
'abcd'

>>> S=set()
>>> L=[]
>>> for c in "aaaabbbccdbdbcd":
...  if c not in S:
...   L.append(c)
...   S.add(c)
... 
>>> ''.join(L)
'abcd'

python3.1

>>> from collections import OrderedDict
>>> ''.join(list(OrderedDict((c,0) for c in "aaaabbbccdbdbcd").keys()))
'abcd'

答案 3 :(得分:2)

保留一组256个“看过”的布尔值,每个可能的角色一个。 流你的字符串。如果您之前没有看过该字符,请输出该字符并为该字符设置“see”标志。

答案 4 :(得分:2)

只有在使用HashTable时才能在O(n)中执行此操作。代码如下 请注意 - 假设输入字符串中可能的字符数是 256

void removeDuplicates(char *str)
{
 int len = strlen(str); //Gets the length of the String
 int count[256] = {0};  //initializes all elements as zero
 int i;
     for(i=0;i<len;i++)
     {
        count[str[i]]++;  
        if(count[str[i]] == 1)
          printf("%c",str[i]);                  
     }     
}

答案 5 :(得分:2)

PHP algorythm - O(n):

function remove_duplicate_chars($str) {
    if (2 > $len = strlen($str)) {
        return $str;
    }
    $flags = array_fill(0,256,false);
    $flags[ord($str[0])]=true;
    $j = 1;
    for ($i=1; $i<$len; $i++) {
        $ord = ord($str[$i]);
        if (!$flags[$ord]) {
            $str[$j] = $str[$i];
            $j++;
            $flags[$ord] = true;
        }
    }
    if ($j<$i) { //if duplicates removed
        $str = substr($str,0,$j);
    }
    return $str;
}

echo remove_duplicate_chars('aaaabbbccdbdbcd'); // result: 'abcd'

答案 6 :(得分:1)

#include <iostream>
#include<string>
using namespace std;
#define MAX_SIZE 256

int main()
{
    bool arr[MAX_SIZE] = {false};

    string s;
    cin>>s;
    int k = 0;

    for(int i = 0; i < s.length(); i++)
    {
        while(arr[s[i]] == true && i < s.length())
        {
            i++;
        }
        if(i < s.length())
        {
            s[k]    = s[i];
            arr[s[k]] = true;
            k++;
        }
    }
    s.resize(k);

    cout << s<< endl; 

    return 0;
}

答案 7 :(得分:0)

在C中这就是我这样做的原因:O(n)及时,因为我们只有一个for循环。

void remDup(char *str)
{
    int flags[256] = { 0 };

    for(int i=0; i<(int)strlen(str); i++) {
        if( flags[str[i]] == 0 )
            printf("%c", str[i]);

        flags[str[i]] = 1;
    }
}

答案 8 :(得分:0)

也许使用内置的Python函数比那些“自制”函数更有效。像这样:

====================

注意:保持秩序

代码

string = "aaabbbccc"

product = reduce((lambda x,y: x if (y in x) else x+y), string)

print product

输出

abc

=======================

注意:订单被忽略

代码

string = "aaabssabcdsdwa"

str_uniq = ''.join(set(string))

print str_uniq

输出

acbdsw

答案 9 :(得分:0)

O(n)解决方案:

dict.iteritems()

答案 10 :(得分:0)

int main()    
{    
    std::string s = "aaacabbbccdbdbcd";

    std::set<char> set1;
    set1.insert(s.begin(), s.end());

    for(set<char>::iterator it = set1.begin(); it!= set1.end(); ++it)
    std::cout << *it;

    return 0;
}

std::set takes O(log n) to insert 

答案 11 :(得分:0)

获取前26个素数的列表.. 现在你可以将每个字符(a,b,c,d等)映射到每个素数..(按字母顺序表示a = 2,b = 3,c = 5等...或者取决于最常用的字符的相对丰度使用具有较低素数的字母表示e = 2,r = 3,a = 5等)...将该映射存储在整数数组中 int prime [26] ..

遍历字符串的所有字符

i=0;
int product = 1;
while(char[i] != null){
   if(product % prime[i] == 0)
      the character is already present delete it
   else
      product = product*prime[i];
}

该算法将在O(n)时间内工作..具有O(1)空间要求 当字符串中不同字符的数量较少时,它会很好用...其他明智的产品将超过“int”范围,我们必须妥善处理这种情况

答案 12 :(得分:0)

import java.util.HashSet;

public class RemoveDup {

    public static String Duplicate()
    {
        HashSet h = new HashSet();
        String value = new String("aaaabbbccdbdbcd");
        String finalString = new String();
        int stringLength = value.length();
        for (int i=0;i<=stringLength-1;i++)
        {
            if(h.add(value.charAt(i)))
            {
                finalString = finalString + (value.charAt(i));
            }


        }
        return finalString;

    }
public static void main(String[] args) {


        System.out.println(Duplicate());
    }
}

答案 13 :(得分:0)

C ++ - O(n)时间,O(1)空间,输出已排序。

std::string characters = "aaaabbbccddd";
std::vector<bool> seen(std::numeric_limits<char>::max()-std::numeric_limits<char>::min());

for(std::string::iterator it = characters.begin(), endIt = characters.end(); it != endIt; ++it) {
  seen[(*it)-std::numeric_limits<char>::min()] = true;
}

characters = "";
for(char ch = std::numeric_limits<char>::min(); ch != std::numeric_limits<char>::max(); ++ch) {
  if( seen[ch-std::numeric_limits<char>::min()] ) {
    characters += ch;
  }
}

答案 14 :(得分:0)

这听起来像是自动机的完美用法。

答案 15 :(得分:0)

您可以对字符串进行排序,然后删除重复的字符。

#include <iostream>
#include <algorithm>
#include <string>

int main()
{
    std::string s = "aaaabbbccdbdbcd";

    std::sort(s.begin(), s.end());
    s.erase(std::unique(s.begin(), s.end()), s.end());

    std::cout << s << std::endl;
}

答案 16 :(得分:0)

在C ++中,您可能使用std::set

std::string input("aaaabbbccddd");
std::set<char> unique_chars(input.begin(), input.end());

理论上你可以使用std::unordered_set代替std::set,这应该给出O(N)预期的整体复杂度(尽管O(N 2 )最坏的情况),其中这个是O(N lg M)(其中N =总字符数,M =唯一字符数)。除非您的长字符串包含 lot 的唯一字符,否则此版本可能会更快。

答案 17 :(得分:0)

  string newString = new string("aaaaabbbbccccdddddd".ToCharArray().Distinct().ToArray());   

 char[] characters = "aaaabbbccddd".ToCharArray();
                string result = string.Empty ;
                foreach (char c in characters)
                {
                    if (result.IndexOf(c) < 0)
                        result += c.ToString();
                }

答案 18 :(得分:-1)

# by using python
def cleantext(word):
    if(len(word)==1):

        return word
    if word[0]==word[1]:

        return cleantext(word[1:])

return word[0]+ cleantext(word[1:])
print(cleantext(word))