笔试题82.新浪微博算法题

这是我在面试过程中遇到的一道代码算法题,需要我在一定的时间内完成这个题目,题目的描述:

将某字符串str1中的字符串str2,全部替换成字符串str3。

例如:str1=”abcecbbccefgxyzbcgbcg”,

str2=”bc”,

str3=”xy”.

替换后为”axyecbxycefgxyzxygxyg”

请尽可能考虑各类情况,并保证时间复杂度和空间复杂度最优。

这个题看似简单的做法是可以的解决的,我当时也想过简单的暴力求解法解决。后来我仔细想了想,这个题目应该分为三步:

1找,2定,3换。先找到服药要求的串,找出它的下标,替换该字符串。

我们都知道字符串的查找算法中最有名的就是KMP算法了,所以我决定采用KMP算法去找,找到下标后就可以替换了。若是不懂KMP算法的话,我建议大家去七月的博客上看一下他写的详解KMP算法,写的很详细很清晰很容易上手。我这里主要是解决这个题,先就不说KMP算法的原理和部件了。我们主要讨论解题的方法,下面我就给出代码,可能并不是最优的解法,大家若有更好的解法记得跟我交流一下,一起分享一下。

//构造next 数组
void makeNext(const char *patten,int *arr)
{
	assert(patten);
	int len = strlen(patten);
	int pos1 = 1;
	int pos2 = 0;
	for(inti = 1; i<len; i++)
	{
	   if(pos1 <= i && patten[pos1-1] == patten[pos2])
	   {
		arr[i]=arr[i-1]+1; //若前面已经出现了前缀后缀匹配,则 next 值加一 pos2++;
	   }
	   else
	   {
		if(patten[pos1-1]==patten[0])//前面的匹配失败,可能存在新的前缀后缀匹配
		{
			arr[i]=1;
			pos2=1;
		}
	   }
	   ++pos1;
	}

	for(inti = len-1; i>0; --i)
        {
	    arr[i]=arr[i]-1;
	}
	arr[0]=-1;
}

//将配位位置的模式串替换成新串
void Replace(char *str,const char *newstr,int plen)
{
	assert(str);
	assert(newstr);
	for(inti = 0; i < plen; ++i)
	{
	    str[i] = newstr[i];
	}
}	

//查找匹配的串的位置
int Find(const char *str,const char *patten,int len,const int *next)
{
	assert(str);
	assert(patten);
	assert(next);
	intslen = strlen(str); //主串长度
	if(slen == 1) //长度为 1 的字符串,相当于查找单个字符
	{
		for(int i = 0; i < len; ++i)
		{
			if(str[i] == patten[0])
				return i;
		}
		return-1;
	}
	int s = 0; // 主串下标
	int t = 0; // 子串下标
	while(t<len && s<slen)
	{
		if(str[s] == patten[t])
		{
			if(t == len-1)//成功匹配
			{
				return(s-t);
			}
			++s;
			++t;
		 }
		else//不相等
		{
			if(next[t] == -1) //第一个都不匹配,子串与主串失败的下一个位置比较
			{
				++s;
				t = 0;
				continue;
			}
			t = next[t]; //前面的已经匹配,不用再比较了
		}
	}
	return -1;
}

void ReplaceSubstr(char *str,const char *patten,const char *newstr)
{ /* 目标:将 str中所有的 patten 串换成 newstr 串 */
	//判断指针是否合法
	assert(str);
	assert(patten);
	assert(newstr);
	assert(strlen(patten) == strlen(newstr));
	//构造 next 数组
	int plen = strlen(patten);//patten串的长度
	int *next = newint[plen];
	memset(next,0,sizeof(int)*plen);
	makeNext(patten,next);
	int slen = strlen(str);//主串的长度 char*pstr=str; //pstr 要不断往前移动
	int curpos = 0;//本次的相对偏移
	while( (curpos = Find(pstr,patten,plen,next) ) != -1)
	{
		Replace(pstr+curpos,newstr,plen);
		curpos += plen;
		pstr += curpos;
	}
	delete[]next;
}

//测试用例
void TestReplacestr()
{ /*charstr[]="abcecbbccefgxyzbcgbcg"; char*patten="bc"; char*newstr="xy";*/
	charstr[] = "abcecbbccefgxyzbcgb";
	char*patten = "b";
	char*newstr = "x";
	cout<<str<<endl;
	ReplaceSubstr(str,patten,newstr);
	cout<<str<<endl;
}

大家若是觉得有什么不妥的地方,请你们给我指出!

时间: 2024-10-29 19:11:16

笔试题82.新浪微博算法题的相关文章

2014年阿里巴巴在线笔试题-第3大题-公共最长字符串长度

