华为笔试题 简答错误记录(字符串处理,好题!!!)
输入描述:
一行或多行字符串。每行包括带路径文件名称,行号,以空格隔开。
文件路径为windows格式
如:E:\V1R2\product\fpgadrive.c 1325
输出描述:
将所有的记录统计并将结果输出,格式:文件名代码行数数目,一个空格隔开,如: fpgadrive.c 1325 1
结果根据数目从多到少排序,数目相同的情况下,按照输入第一次出现顺序排序。
如果超过8条记录,则只输出前8条记录.
如果文件名的长度超过16个字符,则只输出后16个字符
输入例子1:
E:\V1R2\product\fpgadrive.c 1325
输出例子1:
fpgadrive.c 1325 1
链接:https://www.nowcoder.com/questionTerminal/67df1d7889cf4c529576383c2e647c48
来源:牛客网
分析:
比想象中要好做一些,直接按照要求编码即可。但是需要选好数据结构。说实话这道题的统计部分首先想到的方法是Python中的字典,与之类似的就是STL中的map。思路如下:
1.将输入中目录部分去除,开始想使用类似Python中的split函数,结果STL中没有类似函数,我这里使用了string中的find+substr完成类似功能;
2.将文件名字与行号组合作为键,输入中遍历组成map,使用map中的find,如果键值存在,键值+1;否则,键值为1;
3.遍历map,将过长的文件名缩短至16个字符以内,并存入vector中备用。这里有人可能要问:能不能再输入时直接截取过长文件名。不是不可以,但是不建议,因为操作不当可能会引起重复记录。如若我们文件名最长只能有3位,再输入直接截取很容易出现a1.c与b1.c视为一个键的情况;
4.排序,取前八个。由于如果一样多的话是安输入顺序来输出的,因此我能想到的最优排序方法是冒泡,而且是纯冒泡,不会出问题。为什么?我这里采用从下向上冒泡的方法,当大数字向上冒,遇到一样大的停下来,由于上面的比下面的先记录,因此数大小一样的情况下一定上面的是先记录的。
有人可能会担心时间问题,毕竟冒泡的时间复杂度是O(n2)。但是由于我们只需要找出前八个最大的数字,因此是不需要进行全冒泡排序的,只需要给冒泡加以限制,时间就可因控制在8*n上,也就是说冒泡的时间复杂度在本程序中是O(n)!不比你快排快吗?
由于其实现是利用红黑树完成的,所以数据记录部分的时间复杂度是O(nlgn);由于中途遍历一次,截取长名部分的时间复杂度是O(n);而冒泡时间复杂度是O(n)。因此程序的时间复杂度是nlgn + n + n = nlgn + 2n,即O(nlgn)。实际运行时间 3ms。代码如下:
code:
#include<bits/stdc++.h> #include<string.h> using namespace std; #define max_v 105 #define INF 999999 #define me(a,x) memset(a,x,sizeof(a)) typedef long long LL; map<string,int> mm; vector<string> namelist; vector<pair <string,int> > rs; int main() { string str1,str2; while(cin>>str1>>str2) { string str3=str1+" "+str2; int index=0; while((index=str3.find("\\"))!=-1) { str3=str3.substr(index+1); } if(mm.find(str3)==mm.end()) { mm[str3]=1; namelist.push_back(str3); } else { mm[str3]++; } } for(int i=0; i<(int)mm.size(); i++) { int x=mm[namelist[i]]; string name=namelist[i]; if(name.find(" ")>16) { name=name.substr(name.find(" ")-16); } pair<string,int> temp(name,x); rs.push_back(temp); } for(int i=0; i<(int)rs.size()&&i<8; i++) { for(int j=rs.size()-1; j>i; j--) { if(rs[j].second>rs[j-1].second) { swap(rs[j],rs[j-1]); } } } for(int i=0; i<(int)rs.size()&&i<8; i++) { cout<<rs[i].first<<" "<<rs[i].second<<endl; } return 0; }
心之所向,素履以往