点击上方蓝字关注我,我们一起学编程
如果觉得内容还不错,请帮忙分享一下
有任何疑问或者想看的内容,欢迎私信
微信搜索《编程笔记本》(codingbook2020),获取更多干活。
今天分享 3 道 vivo 的春招编程题。
1、现有一个 3x3 规格的 Android 智能手机锁屏程序和两个正整数 m 和 n ,请计算出使用最少m 个键和最多 n个键可以解锁该屏幕的所有有效模式总数。
其中有效模式是指:
- 每个模式必须连接至少 m 个键和最多 n 个键;
- 所有的键都必须是不同的;
- 如果在模式中连接两个连续键的行通过任何其他键,则其他键必须在模式中选择,不允许跳过非选择键(如图);
- 顺序相关,单键有效(这里可能跟部分手机不同)。
输入:m、n ,代表允许解锁的最少 m 个键和最多 n 个键。
输出:满足 m 和 n 个键数的所有有效模式的总数。
解析:这是典型的深度优先搜索的应用,
C++ 代码:
class Solution {
public:
bool canGo(int i, int j) {
if (i < 0 || i > 2 || j < 0 || j > 2 || visited[i][j] == true) {
return false;
}
return true;
}
//d:已经被选中的键的个数(深度)
void DFS(int i, int j, int depth){
if (depth == pointNum) {
return;
}
visited[i][j] = true;
++res[++depth];
//选择下一个键
for (int k = 0; k < 16; k++) {
int ii = i + direction[k].first;
int jj = j + direction[k].second;
if (canGo(ii, jj)) { //该点未被选择
DFS(ii, jj, depth);
} else if (k < 8) { //这步最关键,前8个方向的键若被按下了,可以选择同样方向但更远一步的位置
ii += direction[k].first;
jj += direction[k].second;
if (canGo(ii, jj)) { //该点未被选择
DFS(ii, jj, depth);
}
}
}
visited[i][j] = false;
return;
}
int solution(int m, int n) {
if (m > n) {
return 0;
}
// 设置参数
pointNum = n;
// 深度优先搜索
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
DFS(0, 0, 0);
}
}
int retval = 0;
for (int i = m; i <= n; ++i) {
retval += res[i];
}
return retval;
}
private:
vector<pair<int, int>> direction = {
{ -1, 0 }, { -1, 1 }, { 0, 1 }, { 1, 1 }, // 上、右上、右、右下
{ 1, 0 }, { 1, -1 }, { 0, -1 }, { -1, -1 }, // 下、左下、左、左上
{ -2, 1 }, { -1, 2 }, { 1, 2 }, { 2, 1 }, // 不相邻但连线时不会经过其他点,如 1-8、6-7 等
{ 2, -1 }, { 1, -2 }, { -1, -2 }, { -2, -1 }
};
// 存储结果
vector<int> res(10, 0);
// 记录划过的点
vector<vector<bool>> visited(3, vector<bool>(3, false));
// 最多划过的点数
int pointNum;
};
2、现给定任意正整数 n,请寻找并输出最小的正整数 m(m>9),使得 m 的各位(个位、十位、百位 …)之乘积等于 n ,若不存在则输出 -1。
解析:对于小于 10 的数 n ,按照规则应输出 10+n 。对于大于 10 的数,需要分解为若干个数位之积,由于有“最小”的要求,那么数字的个数应尽可能少,并且大的数字应放置于较低的位。而数字可以分解为 9,8,…,2 的因子之积,所以先求出所有的尽可能多的 9 因子,再求出尽可能多的 8 因子,… ,直至求至因子 2 。当分解完所有因子(9,8,… ,2)之后,剩余的值应该是 1 ,若不是 1 ,则说明这个数不能被分解为各数位之积。
C++ 代码:
class Solution {
public:
int solution(int n) {
if (n < 10) {
return 10 + n;
}
int res = 0;
int base = 1;
for (int i = 9; i > 1; --i) {
while (n % i == 0) {
res += i * base;
base *= 10;
n /= i;
}
}
if (n != 1) {
res = -1;
}
return res;
}
};
3、在 vivo 产线上,每位职工随着对手机加工流程认识的熟悉和经验的增加,日产量也会不断攀升。假设第一天量产 1 台,接下来 2 天(即第二、三天)每天量产 2 件,接下来 3 天(即第四、五、六天)每天量产 3 件 … 以此类推,请编程计算出 n 天总共可以量产的手机数量。
解析:每天的产量类似于:1,2,2,3,3,3,4,4,4,4,5,… 我们需要依次计算出产量为 1 的总数量、产量为 2 的总数量 … ,将其依次累加到结果中,伴随着天数的递增,当天数超出 n 时,结果只加上实际天数的产量。
C++ 代码:
class Solution {
public:
int solution(int n) {
int res = 0;
int day = 1;
while (1) {
int all = (1 + day) * day / 2; // 高斯求和
if (all > n) {
res += day * (n - day * (day - 1) / 2);
break;
}
res += day * day;
++day;
}
return res;
};