牛客网解题-2017腾讯秋招笔试编程题练习卷

序言

今天15:00-17:00的腾讯笔试,提前做了套练习卷。虽然下午的笔试题答得一塌糊涂,但是之前做的题还是总结一下吧

题目

四个题:编码index + 游戏任务标记 + 和为正整数的质数对 + 纬度编码

编码index这个题,我的理解与答案有挺大出入,放在最后一个来讲吧。


2. 游戏任务标记
  • 题目描述

    游戏里面有很多各式各样的任务,其中有一种任务玩家只能做一次,这类任务一共有1024个,任务ID范围[1,1024]。

    请用32个unsigned int类型来记录着1024个任务是否已经完成。初始状态都是未完成。

    输入两个参数,都是任务ID,需要设置第一个ID的任务为已经完成;并检查第二个ID的任务是否已经完成。 输出一个参数,如果第二个ID的任务已经完成输出1,如果未完成输出0。如果第一或第二个ID不在[1,1024]范围,则输出-1。

  • 输入输出示例

    输入:1024 1024

    输出:1

  • 解题思路

    用32个unsigned int类型来记录1024个数,每个unsigned int应记录32个,即用每位来表示每个任务,1表示完成,0表示未完成。

    验证第二次任务ID是否与第一次任务ID相同,直接用第二次的任务ID来提取对应标记位,如果已被标记为1则表示已完成,否则就是未完成。

  • 代码(C)

#include <stdio.h>

int main()
{
    unsigned int array[32];
    int i = 0, j = 0;
    for (; i < 32; i++)
        array[i] = 0;
    int missionId[2] = {0};
        while (scanf("%d", &missionId[j]) != EOF && getchar() != '\n')
            j++;
        if (missionId[0] > 1024 || missionId[0] < 1 || missionId[1] > 1024 || missionId[1] < 1)
        {
            printf("%d\n", -1);
            return 0;
        }
        else
        {
            array[(missionId[0] - 1)/32] = 1 << ((missionId[0] - 1) % 32);      //元素存储
            printf("%d\n", array[(missionId[1] - 1)/32] >> ((missionId[1] - 1) % 32) & 1 ? 1 : 0);
        }
        return 0;
}


3. 和为正整数的质数对
  • 题目描述

    给定一个正整数,编写程序计算有多少对质数的和等于输入的这个正整数,并输出结果。输入值小于1000。

    如,输入为10, 程序应该输出结果为2。(共有两对质数的和为10,分别为(5,5),(3,7))

  • 输入输出示例

    输入:10

    输出:2

  • 解题思路

    首先写出质数判断函数(2~n-1不能除尽即为质数)

  • 代码(C)

#include <stdio.h>
#include <math.h>

int PrimeNumJudge(int n);

int main()
{
    int N;
    int a,b;
    int count = 0;
    scanf("%d", &N);
        a = 1;
        while (a <= (N / 2))
        {
            b = N - a;
            if (PrimeNumJudge(a) == 0 || PrimeNumJudge(b) == 0)
            {
                a++;
            }
            else
            {
                count++;
                a++;
            }
        }
        printf("%d\n", count);
    return 0;
}

int PrimeNumJudge(int n)
{
    //int upper = sqrt(n);    //改进质数验证
    int i;
    if (n == 1) return 0;
    for (i = 2; i < n; i++)
    {
        if (n % i == 0)
            return 0;
    }
    return 1;
}


4. 纬度编码
  • 题目描述

    geohash编码:geohash常用于将二维的经纬度转换为字符串,分为两步:第一步是经纬度的二进制编码,第二步是base32转码。

    此题考察纬度的二进制编码:算法对纬度[-90, 90]通过二分法进行无限逼近(取决于所需精度,本题精度为6)。

    注意,本题进行二分法逼近过程中只采用向下取整来进行二分,针对二分中间值属于右区间。算法举例如下: 针对纬度为80进行二进制编码过程:

    1) 区间[-90, 90]进行二分为[-90, 0),[0, 90],成为左右区间,可以确定80为右区间,标记为1;
    2) 针对上一步的右区间[0, 90]进行二分为[0, 45),[45, 90],可以确定80是右区间,标记为1;
    3) 针对[45, 90]进行二分为[45, 67),[67,90],可以确定80为右区间,标记为1;
    4) 针对[67,90]进行二分为[67, 78),[78,90],可以确定80为右区间,标记为1;
    5) 针对[78, 90]进行二分为[78, 84),[84, 90],可以确定80为左区间,标记为0;
    6) 针对[78, 84)进行二分为[78, 81), [81, 84),可以确定80为左区间,标记为0;

  • 输入输出示例

    输入:80

    输出:111100

  • 解题思路

    因为只要求精度达到6,设置一个6元素数组,记录每一次的编码取值
    记录区间的上下界,并用二分法不断调整

  • 代码(C)

