您的位置:首页 > 编程语言 > C语言/C++

深信服2018校园招聘C++工程师编程题 - 题解

2017-11-30 01:14 501 查看
深信服2017的校园招聘的题目和这次的几乎一样,不知道贵公司是什么样的想法。做过2017的题目的同学应该会比较占优势。题目不难,比较考验编程的技巧与准确度。

第一题:堆排序

题目:

函数
heap_sort
使用堆排序的方法对数组
arr
进行排序,排序后的数据为降序,相关的代码如下,请补充确实的部分。

//  调整为小顶堆
static void heap_arrange(int arr[], int cur, int cnt)  //调整为小顶堆
{
int heaptop_val = arr[cur]; //堆顶的值
while (cur < cnt) {
int left = 2 * cur + 1;
int right = 2 * cur + 2;
int min = -1;
int min_val = ________;
if (left < cnt && arr[left] < min_val) { //检查是否比左节点大
min = left;
min_val = arr[left];
}
if (right < cnt && arr[right] < min_val) {//检查是否比右节点大
min = right;
}
if (min == ________)
break;
arr[cur] = ________;
cur = ________;
}
arr[cur] = ________;
}


解析:

堆排序的原理就是树上的插入排序,因此,堆排序的原理还是要准确理解的,这样才能填出来,既然是插入排序,那么,
min_val
就一直是
heaptop_val
min_val
与左右两个孩子比较得出最小的那个元素,如果最小的元素还是
heaptop_val
那么
min
的值就没变,仍然是
-1
,这个时候插入排序结束,找到了插入的位置就跳出;否则的话就把左右孩子最小的那个结点赋值给当前节点,故
arr[cur] = arr[min]
,更新当前节点
cur = min
;最后,把
heaptop_val
调到要插入的位置,即
arr[cur] = heaptop_val


代码:

//  调整为小顶堆
static void heap_arrange(int arr[], int cur, int cnt)  //调整为小顶堆
{
int heaptop_val = arr[cur]; //堆顶的值
while (cur < cnt) {
int left = 2 * cur + 1;
int right = 2 * cur + 2;
int min = -1;
int min_val = heaptop_val;
if (left < cnt && arr[left]
18998
< min_val) { //检查是否比左节点大
min = left;
min_val = arr[left];
}
if (right < cnt && arr[right] < min_val) {//检查是否比右节点大
min = right;
}
if (min == -1)
break;
arr[cur] = arr[min];
cur = min;
}
arr[cur] = heaptop_val;
}


第二题:单链表冒泡排序

题目:

请实现
list_sort
,使用冒泡法将
head
指向的链表按
val
的值大小排成升序。

struct node {
int val;
struct node *next;
};

static void list_sort(struct node *head)
{

}


解析:

冒泡法大家都很熟悉,单链表来实现无非就是考到链表的基本操作,但是这里我们简化一下代码,也就是说,我们是采用交换两结点的值的做法而不是交换两个结点。

冒泡法有两个循环,最里面的循环是排序用的,而最外面的循环是排序需要的趟数,排序的趟数也就是链表的长度减一(排这么多趟一定可以排好序,但是不一定需要这么多);

这样一来就要求链表的长度,不好,注意到,如果排一趟序无可交换的元素,那么就说明链表已经排好序了,所以,利用这个原理可以设置一个标志变量
f
来维护一趟排序中是否有元素的交换,一趟排序后判一下
f
就可以知道是否跳出最外层的循环.

代码:

static void list_sort(struct node *head)
{
//TODO:
while (true) {
int f = true;
struct node * p = head;
for (;p && p->next; p = p->next)
if (p->val > p->next->val) {
f = false;
int tmp = p->val;
p->val = p->next->val;
p->next->val = tmp;
}
if (f)
break;
}
}


第三题:二进制位反序

题目:

编写函数
reverse
,将
val
(32位无符号整数)的二进制位反序,比如,如果
val
的二进制表示为
1011000011111111
,反序后
val
的二进制表示为
1111111100001101


unsigned int reverse(unsigned int num)
{

}


解析:

做法很多,我的做法是把一边去掉最后一位数,一边生成反序后的十进制数。

代码:

unsigned int reverse(unsigned int num)
{
//TODO:
unsigned int ret = 0;
for (int i = 0; i < 32; i++, num /= 2)
ret = ret * 2 + num % 2;
return ret;
}


第四题

题目:

函数
match
检查字符串
str
是否匹配模板
pattern
,匹配则返回
0
,否则返回
-1


模板支持普通字符(
a-z0-9A-Z
)及通配符
?
*
,普通字符匹配该字符本身,
?
匹配任意一个字符,
*
匹配任意多个字符。比如字符串
abc
对下述模板的匹配结果为:

