文章分类 -  Coding Practice - 剑指offer50题练习笔记

剑指offer-名企面试官精讲典型编程题 河海涛 著,电子工业出版社
面试题 50,二叉树两节点的最低公共祖先
摘要:这道题的探讨已被收入二叉树系列随笔,见二叉树系列 - 求两节点的最低公共祖先,例 剑指Offer 50 阅读全文

posted @ 2014-07-07 06:25 Felix Fang 阅读(134) 评论(0) 推荐(0)

面试题 49,atoi 字符串转化为整数的实现(考察edge case的典型题) [LeetCode]
摘要:面试题49是一道案例分析题,里面模拟了考官和应聘者的全部面试过程和考官心理活动。案例中的重头戏就是atoi 字符串转化为整数的实现。这道题因为边界情况比较多,所以很常见,我也曾经被考过,当时回答得并不理想。做这道题的关键是要事先和面试官多沟通,在各种边界处理上达成一致。再开始写代码。现在罗列出要考虑... 阅读全文

posted @ 2014-03-13 10:32 Felix Fang 阅读(323) 评论(0) 推荐(0)

面试题 48,不能被继承的类
摘要:C#的话,第一反应 sealed;Java的话第一反应 final;C++没这些关键字,毫无疑问,第一反应:把构造函数设为私有。当然,为了这个类本身依然能被实例化,我们需要提供另一个函数来构建实例。有点像单例模式,当然这里没有类是否已经存在的判断。代码:Class SealedClass{public: static SealedClass* CreateInstance(){ return new SealedClass() };private: SealedClass(); ~SealedClass();}书上代码:class SealedClass1{public: ... 阅读全文

posted @ 2014-03-11 10:58 Felix Fang 阅读(217) 评论(0) 推荐(0)

面试题 47(*),不用加减乘除做加法(位运算易想到,怎么用就是个技术活了)(附 不定义新变量前提下交换两数的方法)
摘要:用位运算是第一反应,a^b可以算出当前位的结果, a&b可以算出是否进位。但是接下来怎么办呢?我的方法是,每次从两个数取一位,然后计算,进位。直到两个数都没有位可取了(往左看都只有0),最后做一个进位。我的代码:#include int Sum(int a, int b){ int final... 阅读全文

posted @ 2014-03-11 10:09 Felix Fang 阅读(499) 评论(0) 推荐(0)

面试题 46(*),求1+2+..+n (巧妙使用函数指针和面向对象思想,amazing)
摘要:很苛刻的条件。我自己一开始想从等差数列公式n*(n+1)/2 入手,/2可以用 >>1表示,但是n*(n+1)怎么求真是伤透了脑筋。虽然可以用递归,但是递归也是有返回判断的,这里判断语句都被禁止了。看了答案才知道原来还可以这样玩。。。要学会灵活的运用面向对象和函数指针啊亲。解法一:利用 new 一个n元素的数组代替了循环的功能。如果不用公式,仅仅累加来做,那么最难的地方自然就是如何绕过循环了。解法一非常巧妙地利用了构造函数和static成员来解决这个问题。class Temp的static成员Sum用来保存累加结果,N用来自增,这样不论有多少instance,他们都共享一个stat 阅读全文

posted @ 2014-03-10 01:56 Felix Fang 阅读(436) 评论(0) 推荐(0)

面试题 45,圆圈中最后剩下的数字(学会用已有的stl,比如用List构建环链表)(数学的美丽)
摘要:方法一最直接的方法自然就是构建环链表模拟整个过程。时间复杂度是O(mn),空间复杂度是O(n)。我的代码:#include struct Node{ int value; Node* next;};int ReturnLastValue(int n, int m){ if(n value = 0; p -> next = NULL; Node* previous = NULL; int i = 0, j = 0; for(i = 1; i value = i; p -> next = NULL; previous -> ... 阅读全文

posted @ 2014-03-09 13:54 Felix Fang 阅读(180) 评论(0) 推荐(0)

面试题 44,扑克牌的顺子
摘要:首先需要把问题建模,我们忽略花色,用int数组来表示抽到五张牌的数字。王用0表示。我的思路比答案简洁些,答案中需要排序。实际上,在判断出没有相同数字后,只要用最大数字减去最小数字,看看差是否满足要求就知道是否连续了。如果有一个王,最大最小的差可以为3或者4。如果有两个王,最大和最小的差2,3,4都可以。没有王,就必须为4了。代码:#include bool IsContinuous(int* number, int length){ if(number == NULL) return false; if(length != 5) return false... 阅读全文

posted @ 2014-03-09 11:41 Felix Fang 阅读(252) 评论(0) 推荐(0)

