在字符串中删除特定的字符

【题 目】输入两个字符串,从第一个字符串中删除第二个字符串中出现的所有字符。例如:输入"they are students." 与 “aeiou”,则应该输出“thy r stdnts.”。

  【思 路1】首先我们还是以解决问题为第一要义,寻找最为直观的解决方案,很容易想到的方法就是,对于在第一个字符串中的每一个字符,拿它去查找是否在第二个字符串中出现过,如果是,则删除,如果不是则保留。删除一个字符,要让该字符之后的所有字符逐一向前移位,所以时间复杂度为O(n),对于长度为n的字符串,总的时间复杂度为O(N2).而对于给定的字符,在第二个字符串中查找该字符,如果遍历长度为m的第二个字符串的话,时间复杂度也为O(m),总的时间复杂度为O(mn).

  【思 路2】有没有更为高效的方法呢?事实上我们在并没有必要在每次删除一个字符的时候都让后面的字符移动,我们只需要让被删除位置的字符被后面不需要被删除的字符来代替就可以了,相当于我们有一个先头哨兵,它只负责寻找那些不需要被删除的字符,碰到需要删除的就直接跳过,碰到不需要删除的就告诉主力哨兵,主力哨兵负责对于先头哨兵找到的字符给予“接收”位置就行了。具体来说:我们可以设置两个指针pfast(先头哨兵)和pslow(主力哨兵),初始时两个都指向字符串的第一个字符,pfast碰到一个需要删除的字符“视而不见”直接跳过;pfast如果碰到不需要删除的字符,就把该字符复制给pslow,同时pfast后移(继续寻找),pslow(指向下一个位置)。这样整个算法的时间复杂度就可以达到O(n)。

  接下来我们要考虑查找的问题,对于char型字符的查找,我们讨论过用长度为256的哈希表来存储字符出现的次数最后高效,详细讨论见【算法19】.这样的查找效率为O(1).好了,删除和查找的问题都解决了,我们很容易写出如下的代码:

// They are Students.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include<string>
using namespace std;

void DelChars(char* pstrSource,char* pstrDel)
{
	if(pstrSource == NULL || pstrDel == NULL)
		return;

	//建立并初始化哈希表
	const int hashLength = 256;
	unsigned int hashList[hashLength];
	for(int i = 0;i < hashLength;++i)
	{
		hashList[i] = 0;
	}

	//hash表中存储第二个字符串中每个字符出现的次数
	char *pch = pstrDel;
	while(*pch != '\0')
	{
		hashList[*pch]++;
		pch++;
	}

	//我自己添加的
	for (int i=0;i<256;i++)
	{
		cout<<hashList[i]<<" ";
	}
	cout<<endl;

	char *pfast = pstrSource;
	char *pslow = pstrSource;
	while(*pfast != '\0')
	{
		//如果pfast指向的字符不需要删除,就把其所指的值赋给pslow,两者都向后移
		//否则,pfast向后移动继续寻找,pslow不动
		if(hashList[*pfast] == 0)//没找到要删除的,
		{
			*pslow = *pfast;
			pslow++;
		}
		pfast++;
	}

	//非常容易忽视,记得加上字符串结束符!
	*pslow = '\0';
}

int main()
{
	const int StrMaxLength = 100;
	cout<<"Enter your first(/resource) string:"<<endl;
	char strFirst[StrMaxLength];
	cin.getline(strFirst,sizeof(strFirst));

	cout<<"Enter your second(/detele) string:"<<endl;
	char strSecond[StrMaxLength];
	cin.getline(strSecond,sizeof(strSecond));

	cout<<"the final string you want is:"<<endl;
	DelChars(strFirst,strSecond);
	cout<<strFirst<<endl;

	system("pause");
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值