模板-结果
abc
0
a*
0
a*c
0
a*b
-1
ab?
0
a?
-1
请完成该函数代码:

int match(const char *str, const char *pattern)
{

}


解析:

由于数据不大,故可以暴力递归解决,递归的终止条件是:

strlen(str)
等于0,并且
strlen(pattern)
等于0,这时匹配成功;

strlen(str)
strlen(pattern)
有且只有一个为0,这时匹配失败。

如果
strlen(str)
strlen(pattern)
都不为0,那么继续递归:

pattern[0]
?
,那么就判断
pattern + 1
str + 1
是否匹配;

pattern[0]
*
,那么判断
pattern + 1
str + i
(0<=i<strlen(str)0<=i<strlen(str))里面是否有一个匹配,只要有一个匹配,那么就匹配了,如果所有的都不匹配,那么就不匹配了;

pattern[0]
为字母或数字,那么就判断
str[0]
pattern[0]
是否相等,如果不相等就不匹配,如果相等,那么还要判断
pattern + 1
str + 1
是否匹配。

这个题还要注意一点,题目给出的输入函数会把
\n
也会加入到字符串中,因此可以先把
\n
去掉,不去掉也可以,那么判断
pattern[0]
的时候就要注意顺序,先判断
*
?


代码:

int match(const char *str, const char *pattern)
{
//TODO:
int str_len = strlen(str), pattern_len = strlen(pattern);
if (!str_len && !pattern_len)
return 0;
if (!pattern_len || !str_len)
return -1;
if (pattern[0] == '*') {
for (int i = 0; str[i]; i++)
if (0 == match(str + i, pattern + 1))
return 0;
return -1;
} else if (pattern[0] == '?') {
return match(str + 1, pattern + 1);
} else {
return pattern[0] == str[0] ? match(str + 1, pattern + 1) : -1;
}
}


DIY数据:

// input
abcd
*********************
// output
match


第五题:围棋的“气”

题目:

函数
calc
计算围棋盘位置
(x,y)
处的棋子还有多少口气。

某个位置处的棋子还有多少口气的计算方法(简化计算):从该位置出发,向四个方向遍历,允许拐弯,但不允许走斜线,如果遇到边线和对方的棋子,则认为不能继续往前走。遍历完成后统计遍历过程中遇到的未落子的位置个数,该位置个数即出发点棋子的气的数目。

解析:

首先,这个简化计算描述就不清楚,注意这句话:如果遇到边线和对方的棋子,则认为不能继续往前走,那么遇到自己的棋子怎么办呢?这里值得思考一下;

如果遇到边线和对方的棋子和自己的棋子,则认为不能继续往前走,那么广搜一下,看看目标位置能到的位置有多少个,但是我只过了66.6%66.6%的数据,不知道哪里出了问题也不知道我是不是理解错题目了,于是,我计算了下围棋真正的气

首先找到该棋子的连通块,然后统计连通块外围棋子的个数就是该棋子的气。

找连通块我也没有用广搜,用的是一种扩散的想法,代码类似于这样子:往目标棋子滴一滴墨水,然后一秒钟后就会往外扩散,然后下一秒往外扩散,直到扩散不了。 具体实现看代码。

代码:

int calc(struct weiqi *wq, int y, int x)
{
//TODO:
if (wq->board[x][y] == NONE)
return -1;
enum color nowChess = wq->board[x][y];

int dirx[] = {0, 0, 1, -1};
int diry[] = {1, -1, 0, 0};
int used[19][19] = {0};
used[x][y] = 1;
while (true) {
int f = 0;
for (int i = 0; i < 19; i++) {
for (int j = 0; j < 19; j++) {
if (used[i][j]) {
for (int k = 0; k < 4; k++) {
int tx = i + dirx[k];
int ty = j + diry[k];
if (tx >= 0 && tx < 19 && ty >= 0 && ty < 19 &&
wq->board[tx][ty] == nowChess && !used[tx][ty])
used[tx][ty] = 1, f = 1;
}
}
}
}
if (!f)
break;
}
int ans = 0;
for (int i = 0; i < 19; i++) {
for (int j = 0; j < 19; j++) {
if (used[i][j] == 1) {
for (int k = 0; k < 4; k++) {
int tx = i + dirx[k];
int ty = j + diry[k];
if (tx >= 0 && tx < 19 && ty >= 0 && ty < 19 &&
wq->board[tx][ty] == NONE && used[tx][ty] != 1)
used[tx][ty] = 2;
}
}
}
}
for (int i = 0; i < 19; i++) {
for (int j = 0; j < 19; j++) {
ans += (used[i][j] == 2);
}
}
return ans;
}


DIY数据:

// input
0000000000000000000
0011100000000000000
0001000000000000000
0001111000000000000
0000001000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000110000
0000000000000000000
0000000000000000000
0000000000000000000
2,1
// output
16


