百度武汉站
来源:互联网 发布:程序员被骗婚 编辑:程序博客网 时间:2024/04/29 20:41
百度2014校招笔试题目题解
----武汉站,9.28号百度校招笔试题目算法题目部分
二、算法与程序设计题
1、给定任意一个正整数,求比这个数大且最小的“不重复数”,“不重复数”的含义是相邻两位不相同,例如1101是重复数,而1201是不重复数。(15分)
2、长度为N(N很大)的字符串,求这个字符串里的最长回文子串。(15分)
3、数轴上从左到右有n各点a[0], a[1], ……,a[n -1],给定一根长度为L的绳子,求绳子最多能覆盖其中的几个点。(15分)
这是百度的笔试题目,好像是什么系统行为分析师职位的笔试题目!博文最后会贴出试题照片!
题解:(题解非官方,仅供参考,转载请联系博主,有错误的地方望指正!谢谢)
1、给定任意一个正整数,求比这个数大且最小的“不重复数”,“不重复数”的含义是相邻两位不相同,例如1101是重复数,而1201是不重复数。
解: 这道题目我也没有什么特别出彩的算法,就是按照常规思路来求解,首先要理解什么叫做“不重复数”,这是解题的关键之一,相邻两位不相同的数即为“不重复数”;还有一个地方要注意的就是“求比这个数大且最小的”,就是在比给定数大的不重复数中找到最小的!理解了这两个地方,这道题目就可以着手求解了!
我用一个实例来说说我的思路,假如给定的正整数为11233:
用最常规的方法,就是每次对这个数加1,判断是不是“不重复数”,加1后为11234,有两个1重复了,于是继续加1,……,那么主要就在判断是不是“不重复数”上面了,我设置了两个变量,是currentBit, lastBit,顾名思义,lastBit保存上一个数位的值,currentBit保存当前数位的值,拿整数12345来说,就是初始化lastBit = 5,然后计算currentBit = 4;下一步,把currentBit 值赋给lastBit,即lastBit = 4,计算currentBit = 3;依次类推。
说到这里,很多朋友觉得可以有更加高效的方法,小难点有4:
1、因为可以直接定位到“重复”的数位的位置,比如12344,我们可以直接定位到个位数4和十位数4上面,然后在低数位(这里就是个位数)上加1即可,事实上,不是如此简单,假设是对整数12199呢?还能简单的加1操作吗,加1之后结果为12200,那结果显然是错的,当然这也是可以处理的,处理方法就是把12200继续拿到循环去处理,再判断是不是“不重复数”;
2、这里又产生一个问题,因为“重复“的数位可能不止一对,有可能有多对,比如整数11233,定位“33”之后变为“34”,定位“11”之后变为“12”,结果就是12234。又有重复的地方,就是“22”。继续拿到循环去重复;
3、还有要注意的是,你的程序的设计,是如何存储数位的值的,是一个一个数位的值求出来呢?还是像我这样设置一个前后索引?把每个数位的值求出来并且存储,程序会变得繁琐复杂,不易读懂,如果是设置前后索引,则要注意程序退出循环的条件!
4、对于存在多对“重复”数位的正整数,数位“重复”的定位和变换,是从高位到低位,还是从低位到高位呢?正确的应该是从高位到低位,这给我们的程序设计也带来了不便。
这些就是我在试图找到高效算法时得到的经验,每个小难点都要处理,有点繁琐,有耐心的朋友,可以试着写一下更高效的算法,另外,使用了比较高效的算法,代码尽量保持简洁,并告知博主,谢谢!
my code:(简单加1的方法)
- /*
- 给定任意一个正整数,求比这个数大且最小的“不重复数”,“不重复数的含义是相邻两位不相同,例如1101是不重复数”
- */
- #include <stdio.h>
- #include <stdlib.h>
- int getNumNonrepetition(constint NumGived)
- {
- int flag = 0;//为0表示该数不是“不重复数”
- int numRepeat = NumGived;
- int numTemp = 0;//
- int currentBit = 0, lastBit = 0;//前后数位索引
- while(1)
- {
- numRepeat++;
- //初始化后索引
- numTemp = numRepeat;
- lastBit = numTemp % 10;
- numTemp /= 10;
- flag = 1;
- //判断该数是不是“非重复数”
- while(numTemp != 0)
- {
- currentBit = numTemp % 10;
- numTemp /= 10;
- if(lastBit == currentBit)
- {
- flag = 0;
- break;
- }
- lastBit = currentBit;
- }
- if(flag == 1)//该数为不重复数,返回
- {
- return numRepeat;
- }
- }
- }
- int main(void)
- {
- int NumGived = 19922884;
- int result = getNumNonrepetition(NumGived);
- printf("the number is %d\n", result);
- return 0;
- }
/* 给定任意一个正整数,求比这个数大且最小的“不重复数”,“不重复数的含义是相邻两位不相同,例如1101是不重复数”*/#include <stdio.h>#include <stdlib.h>int getNumNonrepetition(const int NumGived){ int flag = 0;//为0表示该数不是“不重复数” int numRepeat = NumGived; int numTemp = 0;// int currentBit = 0, lastBit = 0;//前后数位索引 while(1) { numRepeat++; //初始化后索引 numTemp = numRepeat; lastBit = numTemp % 10; numTemp /= 10; flag = 1; //判断该数是不是“非重复数” while(numTemp != 0) { currentBit = numTemp % 10; numTemp /= 10; if(lastBit == currentBit) { flag = 0; break; } lastBit = currentBit; } if(flag == 1)//该数为不重复数,返回 { return numRepeat; } }}int main(void){ int NumGived = 19922884; int result = getNumNonrepetition(NumGived); printf("the number is %d\n", result); return 0;}
2、长度为N(N很大)的字符串,求这个字符串里的最长回文子串。
解:题目指出“N很大”,就是提示我们不要想通过遍历的方法来找到这个字符串,我想到的就一种解法,时间复杂度应该不高,但是我算不出来这个算法的复杂度是多少,首先说一下什么是回文字符串:回文字符串是指从左到右和从右到左相同的字符串,比如"1221"或者“12321”都是回文字符串。刚好举得这两个回文字符串的例子就是我的算法的两个类别:
第一类“12321”:中间是一个单独的字符。算法的思想是从第2个字符直到倒数第2个字符遍历,每遇到一个字符,就依次判断这个字符前后的字符是否相等,如果相等,则继续判断下一个字符,直到以这个字符为中心的两边对称的字符不相等为止,或者前后字符的位置数组越界为止;计算此时的回文字符串的长度,与之前的比较,记下较长的回文字符串的长度和中心字符的位置;遍历结束则返回最大长度和中心字符的位置。
图示:若字符串为“1234321”
第二类“123321”:中间是两个相同的字符。算法思想同上,其实是一样的过程!图解也是一样的!
my code:
- /*
- 长度为N(N很大)的字符串,求这个字符串里的最长回文子串。
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- //第一类“12321”:中间是一个单独的字符
- int FindLongPaliSubstr_Odd(constchar A[], int * indexMid)
- {
- int i = 0, cnt = 0;//cnt表示前后移动位数
- int MyMax = 0;
- int lenOfA = strlen(A);
- *indexMid = 0;
- for(i = 1; i <= lenOfA - 2; i++)
- {
- cnt = 0;
- while(i - cnt >= 0 && i + cnt <= lenOfA - 1 && A[i - cnt] == A[i + cnt])
- {
- cnt++;
- }
- cnt--;
- //找到较大长度的回文字符串,保存中心字符的位置
- if(MyMax < 2 * cnt + 1)
- {
- MyMax = 2 * cnt + 1;
- *indexMid = i;
- }
- }
- return MyMax;
- }
- //第二类“12321”:中间是两个相同的字符。
- int FindLongPaliSubstr_Even(constchar A[],int * First)
- {
- int i = 0, cnt = 0;//cnt表示前后移动位数
- int MyMax = 0;
- int lenOfA = strlen(A);
- *First = 0;//中间两个相同字符的第一个字符位置
- for(i = 0; i <= lenOfA - 2; i++)
- {
- if(A[i] == A[i + 1])
- {
- cnt = 1;
- while(i - cnt >= 0 && (i + 1 + cnt) <= lenOfA - 1 && A[i - cnt] == A[i + 1 + cnt])
- {
- cnt++;
- }
- cnt--;
- //找到较大长度的回文字符串,保存中心第一个字符的位置
- if(MyMax < 2 * cnt + 2)
- {
- MyMax = 2 * cnt + 2;
- *First = i;
- }
- }
- }
- return MyMax;
- }
- int main(void)
- {
- char A[] = "adfadfbadfdg12321fagage";
- int indexMid = 0;
- int First = 0;
- int i = 0;
- //两种类别的最长回文子串的长度
- int MaxOdd = FindLongPaliSubstr_Odd(A, &indexMid);
- int MaxEven = FindLongPaliSubstr_Even(A, &First);
- printf("indexMid = %d\n", indexMid);
- printf("First = %d\n", First);
- //哪类比较大,输出哪一类的回文子串
- if( MaxOdd > MaxEven)
- {
- for(i = indexMid - (MaxOdd - 1) / 2; i <= indexMid + (MaxOdd - 1) / 2; i++)
- {
- putchar(A[i]);
- }
- }
- else
- {
- for(i = First - (MaxEven - 2) / 2; i <= First + 1 + (MaxEven - 2) / 2; i++)
- {
- putchar(A[i]);
- }
- }
- return 0;
- }
/* 长度为N(N很大)的字符串,求这个字符串里的最长回文子串。*/#include <stdio.h>#include <stdlib.h>#include <string.h>//第一类“12321”:中间是一个单独的字符int FindLongPaliSubstr_Odd(const char A[], int * indexMid){ int i = 0, cnt = 0;//cnt表示前后移动位数 int MyMax = 0; int lenOfA = strlen(A); *indexMid = 0; for(i = 1; i <= lenOfA - 2; i++) { cnt = 0; while(i - cnt >= 0 && i + cnt <= lenOfA - 1 && A[i - cnt] == A[i + cnt]) { cnt++; } cnt--; //找到较大长度的回文字符串,保存中心字符的位置 if(MyMax < 2 * cnt + 1) { MyMax = 2 * cnt + 1; *indexMid = i; } } return MyMax;}//第二类“12321”:中间是两个相同的字符。int FindLongPaliSubstr_Even(const char A[],int * First){ int i = 0, cnt = 0;//cnt表示前后移动位数 int MyMax = 0; int lenOfA = strlen(A); *First = 0;//中间两个相同字符的第一个字符位置 for(i = 0; i <= lenOfA - 2; i++) { if(A[i] == A[i + 1]) { cnt = 1; while(i - cnt >= 0 && (i + 1 + cnt) <= lenOfA - 1 && A[i - cnt] == A[i + 1 + cnt]) { cnt++; } cnt--; //找到较大长度的回文字符串,保存中心第一个字符的位置 if(MyMax < 2 * cnt + 2) { MyMax = 2 * cnt + 2; *First = i; } } } return MyMax;}int main(void){ char A[] = "adfadfbadfdg12321fagage"; int indexMid = 0; int First = 0; int i = 0; //两种类别的最长回文子串的长度 int MaxOdd = FindLongPaliSubstr_Odd(A, &indexMid); int MaxEven = FindLongPaliSubstr_Even(A, &First); printf("indexMid = %d\n", indexMid); printf("First = %d\n", First); //哪类比较大,输出哪一类的回文子串 if( MaxOdd > MaxEven) { for(i = indexMid - (MaxOdd - 1) / 2; i <= indexMid + (MaxOdd - 1) / 2; i++) { putchar(A[i]); } } else { for(i = First - (MaxEven - 2) / 2; i <= First + 1 + (MaxEven - 2) / 2; i++) { putchar(A[i]); } } return 0;}
3、数轴上从左到右有n各点a[0], a[1], ……,a[n -1],给定一根长度为L的绳子,求绳子最多能覆盖其中的几个点。
解:我对第3题的题解也是很常规,就是把相邻两个点的距离求出来,保存在一个数组arr[N]里面,从头到尾遍历数组arr[N],和直接选择排序差不多,写两个for循环,第一个for循环(外循环)中计数器i 表示连续线段的起点,第二个for循环(内循环)的计数器 j 从 (i + 1)开始,依次累加Sum,若Sum > L,则记录点的个数(j - i)中的较大值max;其中,外循环,只要遇到的数比L大,就continue,内循环,只要遇到的数比L大,就break,这是因为长度为L的绳子是不可能覆盖这些点的,可以直接跳过!
如图:
my code:
- /*
- 数轴上从左到右有n个点a[0],a[1],...,a[n - 1],给定一根长度为L的绳子,求绳子最多能覆盖其中几个点。
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #define N 8
- int MaxTimesOfL(int A[],int L)
- {
- int i = 0, j = 0;
- int *arr = (int *)malloc(sizeof(int) * (N - 1));
- memset(arr, 0, sizeof(int) * (N - 1));
- //初始化数组arr,两点间的距离为一个数组元素
- for(i = 0; i < N - 1; i++)
- {
- arr[i] = A[i + 1] - A[i];
- }
- //输出该数组
- for(i = 0; i < N - 1; i++)
- {
- printf("%-3d", arr[i]);
- }
- int MaxTimes = 0;
- int Sum = 0;
- //遍历找到覆盖的最多点数
- for(i = 0; i < N; i++)
- {
- if(arr[i] > L)//遇到比L大的数则跳过
- {
- continue;
- }
- Sum = arr[i];
- for(j = i + 1; j < N - 1; j++)
- {
- if(arr[j] > L)//遇到比L大的数则跳过,这一句对于程序来说加与不加都一样
- {
- break;
- }
- Sum += arr[j];
- if(Sum > L)
- {
- break;
- }
- }
- MaxTimes = (MaxTimes > (j - i)) ? MaxTimes : (j - i);
- }
- return (MaxTimes + 1);//因为是线段,所以要加1表示覆盖的点数
- }
- int main(void)
- {
- int A[] = {-1, 0, 3, 9, 11, 13, 14, 25};
- int L = 5;
- int result = MaxTimesOfL(A, L);
- printf("\nthe max times is %d\n", result);
- return 0;
- }
/* 数轴上从左到右有n个点a[0],a[1],...,a[n - 1],给定一根长度为L的绳子,求绳子最多能覆盖其中几个点。*/#include <stdio.h>#include <stdlib.h>#include <string.h>#define N 8int MaxTimesOfL(int A[], int L){ int i = 0, j = 0; int *arr = (int *)malloc(sizeof(int) * (N - 1)); memset(arr, 0, sizeof(int) * (N - 1)); //初始化数组arr,两点间的距离为一个数组元素 for(i = 0; i < N - 1; i++) { arr[i] = A[i + 1] - A[i]; } //输出该数组 for(i = 0; i < N - 1; i++) { printf("%-3d", arr[i]); } int MaxTimes = 0; int Sum = 0; //遍历找到覆盖的最多点数 for(i = 0; i < N; i++) { if(arr[i] > L)//遇到比L大的数则跳过 { continue; } Sum = arr[i]; for(j = i + 1; j < N - 1; j++) { if(arr[j] > L)//遇到比L大的数则跳过,这一句对于程序来说加与不加都一样 { break; } Sum += arr[j]; if(Sum > L) { break; } } MaxTimes = (MaxTimes > (j - i)) ? MaxTimes : (j - i); } return (MaxTimes + 1);//因为是线段,所以要加1表示覆盖的点数}int main(void){ int A[] = {-1, 0, 3, 9, 11, 13, 14, 25}; int L = 5; int result = MaxTimesOfL(A, L); printf("\nthe max times is %d\n", result); return 0;}
最后贴一下试题:
- 百度武汉站
- 2014百度武汉站笔试题
- 2014百度武汉站研发题
- 2014百度武汉站笔试题
- 百度2014校园招聘笔试题(武汉站 9.28)
- 百度2014校招系统分析师笔试题(武汉站)
- 百度[搜索]"武汉工程大学图书馆"
- 百度2014校园招聘试题—自然语言处理工程师(武汉站)
- 百度2014校园招聘软件研发笔试题(武汉站)
- 百度后台开发类笔试题2014校园招聘 武汉站
- 百度武汉站笔试题——算法题第一第二题Java实现
- 2014百度笔试题(武汉)
- 百度 2015 武汉研发笔试题
- [百度笔试] 2014百度校园招聘软件研发题--武汉
- 武汉
- 武汉?
- 武汉
- [众人说武汉]ychyxh-BBS武汉白云黄鹤站.zz
- 使用distcc进行分布式编译来提高编译速度
- 青春
- 阿里巴巴北邮站
- android中的Selector
- Bison-Flex 笔记
- 百度武汉站
- request.getAttribute() session.getAttribute() application.getAttribute() 的getAttribute方法有区别
- 人人校招
- Cocos2D资源加载方式
- 腾讯广州站
- Linux内核设计艺术笔记(三)
- C++枚举
- UVa 112 Tree Summing (scanf()去空格&递归&二叉树遍历)
- Cracking the Coding Interview Chap1 Q1.2