华为2015届校园招聘机试题二

华为今年软开提前批招聘的特别早,从7月中旬就开始了,广大IT屌丝们表示普遍没有心理准备啊~~华为软开校招共分三轮,第一轮是上机测试,一共3个编程题,满分320分,初级题(60分)、中级题(100分)、高级题(160分),做出一道题即可进入下一轮(中间还有个性格测试题,不过绝大部分人都能过),第二题是一道字符串处理题(貌似华为每年机试题目里,大都会有一道字符串处理的题目),题目大概是这样的:

给定一个字符串str,比如:gyreabtcdgkljnzab,该字符串由用户在控制台自己输入,然后接着用户输入替换组数m,比如m=2,然后用户根据前面的组数输入替换字符串,输入格式可如下:ab->abcd,每个输入之间独占一行。最后程序输出替换后的字符,比如:组1:经过ab->abcd后,源字符串变为:gyreabcdtcdgkljnzabcd,组2:经过dt->kb后,源字符串变为:gyreabckbcdgkljnzabcd,于是最终输出:gyreabckbcdgkljnzabcd。示例:


input:
gyreabtcdgkljnzab
2
ab->abcd
dt->kb

output:
gyreabckbcdgkljnzabcd


一、C语言解法
思路:利用字符数组src将源字符串存储下来,根据输入的替换组数m,动态声明3个二维字符数组str3[m][]、str1[m][]、str2[m][],一个用于存储替换


字符,一个用于存储被替换的字符串,一个存储替换后的字符串,如对于替换字符串str3[1][] = "ab->abcd",则str1[1] = "ab",str2[1] = "abcd"。


具体代码及注释如下:



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

void splitStr( char *src, char *dst1, char *dst2 );
int strReplace( char *src, char *dst, char **str1, char **str2, const int num );


int _tmain(int argc, _TCHAR* argv[])
{
	char src[300] = {'\0'};						//	源字符串
	char dst[300] = {'\0'};						//	目的字符串
	int m = 0;								//	替换组数
	char **str3 = NULL;							//	替换字符串
	int i = 0;
	char **str1 = NULL, **str2 = NULL;

	//	获取源字符串
	gets( src );
	//	获取替换组数
	scanf( "%d", &m );
	getchar();												//	此时换行符留在stdin缓冲区中,必须将其读取,接着一条gets语句接收将是换行符

	//	动态申请内存,为拆分替换字符串做准备
	str1 = (char **)malloc( sizeof(char *)*m );
	str2 = (char **)malloc( sizeof(char *)*m );
	str3 = (char **)malloc( sizeof(char *)*m );
	for( i=0; i<m; i++ )
	{
		*(str1+i) = (char *)malloc( 30 );
		*(str2+i) = (char *)malloc( 30 );
		*(str3+i) = (char *)malloc( 30 );
		memset( *(str1+i), 0, 30 );
		memset( *(str2+i), 0, 30 );
		memset( *(str3+i), 0, 30 );

		gets( *(str3+i) );									//	获取替换字符串
		splitStr( *(str3+i), *(str1+i), *(str2+i) );		//	拆分替换字符串
	}
	
	
	//	对源字符串进行替换处理
	if( 0 == strReplace( src, dst, str1, str2, m ) )
		puts( dst );

	system( "pause" );
	for( i=0; i<m; i++ )
	{
		free( *(str1+i) );
		free( *(str2+i) );
		free( *(str3+i) );
	}
	free( str1 );
	free( str2 );
	free( str3 );
	str1 = NULL;
	str2 = NULL;
	str3 = NULL;

	return 0;
}

/**************************************************************************************
说明:对字符串进行分割操作一般采用strtok库函数进行处理,但是此处考虑到分隔符为“->”为一个子串,因而
使用了strstr函数进行处理。
另外此处还可以使用for循环 + strncmp函数进行分隔操作,代码如下:
int len = strlen(src);
int j = 0, k = 0;
for( int i=0; i<len; i++ )
{
	if( 0 == strncmp( src, "->", 2 ) )
	{
		strcpy( dst2, src+i );
	}
	else
	{
		*(dst1+j) = *(src+i);
	}
}
* Author:						Sky	
* Date:							2014/08/01
* Functiuon:					splitStr       
* Description:					对源字符串进行拆分操作        
* Access Level:					N
* Input:						src ---- 源字符串 (ab->abcd)				
* Output:						dst1 --- 拆分子串1(ab)
								dst2 --- 拆分子串2(abcd)  
* Return:						NULL     
**************************************************************************************/
void splitStr( char *src, char *dst1, char *dst2 )
{
	int i = 0;
	char *pos = NULL;

	pos = strstr( src, "->" );							//	“->”在字符串中的位置
	strncpy( dst1, src, pos-src);
	strcpy( dst2, pos+2);
}

/**************************************************************************************
* Author:						Sky
* Date:							2014/08/01	
* Functiuon:					strReplace         
* Description:					字符串替换函数,将源字符串src中的子串str1替换成子串str2        
* Access Level:					N	
* Input:						src --------- 源字符串
								str1 -------- 被替换子串
								str2 -------- 替换后的子串
								m ----------- 替换组数
* Output:						dst --------- 目的字符串(替换子串后的源字符串)     
* Return:						0/-1  成功/失败       
**************************************************************************************/
int strReplace( char *src, char *dst, char **str1, char **str2, const int m )
{
	int i = 0, j = 0;
	int k = 0;																//	目的串当前指针位置
	int len = 0, sublen1 = 0, sublen2 = 0;

	if( NULL == src )
		return -1;

	for( i=0; i<m; i++ )													//	外层循环控制替换组数也即替换轮数
	{
		len = strlen( src );
		for( j=0; j<len; j++ )												//	内层循环控制当前轮次字符串的替换
		{
			sublen1 = strlen( str1[i] );
			if( 0 == strncmp( src+j, str1[i], sublen1 ) )					//	如果当前匹配
			{
				sublen2 = strlen( str2[i] );
				strncpy( dst+k, str2[i], sublen2 );							//	替换源字符串中的子串
				k += sublen2;
				j += sublen1-1;
			}
			else															//	否则
			{
				*(dst+k) = *(src+j);
				k++;
			}
		}
		*(dst+k) = '\0';

		k = 0;																//	一轮替换完成,为新一轮替换复位
		strcpy( src, dst );
	}

	return 0;
}

运行结果图:


顺便说一说圈复杂度,面试的时候面试官问头圈复杂度是个什么东东?我没答上来,回来我查了一下,下面是引用CSDN的一篇博文:原地址:http://blog.csdn.net/horkychen/article/details/6996847,大家也可以再维基百科中直接搜索关键字“循环复杂度”

圈复杂度用来评价代码复杂度,以函数为单位,数值越大表示代码的逻辑分支越多,理解起来也更复杂。圈复杂度可以成为编码及重构的重要参考指标,以指导撰写可读性高的代码。有关圈复杂度的定义,可以自行搜索。《代码大全》有如下的定义:

计算子程序中决策点数量的技术 (代码大全2,19章P458)

1.1数,一直往下通程序。

2.一旦遇到以下关字,或者其同类的词,就加1:

  if, while, repeat, for, and, or

3. 给case(switch)语句中的每一种情况都加1.


作者也给了处理复杂度度量结果的建议:

0-5:  子程序可能还不错

6-20: 得想办法简化子程序了

10+  把子程序的某一部分拆分成另一个子程序并调用它。

这些数字和策略都不是绝对的,正如作者所言至少应当视其为警示。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值