五个题完整代码:

一、

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
static void heap_arrange(int arr[], int cur, int cnt);

static int heap_verify(int arr[], int cnt)
{
int i;
for (i = 0; i < cnt / 2; ++i) {
int lhs = 2 * i + 1;
int rhs = 2 * i + 2;

if (lhs < cnt && arr[i] > arr[lhs]) {
fprintf(stderr, "arr[%d]:%d > arr[%d]:%d\n", i, arr[i], lhs, arr[lhs]);
return -1;
}
if (rhs < cnt && arr[i] > arr[rhs]) {
fprintf(stderr, "arr[%d]:%d > arr[%d]:%d\n", i, arr[i], rhs, arr[rhs]);
return -1;
}
}
return 0;
}

static void heap_print(int arr[], int cnt)
{
int layer = 0, num = 0;
for (layer = 0; num < cnt; ++layer) {
int i = 0;
for (i = 0 ; i < (1 << layer) && num < cnt ; ++i)
printf("%3d ", arr[num++]);
printf("\n");
}
}
static void heap_sort(int arr[], int cnt)
{
int i;

printf("origin:\n");
heap_print(arr, cnt);
//  建堆
for (i = cnt / 2 - 1; i >= 0; --i) {
heap_arrange(arr, i, cnt);
}
printf("make heap:\n", i);
heap_print(arr, cnt);
assert(heap_verify(arr, cnt) == 0);
for (i = cnt - 1; i > 0; --i) {
int tmp;
tmp = arr[0];
arr[0] = arr[i];
arr[i] = tmp;
printf("sort i=%d\n", i);
heap_print(arr, cnt);
heap_arrange(arr, 0, i);
heap_print(arr, cnt);
assert(heap_verify(arr, i) == 0);
}
printf("sorted:\n");
heap_print(arr, cnt);
}
static int input(int **arr, int *size)
{
int i;
int ret;

ret = fscanf(stdin, "%d\n", size);
if (ret != 1)
return -1;
*arr = (int *)malloc(sizeof(int) * (*size));
for (i = 0; i < *size; ++i) {
fscanf(stdin, "%d ", &(*arr)[i]);
}
return 0;
}

int main(int argc, char *argv[])
{
int *arr = NULL;
int cnt = 0;
int i;

if (input(&arr, &cnt) < 0) {
fprintf(stderr, "input error\n");
return 0;
}
heap_sort(arr, cnt);
return 0;
}
//  调整为小顶堆
static void heap_arrange(int arr[], int cur, int cnt)  //调整为小顶堆
{
int heaptop_val = arr[cur]; //堆顶的值
while (cur < cnt) {
int left = 2 * cur + 1;
int right = 2 * cur + 2;
int min = -1;
int min_val = heaptop_val;
if (left < cnt && arr[left] < min_val) { //检查是否比左节点大
min = left;
min_val = arr[left];
}
if (right < cnt && arr[right] < min_val) {//检查是否比右节点大
min = right;
}
if (min == -1)
break;
arr[cur] = arr[min];
cur = min;
}
arr[cur] = heaptop_val;
}


二、

#include <stdio.h>
#include <malloc.h>

struct node {
int val;
struct node *next;
};

static void list_sort(struct node *head);

struct node *list_create(int arr[], int size)
{
struct node *head = NULL;
int i;
for (i = size - 1; i >= 0; --i) {
struct node *p = (struct node *)malloc(sizeof(struct node));

p->val = arr[i];
p->next = head;
head = p;
}
return head;
}
static void list_print(struct node *head)
{
for (; head; head = head->next) {
printf("%d", head->val);
if (head->next)
printf(" ");
}
printf("\n");
}
static void list_free(struct node *head)
{
struct node *next;
while (head) {
next = head->next;
free(head);
head = next;
}
}
static int input(int **arr, int *size)
{
int i;
int ret;

ret = fscanf(stdin, "%d\n", size);
if (ret != 1)
return -1;
*arr = (int *)malloc(sizeof(int) * (*size));
for (i = 0; i < *size; ++i) {
fscanf(stdin, "%d ", &(*arr)[i]);
}
return 0;
}

int main(int argc, char *argv[])
{
struct node *head;
int *arr = NULL;
int size = 0;

if (input(&arr, &size) < 0) {
fprintf(stderr, "input error\n");
return 0;
}
head = list_create(arr, size);
list_sort(head);
list_print(head);
list_free(head);
free(arr);
return 0;
}

