各互联网名企面试题汇总(1)
1.PPTV2015研发工程师笔试题(对称子字符串)
输出字符串中对称的子字符串的最大长度
输入描述:测试输入包含1个测试用例,一个字符串str。
输出描述:输出最长的对称子字符串长度。
输入例子:roorle
输出例子:4
解法:中心扩展法。我们可以枚举中心位置,然后再在该位置上扩展,记录并更新得到的最长对称子串长度。
参考代码:
#include<iostream>
#include<stdio.h>
#include<string>
using namespace std;
char str1[10003];
int main()
{
int LongestPalindrome(char *s, int n);
while (gets_s(str1))
{
int n = strlen(str1);
cout << "最大对称子串的长度为:" << LongestPalindrome(str1, n) << endl;
}
return 0;
}
int LongestPalindrome(char *s, int n)
{
int i, j, max, c;
if (s == 0 || n < 1)
{
return 0;
}
max = 0;
//i为对称中心位置
for (i = 0; i < n; ++i)
{
//对称长度为奇数
for (j = 0; (i - j >= 0) && (i + j < n); ++j)
{
//判断条件的意思是i-j>=0表示头部未溢出
//i+j<n表示尾部未溢出
if (s[i - j] != s[i + j])
{
break;
}
c = j * 2 + 1;//更新对称长度
}
if (c > max)
{
max = c;//更新最大对称长度
}
//对称长度为偶数
for (j = 0; (i - j >= 0) && (i + j + 1 < n); ++j)
{
//判断条件的意思是i-j>=0表示头部未溢出
//i+j+1<n表示尾部未溢出
if (s[i - j] != s[i + j + 1])
{
break;
}
c = j * 2 + 2;//更新对称长度
}
if (c > max)
{
max = c;//更新最大对称长度
}
}
return max;
}
输出结果测试:
2.迅雷2016研发工程师笔试题(循环队列)
假设以数组A[60]存放循环队列元素,其头指针是front=47,当前队列有50个元素,则队列的尾指针的值为(B)
A。3 B。37 C。97 D。50
解释:可以把循环队列理解为钟表,一圈是60,现在头在47,所以尾部应该在47-(60-50)=37 所以选B。
3.滴滴出行2017秋招编程题(末尾0的个数)
输入一个正整数n,求n阶乘末尾有多少个0?
输入描述:输入为一行,n(1<n<100)
输出描述:输出一个整数,即题目所求。
输入例子:10
输出例子:2
解释:N!能产生0的质数组合只能是2 * 5,也就是说当对N!进行质数分解之后,N!末尾0的个位M取决于2的个数X和5的个数Y的最小值,即M = min(X,Y)。又因为能被2整除的数出现的频率比能被5整除的数高得多,且出现一个5的时,最少会同时出现一个2,所以M = Y。即得出Y的值就可以得到N!末尾0的个数。
完整代码如下:
#include<iostream>
using namespace std;
static long GetZerosNum(long n);
int main()
{
long n;
printf("请输入一个正整数n:\n");
scanf_s("%d",&n);
//printf("\n");
printf("%d!末尾0的个数为:%d\n", n, GetZerosNum(n));
return 0;
}
//统计n!末尾0的个数
static long GetZerosNum(long n)
{
long num = 0;
int i, j;
for (i = 1; i <= n; i++)
{
j = i;
while (j % 5 == 0)
{
num++;
j /= 5;
}
}
return num;
}
测试结果:
4.美团2016研发工程师笔试题(求平均年龄)
题目要求:已知某公司总人数为w,平均年龄为y(每年三月末计算,同时每年三月初入职新人),假设每年离职率为x(0<x<1),每年保持所有员工总数不变进行招聘,新员工平均年龄21岁。从今年三月末开始,请实现一个算法,可以计算出第N年后公司员工的平均年龄(结果向上取整)
解释:感觉这道题没有什么难度,但是存在一个坑点,有可能就容易忽视掉这个问题,每过一年年龄就会加1。
完整代码如下:
#include<iostream>
using namespace std;
int main()
{
int w, n;//w为公司总人数,n为n年后
float x, y;//x为离职率(0<x<1),y为起始平均年龄
int GetAverageAge(int w, float y, float x, int n);
printf("依次键入:总人数w、初始平均年龄y、离职率x、经过n年\n");
cin >> w >> y >> x >> n;
printf("%d年后公司平均年龄为%d\n", n, GetAverageAge(w, y, x, n));
return 0;
}
int GetAverageAge(int w, float y, float x, int n)
{
int i;
int AverageAge;
for (i = 0; i <= n; i++)
{
++y;
y = (1 - x)*w*y + 21 * x*w;
y /= w;
}
AverageAge = ceil(y);
return AverageAge;
}
测试结果为:
5.阿里巴巴2015研发工程师笔试题(进制转换)
题目:用十进制计算30!,将结果转换为3进制表示的话,该进制下的结果末尾会有(E)个0
A. 6 B. 8 C. 10 D. 12 E. 14 F. 16
解释:选E,这个问题可以转化为:30!中最多可以被多少个3整除,即0~30中3的倍数个数+9的倍数个数+27的倍数个数
(30%3==0)个数为10,(30%9==0)个数为3,(30%27==0)个数为1。10+3+1=14,选E。
6.360校招笔试2016(直接插入排序)
设有一组初始化关键字序列为{30、20、10、25、15、28},则第4趟直接插入排序结束后的结果是(B)
A。 10、15、20、25、28、30
B、 10、15、20、25、30、28
C、 10、20、30、25、15、28
D、 10、20、25、30、15、28
解释:
直接插入排序的基本思想:第i趟排序将序列中的第i+1个元素ki+1插入到一个已经按值有序的子序列(k1,k2,。。。,ki)中的合适位置,使得插入后的序列仍然保持按值有序。
初始序列:{(30),20,10,25,15,28}
第一趟::{(20,30),10,25,15,28}
第二趟::{(10,20,30),25,15,28}
第三趟::{(10,20,25,30),15,28}
第四趟::{(10,15,20,25,30),28}
第五趟::{(10,15,20,25,28,30)}
7.乐视2017暑期实习生笔试题(有序数组)
对一个含有20个元素的有序数组做二分查找,数组起始下标为1,则查找A[2]的比较序列的下标为()
A.、 9、5、4、2
B、 10、5、3、2
C、 9、6、2
D、 20、10、5、3、2
解释:二分查找即折半查找,基本思想是:减少查找序列的长度,分而治之地进行关键字的查找。
折半查找的原则是:(起始下标+末尾下标)/2,向下取整
第一次:(1+20)/2=10.5,取10
第二次:(1+10)/2=5.5,取5
第三次:(1+5)/2=3,取3
第四次:(1+3)/2=2,取2
所以结果为:10、5、3、2 选B
8.有道云2015校招笔试(屏幕解锁方案)
题目描述:在满足以下条件的前提下,手机解锁九宫格一共有多少种解锁图案?
条件1:解锁图案至少经过两个点
条件2:经过的点不能重复
解法:用深度优先递归,如果当前路径大于2个点小于等于9个点并且无重复,加入到结果集,添加周围未遍历过的点继续调用递归。
完整代码如下:
#include<iostream> #include<cstring> using namespace std; int mark[10][10];//标记非法路径的数组 int vis[10];//标记格子是否使用 int num[20], ans = 0, lim; void dfs(int cnt) //深度优先遍历 { if (cnt >= 2) { //当点数大于等于2时,结果加1 ans++; } for (int i = 1; i <= 9; i++) //从1--9号格子依次遍历 { if (!vis[i])//如果格子没有被使用,则进入循环 { if (mark[i][num[cnt - 1]] && !vis[mark[i][num[cnt - 1]]]) continue; num[cnt] = i; vis[i] = 1; dfs(cnt + 1); vis[i] = 0; } } } int main() { num[0] = 0; memset(mark, 0, sizeof(mark));//初始化mark数组 //标记不可能出现的路径,例如1->3->2 mark[1][3] = 2, mark[1][7] = 4, mark[1][9] = 5; mark[2][8] = 5, mark[3][7] = 5, mark[3][9] = 6; mark[4][6] = 5, mark[7][9] = 8; for (int i = 1; i <= 9; i++) for (int j = i + 1; j <= 9; j++) mark[j][i] = mark[i][j]; //完成mark数组赋值 memset(vis, 0, sizeof(vis)); //初始化vis数组 dfs(0); cout << ans << endl; return 0; }
测试结果为:
个人能力有限,欢迎各位博友批评指正!!!