给定一个字符串,要求去除其中的重复字符。例如 abcbs ,操作后得到 abcs 。
方法一:不考虑时间和空间,最简单直接的方法是 另外开辟一个 string 数组,用于保存unique字符。
主函数中的 isUnique(mystr) 见我的上一篇博文。
string duplicate(string str)
{
if(str.size()<2)
return str;
string tmp_str("\0");
tmp_str+=str[0];
string::size_type j;
for(string::size_type i=1 ; i<str.size() ; i++)
{
for(j=0 ; j<tmp_str.size() ; j++)
{
if(tmp_str[j]==str[i])
break;
}
if(j==tmp_str.size())
tmp_str+=str[i];
}
return tmp_str;
}
int _tmain(int argc, _TCHAR* argv[])
{
string mystr;
string dest;
while(cin>>mystr)
{
if(isUnique(mystr))
cout<<mystr<<" is Unique!"<<endl;
else
{
cout<<mystr<<" is not Unique!"<<endl;
dest = duplicate(mystr);
cout<<"After the dup: "<<dest<<endl;
}
}
return 0;
}
这里我用到了 string类来实现duplicate 算法。时间O(n2) 空间O(n)。
方法二:假如我们限定空间复杂度为O(1),即不能开辟新的空间,只能声明一些简单变量,那么我们就只能在元string数组上进行操作了。
我们仔细想后,发现这样是可行的。我们用一个变量 tail 来标记新string数组的长度,可知tail肯定小于等于元数组的长度。具体代码如下:
void duplicate(char str[])
{
int len = strlen(str);
if(len<2)
return ;
int tail = 1;
for(int i=1 ; i<len ; i++)
{
int j=0;
for(j=0 ; j<tail ; j++)
{
if(str[j]==str[i])
break;
}
if(j==tail)
str[tail++]=str[i];
}
str[tail] = '\0';
}
int _tmain(int argc, _TCHAR* argv[])
{
string mystr;
string dest;
while(cin>>mystr)
{
if(isUnique(mystr))
cout<<mystr<<" is Unique!"<<endl;
else
{
char * dest=new char[mystr.size()+1];
strcpy(dest , mystr.c_str());
duplicate(dest);
cout<<"After the dup: "<<dest<<endl;
}
}
return 0;
}
该算法的时间复杂度是O(n2),空间是O(1)。
方法三:应用Hash Table思想,可以将时间复杂度降低到O(1)。
void duplicate(char str[])
{
int len = strlen(str);
if(len<2)
return ;
int hash[256]={0};
hash[str[0]]=1;
int tail = 1;
for(int i=1 ; i<len ; i++)
{
if(hash[str[i]]==0)
{
str[tail++]=str[i];
hash[str[i]]+=1;
}
}
str[tail] = '\0';
}
int _tmain(int argc, _TCHAR* argv[])
{
string mystr;
string dest;
while(cin>>mystr)
{
if(isUnique(mystr))
cout<<mystr<<" is Unique!"<<endl;
else
{
char * dest=new char[mystr.size()+1];
strcpy(dest , mystr.c_str());
duplicate(dest);
cout<<"After the dup: "<<dest<<endl;
}
}
return 0;
}
选择的测试用例:没有重复的字符,空串等。
特别注意:string类对象到 字符数组的转换:
string是C++标准库里面其中的一个,封装了对字符串的操作。
其中 string str1,str2; str[1]=str[3];是错误的,不能下标修改string对象的单个字符值,必须应用string类对应的具体函数来修改。所以我们一般应用char str[ ]比较方便。
str1.data() , str1.c_str() 这两者得到的都是 const char * 类型,而不是char * 类型 。直接 char * tmpstr = str1.c_str(); 是错误的。
str1.copy(tmpstr,5,0) 5表示复制的个数,0表示复制的位置,*(p+5)='\0' ; 要手动加上结束符。
我们一般用 C中的字符串操作函数来处理字符串或字符数组。
如 strlen() , strcpy(), strcmp() .
char * dest=new char[mystr.size()+1]; //必须先申请一个足够大的空间来存储。
strcpy(dest , mystr.c_str());
谢谢,请指教!