#include <stdio.h>

int main()
{
    int left, right, middle;
    left = -90, right = 90;
    int latitude, count = 0;
    int array[6] = {0};
    scanf("%d", &latitude);
    while (count < 6)
    {
        middle = (left + right) / 2;
        if (latitude < middle)
        {
            right = middle;
            array[count] = 0;
        }
        else
        {
            left = middle;
            array[count] = 1;
        }
        count++;
    }
    int i = 0;
    for (; i < count; i++)
    {
        printf("%d", array[i]);
    }
    return 0;
}


1. 编码index
  • 题目描述

    假定一种编码的编码范围是a ~ y的25个字母,从1位到4位的编码,如果我们把该编码按字典序排序,形成一个数组如下:

    a, aa, aaa, aaaa, aaab, aaac, … …, b, ba, baa, baaa, baab, baac … …, yyyw, yyyx, yyyy 其中a的Index为0,aa的Index为1,aaa的Index为2,以此类推。

    编写一个函数,输入是任意一个编码,输出这个编码对应的Index.

  • 输入输出示例

    输入:baca

    输出:16331

  • 解题思路

    这个题的我的理解,编码分布是这样的a,aa,aaa,aaaa,…,aaay,aaba,…,aaby,aaca,…aacy,….ayya,…,ayyy,b,ba,baa,baaa,…,然而实际分布并不是这样,不过我并没有从题目中看出类似a,aa,aaa,aaaa,…,aaay,ab,aba,abaa,…,abay,…,abyy,ac,aca,acaa,…的分布规律。

    所以这里仅给出我自己理解的代码实现(另外三题AC,本题未通过)

  • 代码(C)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    int P = 25;
    int N = P * 25;
    int M = N * 25;
    int length;             //记录输入字符串长度
    int index = 0;
    int count[4] = {0};     //记录四位字符与a字符各自的差值
    char string[100];
    while (fgets(string, 100, stdin))       //循环输入
    {
        length = strlen(string) - 1;        //strlen()不计'\0',此处-1可能与fgets函数自动添加\0有关
        int j = 0;
        for (; j < length; j++)
        {
            count[j] = string[j] - 'a';
        }
        switch (length)                      //小于3位的字符
        {
            case 1:
                printf("%d\n", count[0] * M);
                break;
            case 2:
                printf("%d\n", count[0] * M + 1);
                break;
            case 3:
                printf("%d\n", count[0] * M + 2);
                break;
            default:
                break;
        }
        if (length == 4)                    //4位字符
        {
            index = 3 + count[0] * M + count[1] * N + count[2] * P + count[3];
            printf("%d\n",index);
        }
    }
    return 0;
}
//牛客网上的AC代码一例
#include <stdio.h>
#include <string.h>

#define N1 1
#define N2 25
#define N3 (25 * 25)
#define N4 (25 * 25 * 25)

#define C1 N1
#define C2 (N1 + N2)
#define C3 (N1 + N2 + N3)
#define C4 (N1 + N2 + N3 + N4)

int main()
{
    char code[5] = {0};
    scanf("%s", code);
    int index = 0;
    switch(strlen(code)){
        case 4: index += C1 * (code[3] - 'a') + 1;
        case 3: index += C2 * (code[2] - 'a') + 1;
        case 2: index += C3 * (code[1] - 'a') + 1;
        case 1: index += C4 * (code[0] - 'a');
        default: break;
    }
    printf("%d\n", index);
    return 0;
}



Acknowledgements:
http://blog.csdn.net/jiangnanyouzi/article/details/6827534 (编码index AC解法)

2017.09.13

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值