删除字符串中所有重复项的有效算法是什么?
例如: aaaabbbccdbdbcd
必填结果: abcd
答案 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))