http://www.aachin.info/tech/%E5%89%91%E6%8C%87offer%E9%9D%A2%E8%AF%95%E9%A2%98%E6%80%BB%E7%BB%93%EF%BC%881%EF%BC%89/
面试题3:查找排序二维数组
面试题4:替换空格为%20
扩展1-复制排序数组B至尾部有足够空余空间的排序数组A。 (我记得我最近一次感叹逆序思路的时候就是这道题,替换空格也在CC上有)
面试题5:从尾到头打印链表
看到题的时候还是能想到用栈的。 不过书中说看到栈要联想到递归,这句话很有道理。
虽然递归显然没有用栈的空间效率高,还有栈溢出的危险什么的,但是不失为一种比较奇特的思路,而且代码看上去很高级。
面试题6:通过中序遍历和前序遍历的序列重建二叉树
这道题和序列化树那道题还蛮像的,最近考过的话要多注意下。
面试题7:两个栈实现队列。或两个队列实现栈。
也是CC原题
不过这里的解决方案涉及了关于泛型方面的知识。如果是要设计数据结构的话,可以多考虑利用泛型的。
还有一点是,我有点太拘泥原子操作了。 认定了pop()操作一定要从stack1开始检查。 其实检查stack2是不是非空,就可以省去每次把stack2中的东西倒回stack1的操作。
面试题8:旋转的排序数组的最小数字
虽然是二分查找的一个变体,但是变体也要稍微注意下各种异常处理。
还有递归时(或者还没开始递归时),头已经小于尾了,那就直接返回头。 因为毕竟不是查找。 而是找最小。
面试题9:费波纳茨数列
记得MIT那个算法视频讲分治的时候就是用的这个例子。
普通递归,(就是开始学递归的时候的例子,除了阶乘,就是这货了)。
然后普通迭代,这个就是两个指针然后累加而已。
然后第三种办法是用一个哈希表吧已经有的状态缓存起来,避免重复计算。 (hackerrank上那倒阶乘和组合的题我也这么用的,,可惜还是没达到他的要求,大数的阶乘真的很慢)。
迭代算是自底向上吧,递归自然是自顶向下了。 所以要是感觉自顶向下很浪费时间空间的话,,那估计转化成迭代差不多吧。 或者是用哈希表那个辅助空间。
对于青蛙跳台阶的那个应用还是蛮有思考余地的,主要是对问题的抽象。
面试题10:二进制中1的个数
右移一位和除以二的结果是一样的,但是位运算的效率要高很多。
位运算的边界条件为负数的时候。
跟2相关的运算可以考虑位与运算的思路。
把整数减去1和本身做位运算,是把整数最后边的1变成零。 传说是条很有用的结论。
========================================================================================
中间插一句:浮点数比较的时候最好不用==. 会有损失精度的问题。
再插一句,关于边界条件测试,整数要考虑位数问题,比如要用int啊,long啊,还是终极杀手BigInteger什么的。
========================================================================================
面试题11:数值的整数次方
其实我有考虑到把这个拆开成小部分,然后再合拢,有点分治的意思。
不过右移一位等于/2这个想法还是挺帅,还有边界啊,错误条件什么的。
计算题一定要考虑除以0的异常什么的。
面试题12:打印1到n位的最大数
碰到n的时候,要考虑大数问题。要是不能用BigInteger就得考虑自己实现个。
另外一种解法是用递归实现全排列。 想当年排列组合多容易的题,,好久没练习然后脱离那个环境倒是没那么灵活了。 我会说我当年真的学得差么然后高考还不是重点我也没太在乎么。
面试题13:O(1)时间删除链表节点
删除链表时要考虑传值还是传引用。 传值无论如何得遍历,O(1)只能靠hash表来存储。 如果是传引用的话,所有的问题都只是在能不能得到头一个节点,当前节点的内存空间是已知的。
面试题14:调整数组顺序使得奇数位于偶数前面
头尾换,很多题都有这种思路。
面试题15:链表中倒数第k个结点
主要是要注意容错
面试题16:反转链表
注意链表不是一成不变的链表,因为链表是可以灵活变换的所以要利用这个特性,只要在变换的时候保存好各种指针就好了。
如果觉得变成树好解决问题的话,比如一个结点想指向两遍,那就断开用三个指针吧,把临时状态保存好。
面试题17:合并两个排序的链表
在板书解决方案的时候可以考虑在函数开头部分留一些空白,万一要补特殊条件或者入口条件或者容错什么的,可以有地方书写,省得下面擦一大片。 思路考虑清楚后,还是尽量先写容错和特殊情况。
面试题18:判断B是不是A的子树
这个我对robust倒是还考虑了挺多,就是遇到树的时候稍微有点思路不是很清晰,还得多做做二叉树的题。
面试题19:二叉树的镜像
不算太难的吧,就是看到新概念不要慌就好,二叉树递归的还得多练。
面试题20:顺时针打印矩阵
不是所有的矩阵都是方阵(行列相等),在写测试用例的时候要考虑这个。
面试题21:包含min函数的栈
辅助栈 (主要是要考虑动态的情况,尤其是删除).不要吝啬辅助空间。
面试题22:栈的压入弹出序列
说实话刚看到这个题和例子的时候,没太明白题在说什么。 要是面试的时候碰到这种情况估计得死命沟通吧。
面试题23:
从上往下按层打印二叉树
其实就是BFS
面试题24:二叉搜索树的后序遍历序列
注意是二叉搜索树,凡是题目中有任何提示说是已排序的,肯定要利用排序的性质。 呵呵,第一次面试的教训还不够深刻么。,。
所以要用规律来结题啦,,而不是用普通的遍历什么的。
面试题25:二叉树中和为某一值的路径
这道题比CC上那道类似的题要简单,因为这个的路径指的是从根出发的路径,所以只要用栈迭代实现前序遍历就好了。CC上那个题属于动态规划了。
面试题26:复杂链表的复制
这个,呵呵,额,O(n^2)的方法是肯定不会用的啦,,
倒是想到辅助hash表了,不过第三种方法思路就比较高级了,一下子不好想到了。
遇到复杂的问题的时候,不要畏惧写多个函数。虽然算法问题比较苛求代码短,但是当事情比较复杂,分函数反倒可以理清思路,然后体现下设计和扩展什么的。
这个题虽然是复制链表,但是还是大胆的对原链表进行了改动什么的,所以有时候思考问题要大胆一点。
面试题27:二叉搜索树和双向链表
中序遍历。 有操作的时候不要只想先迭代,其实递归的代码更好写。
当然,链表必备,,注意头指针和尾指针。
这个题还有时间的话也可以练习一下。
面试题28:字符串的排列
这个题也是写过好几遍了,比较经典,可以再写一遍。主要是划分小问题的思路。 还有,error有时候不知道是返回还是抛异常的时候,可以再外面嵌套一个父函数,保证主函数的出口值没有异常。至于父函数怎么处理可以跟面试官讨论。
面试题29:数组中出现次数超过一半的数字
这两种O(n)的解法感觉都挺不错的。
面试题30:最小的k个数
用最大堆的解法应该挺熟悉了,复杂度是nlogk。(这种解法对于大数据来说有节省内存空间的优势。) java里最大堆的语法是
PriorityQueue<Integer> queue =newPriorityQueue<Integer>(10,Collections.reverseOrder());
但是用partition的解法,以及刚才那道题的partition解法可以练习一下。
面试题31:连续子序列的最大值
这就是那道动态规划曾经让我很伤心的经典例题。
面试题32:从1到n的整数中1出现的次数
十进制数字位数=logn
我的解法和这里说的想法稍微有点不一样,待验证。
面试题33:把数组排成最小的数
对于排序来说,识别出comparator怎么实现的是很重要的一条。这个题如果要证明这个思路的话,嗯。。
面试题34:丑数
遇到复杂的问题的时候,还是用数学归纳的思想来考虑思路比直接想总结规律要容易些。
面试题35:第一个只出现一次的字符
常规的ASCII hash题了。
面试题36:数组中的逆序对
稍微有点思路,不是太具体。当然O(n^2)的解法就不值一提了。有点归并的意思。所以把快排和归并的代码再写写。 快排注意多变通partition那部分。
面试题37:两个链表的第一个公共节点
这个辅助空间的解法用的是两个栈,然后从结尾同步比较。 其实我觉得可以用个辅助hash表,先把第一条装进hash表里面,然后再依次看第二个节点里面在hash里面有没有值。判断的时间是O(1),总时间还是O(m+n);
不过把链表的长度截成一样的,再同步比较,然后不用辅助空间的思路确实挺好的。
面试题38:数字在排序数组中出现的次数
利用二分查找就要好好用,别把二分也用成了O(n)。
面试题39:二叉树的深度
虽然是道比较简单地题,但是关于树的都还可以再多写写。
PLUS:后序遍历判断是否平衡。 记得平衡树还有好些代码的,可以回去翻翻以前写的。适当的时候记得自底向上。
面试题40:数组中只出现了一次的两个数字
这个:任何数字异或自己都为0. <- 坑姐啊,你觉得就算姐姐知道这个结论能一下想到么。 当然现在可能是多一条思路了
异或这个思路也就罢了。 根据为1的位数来把数组分成两个小数组,嗯,多学着点。
还有就是这个题结论是要两个数字,但是思路却先从一个数字的例子开始,划分问题就是成功的一半么。
面试题41:和为s的两个数 VS 和为s的连续数列
如果思路是假设数字为正数的话一定要说出来和面试官讨论 。 不然还是假设有正有负吧
连续数列那个优化终止条件还是蛮重要的,时候不用遍历完全就可以终止了。
面试题42:翻转单词顺序 VS 左旋转字符串
关于两次翻转字符串的一些思路。
面试题43: n个骰子点数 (我才知道搜狗输入骰子是念做tou zi)
面试题44:扑克牌的顺子
主要是不要忽略个各种建模的可能情况。 还有这个虽然用bucket sort比quicksort要快,但是因为n比较小,所以其实也没太大区别。
面试题45:圆圈中最后剩下的数字
先总结数学公式再做题好帅的说。
面试题46:求1到n的和,不能用加减乘除,循环,if等
面试题47: 不用加减乘除做加法
面试题48:不能被继承的类
面试题49: 字符串转成整数
与整数相关的要考虑:1:空;2:符号;3. 是否浮点:4.整数位是否溢出; 5.非法输入
面试题50:树中两个节点最低公共祖先
这个也做过,不过是树的再做一遍。 假设条件不同,解决方案也不一样。