字节跳动2019春招研发部分编程题汇
我叫王大锤,是一家出版社的编辑。我负责校对投稿来的英文稿件,这份工作非常烦人,因为每天都要去修正无数的拼写错误。 但是,优秀的人总能在平凡的工作中发现真理。我发现一个发现拼写错误的捷径: 1. 三个同样的字母连在一起,一定是拼写错误,去掉一个的就好啦:比如 helllo -> hello 2. 两对一样的字母(AABB型)连在一起,一定是拼写错误,去掉第二对的一个字母就好啦:比如 helloo -> hello 3. 上面的规则优先“从左到右”匹配,即如果是AABBCC,虽然AABB和BBCC都是错误拼写,应该优先考虑修复AABB,结果为AABCC 我特喵是个天才!我在蓝翔学过挖掘机和程序设计,按照这个原理写了一个自动校对器,工作效率从此起飞。 用不了多久,我就会出任CEO,当上董事长,迎娶白富美,走上人生巅峰,想想都有点小激动呢! …… 万万没想到,我被开除了,临走时老板对我说: “做人做事要兢兢业业、勤勤恳恳、本本分分,人要是行, 干一行行一行。一行行行行行;要是不行,干一行不行一行,一行不行行行不行。” 我现在整个人红红火火恍恍惚惚的…… 请听题:请实现大锤的自动校对程序
输入格式
第一行包括一个数字N,表示本次用例包括多少个待校验的字符串。1<=N<=50 后面跟随N行,每行为一个待校验的字符串。字符串长度不超过1000
输出格式
N行,每行包括一个被修复后的字符串。
输入样例
2 helloo wooooooow
输出样例
hello woow
解题思路:典型的签到题,因为数据规模决定了使用任何方法都能通过。这里介绍三种复杂度O(n)作法。
(一)单链表作法
题目中要求消除(删除)元素,未避免删除后移动元素,用链式结构是一种较好的选择。
int i,j,t,n,nex[10005]= {0};
char c[10005]= {0};
cin>>t;
while(t--)
{
scanf("%s",c+1);/**< 从下标1开始读取 */
n=strlen(c+1);
for(i=1; i<n; i++) /**< 构造静态链表*/
nex[i]=i+1;
nex[n]=0;/**< 尾结点指针为0 */
int c1=1,c2,c3,c4;/**< 定义4个指针来处理问题,依次相邻四个字符 */
while(c1)
{
c2=nex[c1],c3=nex[c2],c4=nex[c3];/**<满足AAA或AABB删除 */
if(c2&&c[c1]==c[c2]&&( (c3&&c[c2]==c[c3]) || (c4&&c[c3]==c[c4]) ))
nex[c2]=c4;/**< 注意判定条件时一定要确保指针c2,c3,c4不是0,即非空指针 */
else
c1=c2;
}
c1=1;
while(c1)
{
cout<<c[c1];
c1=nex[c1];
}
cout<<endl;
}
return 0;
(二)栈结构消除
字符串消除问题,可考虑能不能用栈结构解决。用栈存储字符串,i为当前处理字符,如果栈顶两个元素为AA,i也是A或者i和i+1为BB时,i不需要入栈,其他情况i都必须入栈。
标准栈结构只能得到栈顶一个元素,无法解决AA判定,因此必须手写栈结构。
int i,j,t,n,top=0;
char c[10005]= {0},st[1005];/**< 手写一个栈结构st,top为栈顶指针 */
cin>>t;
while(t--)
{
scanf("%s",c+1);/**< 从下标1开始读取 */
n=strlen(c+1);
top=0;
for(i=1;i<=n;i++)
{
if(top>=2) /**< 栈中多于2个元素才能判断 */
{
if(st[top-1]==st[top-2]&&(c[i]==st[top-1]||c[i]==c[i+1]))/**< 满足AAA或AABB相等条件 */
continue;
}
st[top++]=c[i];
}
for(i=0;i<top;i++)/**< 输出栈中所有元素 */
cout<<st[i];
cout<<endl;
}
return 0;
(3)枚举算法
枚举每一个字符i,看看是否需要删除。思考一下,当字符i的左侧为AA情况时,有三种可能AAA,AABB,AABC,前两种可以认为i被删除,继续查看i+1就行了。当出现AABC????这种情况时,下一次判定不用再管AAB了(不可能参与消除),看看C和C后面是否相同,继续向后扫描
int main()
{
ios::sync_with_stdio(0),cin.tie(0);
int i=2,j,p1=1,p2=0,t;
cin>>t;
while(t--)
{
i=2,p1=1,p2=0;
string s;
cin>>s;
while(i<s.size())
{
if(s[p1]!=s[p2]) /**< 先找到AA情况 */
{
p1++,p2++,i++;
continue;
} /**< 如果s[i]能凑成AAA或AABB,把s[i]清除,继续向后检查 */
while(s[i]==s[p1]||s[i]==s[i+1])
s[i++]=' ';/**< 用空格字符实现清除 */
p2=i+1,p1=i+2,i+=3;/**< 一定是AABC情况,下一次让p2指向c */
}
for(i=0; i<s.size(); i++)
if(s[i]!=' ')
cout<<s[i];
cout<<endl;
}
return 0;
}