[vivo]2020届春招在线编程考试

点击上方蓝字关注我,我们一起学编程
如果觉得内容还不错,请帮忙分享一下
有任何疑问或者想看的内容,欢迎私信

微信搜索《编程笔记本》(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;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值