序言
今天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