1找单身狗
一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。
编写一个函数找出这两个只出现一次的数字。
例如{1,2,3,4,5,1,2,3,4,6}找两条单身狗
这题最难的是咋分组?不知道各位听过按位异或没?就是两个二进制数进行异或,相同为0,相异为1。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void fingle_dog(int a2[], int sz)
{
int i = 0;
int ret = 0;
int dog1 = 0;
int dog2 = 0;
for (i = 0; i < sz; i++)
{
ret ^= a2[i];
}
//查找第几位是1
int pos = 0;
for (i = 0; i < 32; i++)
{
if (((ret >> i) & 1) == 1)
{
pos = i;
break;
}
}
for (i = 0; i < sz; i++)
{
if (((a2[i] >> pos) & 1) == 0)
{
dog1 ^= a2[i];
}
}
dog2 = ret ^ dog1;
printf("%d %d\n", dog1, dog2);
}
int main()
{
int a1[] = { 1,2,3,4,5,1,2,3,4,6 };
int sz = sizeof(a1) / sizeof(a1[0]);
fingle_dog(a1, sz);
return 0;
}
2.atoi函数模拟实现
atoi 功 能: 将字符串转换成整型数;atoi()会扫描参数nptr字符串,跳过前面的空格字符,直到遇上数字或正负号才开始做转换,而再遇到非数字或字符串时('\0')才结束转化,并将结果返回(返回转换后的整型数)。
我们模拟时会遇到以下几个问题:
1.空指针;
2,空白字符串;
3.字符串为空;
4.正负号问题;
5.字符不是数字字符;
只要出现除了4其他情况,atoi函数就不能将数字字符转化为sh数字,所以我们定义一个判断状态的枚举类型,只有两种情况,正常和异常,我们先定义它是异常的,因为正常的情况少,容易修改。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
#include<ctype.h>
#include<limits.h>
enum Status
{
VALID,
INVALID,
}status = INVALID;
//正常转化时是合法的VALID,其他情况都是非法,所以令它非法
int my_atoi(char* str)
{ //空指针
assert(str);
int flag = 1;
//字符串为空
if (str == '\0')
{
return 0;
}
//空白字符
while (isspace(*str))//isspace判断是否为空白字符
//空白字符是指在屏幕不会显示出来的字符
//(如空格,制表符tab,回车换行等)
{
str++;//直接跳过
}
//正负号
if (*str == '+')
{
flag = 1;
str++;
}
else if (*str == '-')
{
flag = -1;
str++;
}
long long n = 0;//整形可能存不下
while (*str)//字符串还没结束
{
if (isdigit(*str))//判断是不是数字字符,头文件<ctype.h>
{
n = n * 10 + flag * (*str - '0');
//是数字字符但是数值溢出
if ((n < INT_MIN) || (n > INT_MAX))
{
n = 0;
break;
}
}
else//不是数字字符了(a,b,c等)
{
n = 0;
break;
}
str++;
}
if (*str == '\0')
{
status = VALID;
}
return (int)n;
}
int main()
{
char ch[] = "12345";
int p = my_atoi(ch);
if (status == VALID)
{
printf("合法返回:%d", p);
}
else
{
printf("非法返回:%d", p);
}
}
注意n的类型是long long因为int的可能存储不下。
n = n * 10 + flag * (*str - '0');——要×flag因为这一步可以判断是正是负。