C++ 去除字符串中的重复字符

给定一个字符串,要求去除其中的重复字符。例如 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());

 

谢谢,请指教!

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值