百度、谷歌、微软、MTK经典面试题
- 格式:doc
- 大小:647.00 KB
- 文档页数:54
1. 有一个整数数组,请求出两两之差绝对值最小的值。
记住,只要得出最小值即可,不需要求出是哪两个数。
(Microsoft)方法1:两两作差求绝对值,并取最小,O( n2 )。
方法2:排序,相邻两点作差求绝对值,并取最小,O( nlgn ).方法3:有没有O( n )的解法?网上有如下解法:设数组A = { a1, a2, … , an }, 求s = min( |ai - aj| ), 其中1<= i, j <=n.设B = { b1, b2, … , bn-1 }, 且bi = ai – ai+1即:b1 = a1 – a2, b2 = a2 – a3, b3 = a3 –a4, …于是有如下规律:例如:a3 – a5 = ( a3 – a4 ) + ( a4 – a5 ) =b3 + b4a1 –a6 = b1 + b2 + … + b5即:ai –aj = bi + … + bj-1则数组A中任意两个数的差,都可以用数组B中一个字段的和表示。
则原问题可以转换为:在数组B中,求连续的某一段,使其和的绝对值最小。
(只求最小值,不需要知道具体是哪些数)例如 B = { 1, -2, 3, -1, -9, 7, -5, 6 };则绝对值最小值为0,具体是{ -2, 3, -1 } 或{3, -1, -9, 7}网上的解法,一般到这里就没下文了。
只是简单的提了一下,类似于最大子序列的和。
具体怎么做,还要自己想想。
最大子序列和利用DP,可O( n )求解。
这题咋做?纠结。
2. 写一个函数,检查字符是否是整数,如果是,返回其整数值。
(或者:怎样只用4行代码编写出一个从字符串到长整形的函数?)据说此题是,Microsoft的大牛只有了4行代码就给出了答案。
可惜,不知道是怎么写的。
自己试着写写,当然可能会不至4行。
单纯追求行数,也没什么意义,如果你愿意可以把所有的程序都写成一行。
注意:1. 处理前导空格2. 处理正负号3. 处理进制(16进制、8进制、10进制)4. 非法字符(0---9, a---f, A---F)5. 注意整数的范围,不能溢出view plaincopy to clipboardprint?1. bool StrToInt( char *pc, long &value )2. {3. //去掉前导空格4. while( ( *pc==' ' || *pc=='\t' ) && *pc != '\0' ) pc++;5. if( *pc == '\0' ) return false;6.7. //处理正负号8. int sign = 1;9. if( *pc == '+' || *pc == '-' )10. {11. if( *(pc+1) =='\0' ) return false;12. if( *pc == '-' ) sign = -1;13. pc++;14. }15.16. //处理数值17. long tmp = 0;18. while( *pc != '\0' )19. {20. tmp *= 10;21. //++优先级比*高22. if( *pc < '0' && *pc > '9' ) return false;23. tmp += ( *pc++ - '0' );24. }25. value = tmp * sign;26. return true;}3. 给出一个函数来输出一个字符串的所有排列方法1:一个简单的DFS。
从后往前不断交互。
N个字母求全排列,O( n! )。
具体实现,看代码吧。
方法2:如果不会写递归,也可以利用STL。
STL里有一个next_permutation函数。
利用这个函数可以返回大于原字符串的下一个字典序列。
当字符串为最大字典序列时,函数返回false。
这样只要先对原字符串排序,然后不断调用next_permuation即可。
view plaincopy to clipboardprint?1. inline void Exchange( char *px, char *py )2. {3. char tmp = *px;4. *px = *py;5. *py = tmp;6. }7.8. void PrintStrPermut( char *pstr, char *pbegin )9. {10. //处理空字符串11. if( pstr == NULL || pbegin == NULL ) return;12.13. //递归终止条件14. if( *pbegin == '\0' )15. cout << pstr << endl;16. else17. {18. for( char *p=pbegin; *p!='\0'; p++ )19. {20. Exchange( p, pbegin );21. PrintStrPermut( pstr, pbegin+1 );22. Exchange( p, pbegin );23. }24. }25. }26.27. void PrintStrPermut2( char *pstr )28. {29. char *p = pstr;30. while( *p != '\0' ) p++;31.32. sort( pstr, p );33. cout << pstr << endl;34. while( next_permutation( pstr, p ) )35. {36. cout << pstr << endl;37. }}4.请编写实现malloc()内存分配函数功能一样的代码这题比较难,要是不懂点OS的内存管理,根本就无从下手。
我们知道调用malloc()后,OS就要想方设法为我们返回一块空闲空间。
这就涉及到OS的内存管理。
OS的内存管理可以这样考虑:假设整块内存有128K初始状态,128K都是空闲第一次请求,申请了16k,空闲112K第二次请求,申请了32K,空闲80K第三次请求,申请了8K,空闲72K第二次请求申请的32K被释放,空闲108K第四次请求,申请了24K,空闲84K…从上面的例子可以看出,一整块连续的空闲内存块,经过一段时间的使用,会被无情的划分为许多小块。
这些小块大小不等,并且有的空闲、有的被占用。
当调用malloc时,OS就沿内存扫描,找到一块够大的空闲块,从中划分出要使用的部分,将这部分标记为己分配,并返回这部分的首地址。
如果,空闲的块都是些小的碎片,那就悲具了(当然,OS可以把将相邻的空闲块合并,再尝试)。
现在,模拟一下malloc的过程:为了便于管理,首先定义内存控制块mcb。
这个mcb记录两个信息:块是否空闲、块的大小。
即,每个分配出去的块,其实都带有一个mcb,只不过这个mcb位于块的最前端,返回该用户的指针刚好指向mcb之后,所以对用户是不可见的。
现在,就可以处理free了。
Free只要把已分配的内存块重新标记为空闲即可,这里当然要用到该快的mcb了。
Malloc简单来说,就是维护几个指针,根据分配请求修改指针位置。
对于要分配的块,将标记置位己分配,并返回这部分的首地址。
参考/blog/static/32574109200881445518891/,这里讲的很清楚,还附有代码,我就不狗尾续貂了。
5. 字符串A的后几个字节和字符串B的前几个字节重叠。
这题似乎没什么玄机,就是个简单的字符串处理。
使用strlen和memcpy可以完成,见代码。
view plaincopy to clipboardprint?1. bool StrOverlap( char *strA, char *strB, int cnt, char *strC )2. {3. int sizeA = (int)strlen( strA );4. int sizeB = (int)strlen( strB );5.6. if( cnt > sizeA || cnt > sizeB ) return false;7.8. memcpy( strC, strA, sizeA-cnt );9. memcpy( strC+sizeA-cnt, strB+cnt, sizeB-cnt );10.11. //注意添加结束标记12. strC[sizeA+sizeB-2*cnt] = '\0';13. return true;}6. 怎样编写一个程序,把一个有序整数数组放到二叉树中?由数组建立排序二叉树。
因为数组已排序,所以可以进行类似排序二叉树上的查找。
感觉有点类似先序遍历,每次先处理根节点,然后分别是左子树、右子树。
具体做法是:1.整个数组对应一个二叉树,则中间元素对应二叉树的根节点2.中间元素左边的部分对应左子树、右边的部分对应右子树3.对左右两部分再继续递归调用。
view plaincopy to clipboardprint?1. struct BiTreeNode2. {3. int data;4. BiTreeNode* leftChild;5. BiTreeNode* rightChild;6.7. //构造函数,初始化成员变量8. BiTreeNode(): data(0), leftChild(0), rightChild(0){};9. };10.11. void ArrayToTree( int *pi, int left, int right, BiTreeNode *&root )12. {13. if( left <= right )14. {15. int mid = ( left + right ) / 2;16. root = new BiTreeNode;17. root->data = pi[mid];18.19. ArrayToTree( pi, left, mid-1, root->leftChild);20. ArrayToTree( pi, mid+1, right, root->rightChild );21. }}7. 怎样从顶部开始逐层打印二叉树结点数据?请编程。