2018C语言及数据结构面试题

1、如何判断合法的IP地址,尽可能考虑各种情况 (腾讯面试题)
规则有:
正确的“192.168.3.44”
(1)由数字字符和点号组成
(2)第一个数字字符不能是0
(3)数字字符和点号的存放
(4)每个数字的范围是0~255

代码如下:
static int CountPoint(const char *str)
{
int count = 0;
while(*str != ‘\0’)
{
if(*str == ‘.’)
count++;
str++;
}
return count;
}

bool TestIP(const char * str)
{
assert(str != NULL);
if(str == NULL)
{
return false;
}

if(CountPoint(str) != 3)
{
	return false;
}

if(str[0] == '0')
{
	return false;
}

int tmp = 0;
int countnum = 0;//标记数字的个数
while(*str != '\0')
{
    if(isdigit(*str))
	{
		tmp =tmp*10+ *str-'0';
	}
	else if(*str != '.' ||tmp>255)
	{
		return false;
	}

	else
	{
		tmp = 0;
	}
	str++;
}
if(tmp > 255)//处理尾部数据
{
	return false;
}

return true;

}

int main()
{
	char arr[]="192.168.2.25";
	char brr[]="169.3.2";
	char crr[]="123.4.44.";

if(TestIP(arr))
{
	printf("此IP地址合法\n");
}
else
{
	printf("不合法\n");
}

if(TestIP(brr))
{
	printf("此IP地址合法\n");
}
else
{
	printf("不合法\n");
}

if(TestIP(crr))
{
	printf("此IP地址合法\n");
}
else
{
	printf("不合法\n");
}

return 0;
}

2、算法题:求一个有序数组中两个值相加为k的数字,返回这两个数字的下标。(腾讯面试题)

//算法分析:有序的数组(假设非降序),采取双向遍历,一个从前往后,一个从后往前,当前数字相加如果相等则返回,如果小于k则前面的继续往后,如果大于k则后面的继续往前
//代码如下:

bool FindNum(int *arr,int len,int k)//时间复杂度O(n)
{
	assert(arr != NULL);
	if(arr == NULL)
	{
		return false;
	}
	int low = 0;
	int high = len-1;
while(low <= high)
{
	if(arr[low] + arr[high] == k)
	{
		printf("%3d + %3d == %3d\n",arr[low],arr[high],k);
		low++;
	}
	else if(arr[low] + arr[high] < k)
	{
		low++;
	}
	else
	{
		high --;
	}
}
return true;
}

/2.2,如果是无序的数组呢?
//算法分析:1.先排序,在利用上面(2.1)的算法
3.用c语言判断操作系统是32位的还是64位
//分析:这个题目应该是判断当前平台是32位还是64位,最简洁的办法是判断指针的大小,如果4字节则为32位,8字节位64位,sizeof(int *);

//4.泛型冒泡(腾讯面试题)

typedef int (*PCmp)(void *vp1,void *vp2);//泛型比较

//泛型冒泡
void BubbleSort(void *arr,int len,int elemsize,PCmp cmp)
{
	void *tmp = malloc(elemsize);//交换数据的中间变量
	void *var1;//冒泡的第一个值的指针
	void *var2;//冒泡的第二个值的指针
for(int i=0;i<len-1;i++)
{
	for(int j=0;j+1<len-i;j++)
	{
		var1 = (char *)arr+j*elemsize;
		var2 = (char *)arr + (j+1)*elemsize;
		if(cmp(var1,var2) > 0)  //交换数据
		{
			memcpy(tmp,var1,elemsize);
			memcpy(var1,var2,elemsize);
			memcpy(var2,tmp,elemsize);
		}
	}
}
}

int Cmp_int(void *vp1,void *vp2)
{
	return *(int *)vp1 - *(int *)vp2;
}

int Cmp_str(void *vp1,void *vp2)
{
	return strcmp(*(char **)vp1,*(char **)vp2);
}

int main()
{
	int arr[] = {3,5,7,9,0,12,45,6,78,23,44,10};
	BubbleSort(arr,sizeof(arr)/sizeof(arr[0]),sizeof(int),Cmp_int);
char *brr[] = {"abc","aaa","bcd","xyz","ccccc","hhh"};
BubbleSort(brr,sizeof(brr)/sizeof(brr[0]),sizeof(char *),Cmp_str);

return 0;
}

//5.(腾讯面试题)
假设环境均为x86,32位机器,linux环境下1、以下代码执行后b的值是什么
int a = 0xabcdefff;
char b = (char)a;
b=?
解答:将宽的数据类型强转成窄类型时,保留低数据,则b的值为0xff即-1

