1.模拟实现C库的atoi和itoa。
2.给一个超过100G的log file, log中存着IP地址, 设计算法找到出现次数最多的100个IP地址?
1.题考察面试者的思维方式:完整性和鲁棒性
先想好测试用例,沟通好错误处理,才能满意的做完。
错误需要考虑的情况有:
1.当字符串为空时返回0,0字符串返回值也是0,但是两者的含义不同,我们应该做到区分,怎么区分? 定义全局变量,设置有效无效
2.“+123”“-565”,
3.数值溢出
4.字符串为NULL
5.穿入非法字符,怎么解决?
6.“+”“-” (+ - 号后面没有跟数字)
enum Status{kValid=0,kInvalid};
int g_nstatus = kValid;
long long strToIntCore(const char* digit,bool minus)
{
long long num = 0;
while (*digit)
{
if (*digit >= '0'&*digit <= '9')
{
int flag = minus ? -1 : 1;
num = num * 10 + flag*(*digit - '0');
if (!minus&&num > 0x7FFFFFFF || minus&&num < 0x80000000)
{
num = 0;
break;
}
}
else
{
break;
}
digit++;
}
if (*digit == '\0')
{
g_nstatus = kValid;
}
return num;
}
int myatoi(const char* str)
{
g_nstatus = kInvalid; //(初始化为无效值)
long long num = 0;
if (str == NULL || *str != '\0')
{
bool minus=false;
if (*str == '+')
{
str++;
minus = false;
}
if (*str == '-')
{
str++;
minus = true;
}
if (!*str != '\0')
{
num = strToIntCore(str,minus);
}
}
return (int)num;
}
/
char* myitoa(int num,char* str,int radix)
{
char index[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
unsigned int unum = 0;
int i = 0;
if (radix == 10 && *str == '-')
{
str[i++] = '-';
}
unum = (unsigned)num;
do
{
str[i++] = index[unum % radix];
unum = unum / radix;
} while (unum);
str[i] = '\0';//字符串\0结尾
int k = 0;
//字符串翻转
if (str[0] == '-')
{
k = 1;
}
i = i - 1;
for (k; k <=i;)//基数个元素会相聚到一个元素上, 偶数个元素会错开位置
{
char temp = str[i];
str[i] = str[k];
str[k] = temp;
k++;
i--;
}
return str;
}
2.给一个超过100G的log file, log中存着IP地址, 设计算法找到出现次数最多的100个IP地址?
一般来讲求topK 问题,建堆求topK来解决大数据问题非常有效。
此处来进行求解出现次数最多的IP地址,
首先看到100G的日志文件,我们的第一反应肯定是太大了,根本加载不到内存,更别说设计算法了,那么怎么办呢?既然装不下,我们是不是可以将其切分开来,一小部分一小部分轮流进入内存呢,答案当然是肯定的。
在这里要记住一点:但凡是大数据的问题,都可通过切分来解决它。
粗略算一下:如果我们将其分成1000个小文件,每个文件大概就是500M左右的样子,现在计算机肯定轻轻 松松就能装下。
那么,问题又来了,怎样才能保证相同的IP被分到同一个文件中呢?
这里我想到的是哈希切分,使用相同的散列函数(如 BKDRHash)将所有IP地址转换为一个整数key,再利用 index=key%1000就可将相同IP分到同一个文件。
依次将这1000个文件读入内存,出现次数最多的IP进行统计。
最后,在1000个出现次数最多的IP中找出最大的出现次数即为所求。
用到的散列函数:
与上题条件相同,如何找到TOP K的IP?
答:
这倒题说白了就是找前K个出现次数最多的IP,即降序排列IP出现的次数。
与上题类似,我们用哈希切分对分割的第一个个小文件中出现最多的前K个IP建小堆,
然后读入第二个文件,将其出现次数最多的前K个IP与 堆中数据进行对比,
如果包含大于堆中的IP出现次数,则更新小堆,替换原堆中次数的出现少的数据
再读入第三个文件,以此类推……
直到1000个文件全部读完,堆中出现的K个IP即是出现 次数最多的前K个IP地址。