说明 2014年阿里巴巴在线笔试题-第3大题    首先,我没参加这次的阿里巴巴在线笔试题,题目全部是从别人口中描述而来,对于以下的分析,如果有什么不对的地方还望指教.也希望大家能够有更好的办法,希望大家来能不吝赐教. 题目描述 给定一个主字符串和一个匹配字符串,现在问你,找出 "主串中可匹配到的匹配串中子串的最大长度",可能比较绕,举个例子吧 主字符串       abcdefgsdff     记为A 匹配字符串   abefgf               记为B 要求的值就是 

笔试题集锦(智力题)

一.简答题 1. 动态链接库和静态链接库的优缺点 2. 轮询任务调度和可抢占式调度有什么区别? 3. 列出数据库中常用的锁及其应用场景 二.算法设计题 1. 给定N是一个正整数,求比N大的最小"不重复数",这里的不重复是指没有两个相等的相邻位,如1102中的11是相等的两个相邻位故不是不重复数,而12301是不重复数. 2. 设N是一个大整数,求长度为N的字符串的最长回文子串. 3. 坐标轴上从左到右依次的点为a[0].a[1].a[2]--a[n-1],设一根木棒的长度为L,求L最多

js作用域之常见笔试题,运行结果题

笔试题中经常有运行结果题,而大多体型都是围绕作用域展开,下面总结了几种相关的题: 外层的变量函数内部可以找到,函数内部的变量(局部变量)外层找不到. function aaa() { var a = 10; } alert(a);//Error a is not defined 由于a是函数内部定义的局部变量,根据作用域关系,外层(全局环境)访问不到局部变量.因此会报错 var a=10; function aaa(){ alert(a); } function bbb(){ var a=20;

Java笔试题之《算法与编程》

算法与编程 1.判断身份证:要么是15位,要么是18位,最后一位可以为字母,并写程序提出其中的年月日. 答:我们可以用正则表达式来定义复杂的字符串格式,(\d{17}[0-9a-zA-Z]|\d{14}[0-9a-zA-Z])可以用来判断是否为合法的15位或18位身份证号码. 因为15位和18位的身份证号码都是从7位到第12位为身份证为日期类型.这样我们可以设计出更精确的正则模式,使身份证号的日期合法,这样我们的正则模式可以进一步将日期部分的正则修改为[12][0-9]{3}[01][0-9][

阿里巴巴笔试题集第23题及分析

题目: 一个骰子, 6 面, 1 个面是 1 , 2 个面是 2 , 3 个面是 3 , 问平均掷多少次能使 1 . 2 . 3 都至少出现一次. ?方法: 面对面试概率题几乎屡试不爽的分叉树递归列方程法. ?这是一个求数学期望的问题,最终是求 1 , 2 , 3 出现至少一次的最短长度的期望. ?这样分叉树的每个节点是一个期望状态,而每个分叉是一次投掷结果.将后续期望出现 1 . 2 . 3 各至少一次的情形记作 L 123 (即题目所求),将后续期望出现 1 . 2 各至少一次( 3 无关)

C++笔试题2(基础题)

(1)请写出下列程序的输出内容 代码如下: 1 #include <iostream> 2 using namespace std; 3 4 class A 5 { 6 public: 7 A() 8 { 9 cout << "A::A()" << endl; 10 } 11 virtual ~A() 12 { 13 cout << "A::~A()" << endl; 14 } 15 void fun1(

(笔试题)洗牌算法

题目: 给定N张扑克牌和一个随机函数,设计一个洗牌算法 思路: 假设数组A存的是扑克牌代表的数字,则洗牌的过程就是数组中元素交换的过程. 洗牌是个随机的过程,也是一个排列组合的过程. 假设有N张牌,则其排列组合的可能情况为N!=N*(N-1)*....*2*1. 有两种的随机洗牌函数: 1.A[i]=A[rand()%N] 2.A[i]=A[rand()%(N-i)] 但第一种情况得到的选择可能为N^N,而第二种情况为N! 因此第二种随机算法更符合. 代码: void shuffle(int a

笔试题集锦(编程题)

1.已知数组a前半部分a[0,mid - 1],后半部分a[mid,num-1],现前半部分和后半部分均已排好序.要求:实现a数组的从小到大排序.空间复杂度为O(1). void MergeSort(int *v, const int len, const int mid)   {         int i, temp;       int left = 0, right = mid;          while (left < right && right < len) 

测试笔试题之测试用例设计题

1.假设京东有一个Web API:http://p.jd.com?p1=90&p0=100,输入打折价p1和原价p0,返回折扣信息0.9,请设计测试用例进行测试. 答案: (1)输入打折价错误+输入原价错误(输入值不在正常范围内) (2)输入打折价错误+输入原价正确 (3)输入打折价正确+输入原价错误 (4)输入打折价正确+输入原价正确(打折价高于原价) (5)输入打折价正确+输入原价正确(打折价高于原价 返回折扣信息不对) (6)输入打折价正确+输入原价正确(打折价高于原价 返回折扣信息对)