//6.(腾讯面试题)
c语言编码,实现函数long htonl(long a),也就是将主机序转化为网络序
//解析:主机序也称为本地字节序,分为大端和小端.大端:低地址放大数据;小端:低地址放小数据.网络序统一为大端
//该算法主要需要测试主机序,如果是大端则不做任何的改变,如果是小端则逆序

bool IsLittle()//判断主机序是否为小端
{
	short a  = 0x0001;//小数据为0x01,高数据为0x00
	return *(char *)&a == 0x01; //低地址放小数据
}

long Htonl(long a)
{
	long b = 0;
if( !IsLittle() )//大端
{
	return a;
}

for(int i=0;i<sizeof(a);i++)//小端:0x12345678->0x78563412
{                                        //处理单位为字节,1字节8位
	b = (b<<8) | (a & 0xff);
	a >>= 8;      
}
	return b;
}
int main()
{
	printf("%x\n",Htonl(0x12345678));

	return 0;
}

//7、有一个集合由A-Z这26个字母组成,打印这个集合的所有子集,每个子集一行,写C代码实现,不能使用递归(腾讯面试题)
//解析:https://blog.csdn.net/K346K346/article/details/80436430
在这里插入图片描述
//str为A~Z的字母集合,n为需要处理的前n个字符集合,本题n为26,n是为了方便测试

void SubSet(int n)
{
	const char *str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	int maxnum = 1<<n;          //2^n
	for(int i=0;i<maxnum;i++)//处理0到2^n  -1之间的数字
	{
		for(int j=0;j<n;j++)//j表示二进制右数第几位
		{
			if( (i&(1<<j)) != 0)//表示当前位不为0,则需要打印相应的字母
			{
				printf("%c ",str[j]);
			}
		}
		printf("\n");
	}
}

int main()
{
	SubSet(3);
	//printf("-----------\n");
	//SubSet(26);//数据太大不好统计测试结果

	return 0;
}

//8、介于0到1000000之间的n个整数,请对他们进行排序,要求时间复杂度为O(n),写c代码实现(腾讯面试题)
//算法解析:定义一个长度为1000000的数组brr,全部初始化为0,从头到尾遍历这n个数字,出现哪个数字则将其作为下标对应的数组值加1(哈希函数为y=x),然后从到到尾遍历brr,数字是几则将下标打印几次

void Sort(int *arr,int n) //时间复杂度O(n),空间复杂度O(数据的取值范围)
{
	int i;
	for(i=0;i<n;i++)
	{
		if(arr[i]<0 || arr[i]>=1000000)
		{
			printf("数据不在范围内,错误\n");
			return ;
		}
	}
	int *brr = (int *)calloc(1000000,sizeof(int));//calloc将每个值设为0
	assert(brr != NULL);
	for(i=0;i<n;i++)
	{
		brr[arr[i]]++;//哈希函数y = x = arr[i]
	}

	i = 0; 
	for(int j=0;j<1000000;j++)
	{
		for(int k=0;k<brr[j];k++)
		{
			arr[i++] = j;
		}
	}
	free(brr);
}

int main()
{
	int arr[] = {5,8,0,9,12,34,56,7,8,89,13,44,76,88,98,69};
	Sort(arr,sizeof(arr)/sizeof(arr[0]));

	return 0;
}

9、将数字n转为指定进制下的数字字符串,2<=进制radix&&radix<=36
算法 ,每次取数字n的末尾,再丢弃末尾,然后在逆置字符串
代码如下:

void Myitoa(char *str,int n,int radix)
{
	if(radix <2 || radix >36)
	{
		return ;
	}

	int tmp;
	
	while(n != 0)
	{
		tmp = n%radix;
		if(tmp < 10)
		{
			*str = tmp +'0';
		}
		else
		{
			*str = (tmp-10) +'a';
		}
		n /= radix;
		str++;
	}

	*str = '\0';
}
void Reverse(char *str)
{
   	char *p;
	for(p=str;*p!='\0';p++) ;

	char t;
	p--;
	while(str < p)//str != p
	{
		t = *str;
		*str = *p;
		*p = t;
		str++;
		p--;
	}


 }
    /*
    int main()
    {
	char p[100];
	Myitoa(p,20,2);

	printf("%s\n",p);


	Myitoa(p,20,16);
	printf("%s\n",p);

	Myitoa(p,200,16);
	printf("%s\n",p);

	Myitoa(p,12345,10);
	printf("%s\n",p);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值