百度2015校园招聘 面试算法题

感谢者望守想梦 http://blog.csdn.net/u012999424 所提供的面试经历


题目:一个char数组只包含a,b,c,d,e五种字符,设计一种算法,找出一个包含五种字符的最小区间,数组是循环的。


思路: 1、建立索引 front, rear指向子区间的首和尾

2、rear自增遍历数组,设立count[5]存储每种字符出现的个数,设立num记录出现字符的种类数量

3、当num=5时,rear停止自增,front开始自增并且count[*(src+front)]-'a']--,直到其中一个字符为0。这样就找到了符合条件的子区间,但不一定是最小的。

4、判断front和rear与已记录的最小区间

5、重复2-4,遍历字符数组两遍


O(n)算法

#include <iostream>
using namespace std;

void minSubString(char *src, char *des){
	int length=strlen(src)-1;			//字符串长度

	int turn=0;							//记录循环次数
	int min=strlen(src);
	int minfront=0;
	int minrear=0;

	int front, rear;
	front=rear=0;
	int allChar=strlen(des);		//记录需要匹配的字符种类个数
	int num=0;						//记录一共多少种字符出现
	int count[5]={0,0,0,0,0};		//记录每个字符出现次数

	char *p=src;
	char c;			//临时存储字符

	while( turn<2 ) {
		c = *(p+rear);
		
		if(c=='\0') {				//进入下一次循环遍历
			rear=0;
			turn++;
			continue;
		}

		if(count[c-'a'] == 0) {
			num++;
			count[c-'a']++;
		}
		else {
			count[c-'a']++;
		}

		if(num == allChar) {		//所要求的字符集已全部检索
			while(1) {
				c = *(p+front);
				
				if(c=='\0') {
					front++;
					continue;
				}

				count[c-'a']--;
				if(count[c-'a'] == 0) {				//字符集中某个字符出现次数为0
					if(rear<front)
						rear=rear+strlen(src);
					if(rear-front < min){			//此处的front依旧指向那个出现次数为0的字符
						min=rear-front;
						minfront=front;
						minrear=rear-strlen(src);
					}
					count[c-'a']++;					//回退,开始新的子串检索
					break;
				}
				front++;
				if(front>strlen(src)){				
					front=0;
				}
			}
		}

		
		rear++;
	}
	

	//输出处理
	cout<<("最小区间");
	cout<<minfront;	
	cout<<(" ");
	cout<<minrear;
	cout<<endl;
	if(minrear>minfront) {
		for(int i=minfront; i<=minrear; i++) 
			cout<<*(p+i);
	}
	else if(minrear<minfront) {
		for(int i=minfront; i<strlen(src); i++) {
			
			cout<<*(p+i);
		}
		for(int j=0; j<=minrear; j++)
			cout<<*(p+j);
	}
	cout<<endl;

}


int main() {
	
	char *src="eabbbbbcdabcdacccaeaabcd";
	char *des="abcde";
	minSubString(src,des);
	return 0;

}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值