面试题 43,n个骰子的点数
摘要:这道题要用递推的思想做。假设骰子是最常见的骰子,有6个面,1-6对于n个骰子,其和的可能性有n到6n这么多种情况。(1) 假设f(m) 表示骰子数目为n时,和为m的可能性的数量,当骰子数量从n变为n+1,由于组合更多,之前计算好的和为m的可能性的数量也会变化。考虑到新的骰子可以从1变到6,要想让所有骰子和依然为m,那么其余的骰子的和就需要从m-6变到m-1,也就是说对于 m double* CalcuSumRatio(int num, const int MaxValue){ if(num 0){ sum[i & 1][j] += sum[1 - ... 阅读全文

posted @ 2014-03-09 01:28 Felix Fang 阅读(328) 评论(0) 推荐(0)

Self introduction
该文被密码保护。

posted @ 2014-03-04 12:17 Felix Fang 阅读(4) 评论(0) 推荐(0)

面试题 42(*),翻转单词顺序,字符串的左旋转 (字符串操作类经典题目:两次Reverse字符串的妙用,可以做到不需要额外空间的情况下按要求变换顺序)
摘要:看了书里的提示才想到:两次翻转字符串。这是非常经典的题目,解法也非常经典。先把字符串整个逆序一遍,然后再将里面被空格分开的子字符串挨个逆序一遍,就得到要求的字符串了。自己实现的代码:#include #include void ReverseStr(char* str, char* end){ for(; str char* LeftRotateString(char* pStr, int n){ if(pStr != NULL) { int nLength = static_cast(strlen(pStr)); if(nLength > 0 &... 阅读全文

posted @ 2014-03-03 04:48 Felix Fang 阅读(279) 评论(0) 推荐(0)

面试题 41,和为s的两个数字,引申:和为s的连续正数序列,窗口思想(其实就是是双指针贪心)和中位数法 [LeetCode] Minimum Window Substring
摘要:O(n2)的方法自然可以解决。面试时可以先扔出来这个,然后再思考更好的解,让面试官知道你并不是不会,而是在思考更好的解。后来想出来了一个办法,像这种存在“数组”,“查找两个数”关键字的,一律试试头尾各定义两个指针往中间扫描的思路,大多数都会有一些收获。书中的解法和我思路一样:在序列首尾各定义指针p1... 阅读全文

posted @ 2014-03-03 00:44 Felix Fang 阅读(1810) 评论(1) 推荐(0)

面试题 40(*),数组中只出现一次的数字 (附带GNENERAL解法:所有数字出现a次,另两个数各出现b和c次)(数字XOR本身会成为0,学会利用这个特性)
摘要:想了20多分钟都没有良好的思路。看答案后,这可能是本书到现在为止最难的一题。先将问题简化:如果数组中只有一个数字只出现了一次,其余都出现两次,求唯一那个只出现一次的数字。出现两次的数字,我们肯定要用到什么方法让他们相互抵消掉。请不要忘掉XOR是最好的方法。因为0 XOR A = A,A XOR A ... 阅读全文

posted @ 2014-03-02 11:41 Felix Fang 阅读(225) 评论(0) 推荐(0)

面试题 39,二叉树的深度,以及判断二叉树是否是平衡二叉树 (比较经典的题目)
摘要:比较老的题目,最简单版本的代码如下:int CalcuDepth(TreeNode *root){ if(NULL == root) return 0; int leftDepth = CalcuDepth(root -> m_pLeft); int rightDepth = CalcuDepth(root -> m_pRight); return (leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1);}接着还有第二问:判断二叉树是否是平衡树,即所有节点左右子树高度差不超过1。先... 阅读全文

posted @ 2014-03-02 07:37 Felix Fang 阅读(243) 评论(0) 推荐(0)

面试题 38,数字在排序数组中出现的次数(注意时间复杂度中O的意思是最坏情况下的时间,分析时间复杂度要细心)
摘要:找这个数用二分,然后左右两边挨个数,统计出现次数。但是这种方法是O(n)而不是O(logn),因为O是最坏情况下时间,最坏情况下,如果数组中全是要找的数的话,统计时间是O(n)。。有木有一种题目在耍赖的感觉。。。改进方法是,找数用二分,数数也用二分。书中的方法是:二分找到数第一次出现的地方,再二分找到最后一次出现的地方,一减完事儿了。两种方法都是O(2logn)自己代码,白板写后编译无错,运行有一处错误:CountNumber函数的最后一行忘了添加"+1"。#include int FindNumIndex(int* list, int start, int end, in 阅读全文

posted @ 2014-03-02 07:07 Felix Fang 阅读(241) 评论(0) 推荐(0)

面试题 37,两个链表的第一个公共节点(附引申:环链表的环入口节点) (纪念第一次.txt 白板写代码 error free bug free)
摘要:想了五分钟没想出好的解法,最优解其实很简单,自己也已经摸到门口了,最后没想下去,蠢死了。。思路:首先,从公共节点开始,两条链表肯定已经合并了(这个已经想到了),定义两个指针变量两个链表,直到某一个指针到达末端(这个也想到了)。这样就计算出了两个链表的长度差,重新遍历,较长的链表上的指针提前出发,把长度差走掉,然后两个指针地址相等时就是第一个公共节点了。时间复杂度(M+N),无额外空间。自己代码,比书上要简洁一些,不需要计数,另定义指针p,和那个没走完的指针同步行走直到没走完的指针走到底了,p停下的位置就是该提前走掉的长度差。#include #include struct ListNode{ 阅读全文

posted @ 2014-03-02 02:12 Felix Fang 阅读(1025) 评论(0) 推荐(0)

面试题 36(*),数组中的逆序对(类似归并排序,不过归并时添加计数器记录逆序对的数量)
摘要:思路:如果用O(n^2)自然可以完成。我并没有想到比较好的思路。书中给出了类似归并排序的做法,在O(nlogn)时间内完成了计算。思路就是在递增归并排序的基础上,做了改动:每次在merge两个子序列时,统计a和b组成的逆序对,a来自前一个递增子序列,b来自后一个递增子序列。由于两个子序列都是递增的,这时候求a和b构成逆序对的数量就可以在O(n)内完成了。当a前进一步时,就把第二个子序列中b所在位置及之前所有遍历过的元素的数量添加到count中。count = 两个子序列内部的逆序对(用递归求出) + a和b所产生的逆序对个数自己实现的代码如下:#include int FindInverseP 阅读全文

posted @ 2014-02-05 12:00 Felix Fang 阅读(208) 评论(0) 推荐(0)

面试题 35,第一个只出现一次的字符(利用ASCII码表实现 基于单子符的哈希表)
摘要:使用哈希表来记录字符出现的次数是比较常见的思路。但是答案使用了ASCII值作为数组的下表,从而很简单地利用256长的数组实现了哈希表。字符- '\0'就是下标。实际上,可以直接使用字符作为数组的下表unsigned int HashTable[256]; HashTable['A'] = 1 是合法的,编译器会自动把 'A'转成ASCII码值,也就是说HashTable['A'] = 1 和HashTable['A'-'\0'] = 1 意思一样。先扫描一遍,记下每个字符出现的个数。再扫一遍,扫到第 阅读全文

posted @ 2014-01-27 12:15 Felix Fang 阅读(398) 评论(0) 推荐(0)

面试题 34(*),丑数(Ugly Number) (用的也是递推思想)
摘要:思路:由于丑数必然是等于一个较小的丑数与2,3或5相乘的结果。因此,假设我们已经拥有了从小到大排好队的丑数序列,当需要寻找新的丑数时,它必然是来自这个序列中的某一个数乘以2,3,5。我们可以将队列中每一个数字都乘上2,3,5,然后找一个大于当前队列最大值的最小丑数,放入队列。这样就可以用递归或者循环做了。这个思路可以进一步优化:我们真的需要每次都把队列中所有的数字都乘以2, 3, 5吗?假设我们找到的新丑数,是位于T1位置老丑数乘以2所得的结果,那么接着再找下一次丑数时,我们肯定不再需要考虑T1位置及T1位置往前的数字乘以2的结果,因为他们必然比当前队列的最后一个丑数小。所以,乘以2方面,T1 阅读全文

posted @ 2014-01-27 05:42 Felix Fang 阅读(425) 评论(0) 推荐(0)

面试题 33,把数组排成最小数(非常巧妙的重定义了比较函数,再基于这个比较函数排序)
摘要:我的思路:递归函数,函数将数组作为输入,函数中的逻辑是这样的:返回条件是数组中只有一个数了,就返回这个数。从最高为开始比较数组里的成员,返回最高位最小的,如果最高位一致,比较第二位,如果存在没有第二位的数,看是否其他数中有第二位比第一位小的,有的话,返回第二位最小的数,没有,返回那个没有第二位的数;如果所有数都有第二位,返回第二位最小的数;如果所有第二位而且都相同,比较第三位。比较函数其实也可以用递归做。找到的数会被移出数组,从后部拼接到组成的数中。将剩下的数组成的数组作为参数,递归。答案的思路异常巧妙!在上面的思路中,递归的核心部分就是如何比较,从而从数组中选出一个数返回。答案中给出了更加简 阅读全文

posted @ 2014-01-27 02:09 Felix Fang 阅读(128) 评论(0) 推荐(0)

面试题 32,从1到整数n中1出现的次数
摘要:我虽然想到要用统计去做,但是思路不够明晰,这里参考答案的思路,组织下。思路:以n=36789为例。我们把计算分为1-6789,和6790-36789两段。为什么这么做?因为6790-36789这一段中,低四位的每一位数字,都涵盖了从0到9的变化;这种变化,每经过10000就会出现一次。这个例子中,6790-16789,16790-26789,26790-36789,共出现3次。每次出现,低四位的每一位都是0-9都体验了一遍,因此1的个数为10^3。一共出现3次,所以6790-36789这一段中,低四位上的1 共出现 3*10^3次。那么6790-56789这一段中,最高位上出现了多少次1?因为 阅读全文

posted @ 2014-01-27 01:29 Felix Fang 阅读(226) 评论(0) 推荐(0)

导航