static void list_sort(struct node *head) { //TODO: while (true) { int f = true; struct node * p = head; for (;p && p->next; p = p->next) if (p->val > p->next->val) { f = false; int tmp = p->val; p->val = p->next->val; p->next->val = tmp; } if (f) break; } }


三、

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

unsigned int reverse(unsigned int num) { //TODO: unsigned int ret = 0; for (int i = 0; i < 32; i++, num /= 2) ret = ret * 2 + num % 2; return ret; }

int main(int argc, char *argv[])
{
unsigned int num = 0;
unsigned int ret = 0;

if (1 != fscanf(stdin, "0x%x", &num)) {
fprintf(stderr, "input error\n");
return 0;
}
ret = reverse(num);
printf("%08x\n", ret);
return 0;
}


四、

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <malloc.h>

int match(const char *str, const char *pattern)
{
//TODO:
int str_len = strlen(str), pattern_len = strlen(str);
if (!str_len && !pattern_len)
return 0;
if (!pattern_len || !str_len)
return -1;
if (pattern[0] == '*') {
for (int i = 0; str[i]; i++)
if (0 == match(str + i, pattern + 1))
return 0;
return -1;
} else if (pattern[0] == '?') {
return match(str + 1, pattern + 1);
} else {
return pattern[0] == str[0] ? match(str + 1, pattern + 1) : -1;
}
}

int input(char **src, char **ptn)
{
char buf[10240];

*src = NULL;
*ptn = NULL;
if (fgets(buf, sizeof(buf), stdin) == 0)
goto failed_;
*src = strdup(buf);
if (fgets(buf, sizeof(buf), stdin) == 0)
goto failed_;
*ptn = strdup(buf);
return 0;
failed_:
if (*src)
free(*src);
if (*ptn)
free(*ptn);
*src = NULL;
*ptn = NULL;
return -1;
}

int main(int argc, char *argv[])
{
char *src = NULL;
char *ptn = NULL;

if (input(&src, &ptn) < 0) {
fprintf(stderr, "error\n");
return 0;
}

if (match(src, ptn) == 0) {
printf("match\n");
} else {
printf("unmatch\n");
}
return 0;
}


五、

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

enum color {
NONE, WHITE, BLACK, //棋子颜色,NONE表示未落子
};
struct weiqi {
enum color board[19][19]; //棋盘上每个位置的落子
};

int calc(struct weiqi *wq, int y, int x) { //TODO: if (wq->board[x][y] == NONE) return -1; enum color nowChess = wq->board[x][y]; int dirx[] = {0, 0, 1, -1}; int diry[] = {1, -1, 0, 0}; int used[19][19] = {0}; used[x][y] = 1; while (true) { int f = 0; for (int i = 0; i < 19; i++) { for (int j = 0; j < 19; j++) { if (used[i][j]) { for (int k = 0; k < 4; k++) { int tx = i + dirx[k]; int ty = j + diry[k]; if (tx >= 0 && tx < 19 && ty >= 0 && ty < 19 && wq->board[tx][ty] == nowChess && !used[tx][ty]) used[tx][ty] = 1, f = 1; } } } } if (!f) break; } int ans = 0; for (int i = 0; i < 19; i++) { for (int j = 0; j < 19; j++) { if (used[i][j] == 1) { for (int k = 0; k < 4; k++) { int tx = i + dirx[k]; int ty = j + diry[k]; if (tx >= 0 && tx < 19 && ty >= 0 && ty < 19 && wq->board[tx][ty] == NONE && used[tx][ty] != 1) used[tx][ty] = 2; } } } } for (int i = 0; i < 19; i++) { for (int j = 0; j < 19; j++) { ans += (used[i][j] == 2); } } return ans; }int input(struct weiqi *wq, int *x, int *y)
{
int row, col;
int ret;
char buf[80];

for (row = 0; row < 19; ++row) {
if (fgets(buf, sizeof(buf), stdin) == NULL)
return -1;
if (strlen(buf) < 19)
return -1;
for (col = 0; col < 19; ++col) {
switch (buf[col]) {
case '0':
wq->board[row][col] = NONE;
break;
case '1':
wq->board[row][col] = WHITE;
break;
case '2':
wq->board[row][col] = BLACK;
break;
default:
return -1;
}
}
}
ret = fscanf(stdin, "%d,%d\n", x, y);
if (ret != 2)
return -1;
for (row = 0 ; row < 19; ++row) {
for (col = 0; col < 19; ++col) {
fprintf(stderr, "%d ", wq->board[row][col]);
}
fprintf(stderr, "\n");
}
fprintf(stderr, "x = %d, y = %d\n", *x, *y);
return 0;
}

int main()
{
struct weiqi wq;
int x = 0, y = 0;
int cnt;

memset(&wq, 0, sizeof(wq));
if (input(&wq, &x, &y) < 0) {
fprintf(stderr, "error!\n");
return 1;
}
cnt = calc(&wq, x, y);

printf("%d\n", cnt);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: