微软必应·英雄会第三届在线编程大赛 “几个bing” 题解
来源:互联网 发布:旁氏米粹洗面奶知乎 编辑:程序博客网 时间:2024/04/29 04:02
新年之初,登陆CSDN看到了英雄会的题目,好久没有头脑风暴了,一看题目还算掌握中,决定试试,于是开始分析题目了。
题目要求: 例如有一个字符串"iinbinbing",截取不同位置的字符‘b’、‘i’、‘n’、‘g’组合成单词"bing"。若从1开始计数的话,则‘b’ ‘i’ ‘n’ ‘g’这4个字母出现的位置分别为(4,5,6,10) (4,5,9,10),(4,8,9,10)和(7,8,9,10),故总共可以组合成4个单词”bing“。
问题是:现给定任意字符串,只包含小写‘b’ ‘i’ ‘n’ ‘g’这4种字母,请问一共能组合成多少个单词bing?
字符串长度不超过10000,由于结果可能比较大,请输出对10^9 + 7取余数之后的结果。
分析了一下,可以开创四个数组,分别记录b,i,n,g的位置,通过位置进行比较求解。
先定义四个vector<int> 对象:
vector<int> b;vector<int> i;vector<int> n;vector<int> g;
对于任意一个输入字符串input,先进行如下操作,
int len = input.length(); for(int j = 0;j<len;j++) { x = input[j] - 'a'; switch(x) { case 1: //‘b' b.push_back(j); break; case 8: // 'i' i.push_back(j); break; case 13: //'n' n.push_back(j); break; case 6: //'g' g.push_back(j); } }
如给定输入input = "iinbinbing";
b[] = { 3,6 }
i[] = { 0,1,4,7 }
n[] = { 2,5,8 }
g[] = { 9 }
算法一:
通过嵌套循环遍历 b[],i[],n[],g[],当数组中存放的值为递增序时,结果+1,复杂度O(n^4),代码略。
程序复杂度分析,由于输入长度最多为10000,因此所有测试数据中,复杂度最大的为2500^4,即是
bbb.........iii............nnn............ggg.........
(各2500个)
而对于2500^4 = 39062500000000 , 是一个非常庞大的数据。因此该算法必然导致超时。
算法二:
增加定义四个数组:
vector<long long> result_b; vector<long long> result_i; vector<long long> result_n; vector<long long> result_g;
每个result_x数组中的值分别表示对应x数组中值所包含的可行解,result_x初始化为:
int len_b = b.size(); result_b.assign(len_b,0); int len_i = i.size(); result_i.assign(len_i,0); int len_n = n.size(); result_n.assign(len_n,0); int len_g = g.size(); result_g.assign(len_g,1);
如:
b[] = { 3,6 }
i[] = { 0,1,4,7 }
n[] = { 2,5,8 }
g[] = { 9 }
====>
result_g[] = {1} , 可行解就是本身
result_n[] = {1,1,1} , 对于n[0]=2来说,g[]中有1个值(9)比2大,因此result_n[0] = result_g[0]
result_i[] = {3,3,2,1}, 同理,对于i[2]=4来说,n[]中有2个值(5,8)比4大,因此result_i[2] = result_n[1]+result_n[8]=2
result_b[] = {3,1} , 对于b[0] = 3来说,i[]中有两个值(4,7)比3大,因此result_b[0] = result_i[2] + result_i[3] = 3
最后对result_b[]求和即是最后的结果。
因此把上面的四重循环分解为三个二重循环,第一次n[]和g[]循环,第二次i[]和n[]循环,第三次b[]和i[]循环。复杂度为O(n^2),最坏数据为biii.......nnn.......g,其中有连续两个字符为4999个,最坏计算次数约为5000^2 = 25000000,按理说在10^8下应该很快运行结束,按照该算法进行挑战,提交后发现还是超时。
利用程序构造字符串测试了一下,大概得花10秒左右,想到可能是测试数据太多在vector要进行不断的创建造成,精简了一些if语句,比如在第一个二重循环时,数据不可能大于10^9,省略了该步骤的条件判断,再次提交,还是超时。
由于已经挑战失败,只能当学习再试试改进。
算法三:
在算法二的基础上,增加了标记,分析在求解result_x[]数组时,result_x最后的结构必然是一个非递减序列,因此求result_x[i]的值均可以用到result_x[i-1]进行快速求解,省去了对第二层数组的累加。
比如在上例:
b[] = { 3,6 }
i[] = { 0,1,4,7 }
再求得result_i[] = {3,3,2,1}时,求result_b[]时,最多只需要遍历i[]2次即可。
第一次计算sum(result_i[]) = 9;
第二次计算result_b[] 具体如下:
定义一个位置site初始指向i[0],若b[0] > i[site],num -= result_i[site]且site++,直到b[0]<i[site],result_b[0] = num
代码实现为
num = sum(result_i); site = 0; for(int j = 0;j<len_b;j++) { while(site<len_i && b[j]>i[site]) { num -= result_i[site]; site++; } result_b[j] = num; }
这样对于b[] ,i[] 相当于各自只需要遍历一次,算法复杂度O(n)。
最后只需要计算 c = sum(result_b); 即可。
由于结果较大,需要用大整数,但是分析了最大数据小于long long类型(64位),因此定义计数c为long long类型,最后取模即可,最后提交顺利通过。
源代码下载地址 :http://download.csdn.net/detail/longteng1116/6801531
2 0
- 微软必应·英雄会第三届在线编程大赛 “几个bing” 题解
- csdn英雄会题解之几个bing--微软必应·英雄会第三届在线编程大赛
- 几个bing的c#求解--微软必应·英雄会第三届在线编程大赛
- 微软必应·英雄会第三届在线编程大赛:几个bing?
- 微软必应·英雄会第三届在线编程大赛:几个bing?
- 微软必应·英雄会第三届在线编程大赛:几个bing?
- 微软必应·英雄会第三届在线编程大赛:几个bing
- 微软必应-英雄会第三届在线编程大赛:几个Bing?【英雄会】
- 算法与数据结构(2)--英雄会第三届在线编程大赛:几个bing
- 英雄会第二届在线编程大赛·线上初赛:AB 题解
- 【题解】英雄会第二届在线编程大赛·CSDN现场决赛:三元组的数量
- 【题解】 英雄会-第五届在线编程大赛月赛第二题:走格子
- pongo(csdn英雄会题解)之三元组的数量--英雄会第二届在线编程大赛·CSDN现场决赛
- pongo(csdn英雄会题解)之三元组的数量--英雄会第二届在线编程大赛·CSDN现场决赛
- 微软Azure•英雄会第五届在线编程大赛月赛第四题:Core allocation
- csdn英雄会题解之第五届在线编程大赛月赛第三题:石子游戏 --多堆博弈游戏 多堆拈游戏
- CSDN英雄会-第五届在线编程大赛月赛第三题:石子游戏(1)
- 参与英雄会第一届在线编程大赛:单词博弈
- sping项目中引用第三方jar,报错: No matching bean
- 【互联网那些事】到底什么是互联网思维
- 黑马程序员_银行业务调度系统
- 非递归全排列
- Hadoop监控方法总结
- 微软必应·英雄会第三届在线编程大赛 “几个bing” 题解
- ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysql.sock'
- 递归无序全排列
- 【算法导论】最大流算法
- 黑马程序员—交通灯管理系统
- sicily 1817.校歌手大奖赛
- 源代码和kernel编译
- 大数_高精度乘法
- Android学习小demo(1)自定义View