这个网址是我后来发现的别人很好的总结,感谢
https://blog.csdn.net/u012505432/article/details/52071537
http://blog.csdn.net/u011462357/article/details/79278482(同剑指面试题3)
http://blog.csdn.net/u011462357/article/details/78593652(类似剑指面试题4 替换空格)
排序和查找是面试中的重点,应随时,完整地能写出 二分查找,归并排序,快速排序的代码
栈比循环形式简单,但效率不如循环高
要能比较冒泡排序,快速排序,归并排序的优劣,空间复杂度,平均时间复杂度和最差时间复杂度
查找不外乎顺序查找,二分查找,哈希表查找和二叉排序树查找。
二分查找要做到信手拈来面试题8寻找一个旋转数组里的最小数字 链接:http://blog.csdn.net/u011462357/article/details/78884084
递归的实现要比循环的实现简单的多,如果面试官没有明确要求,应该尽量使用递归实现。
递归优点:简洁
递归缺点:1。递归由于是函数调用自身,而函数调用是有时间和空间消耗的:每一次函数调用,都需要在内存栈中分配空间以保存参数、返回地址及临时变量,而且往栈里压入数据和弹出数据都需要时间。所以递归实现的效率不如循环。
2。递归中有可能很多计算都是重复的,从而对性能带来很大的负面影响。递归的本质是把一个问题分解成两个或多个小问题。如果多个小问题存在相互重叠的部分,那么就存在重复的计算。
3。除了效率之外,可能引起更严重的问题:调用栈溢出。前面分析中提到需要为每一次调用在内存栈中分配空间,而每个进程的栈容量是有限的。当递归调用的层级太多时,就会超出栈的容量,从而导致调用栈溢出。
斐波那契数列的变形:青蛙跳台阶,一次可以跳1级或者2级,问跳上n级台阶有几种方法。解法:http://blog.csdn.net/u011462357/article/details/79252607
斐波那契数列问题有O(logn)的解法,但不是面试官想考察的重点。
位运算只分5种:
位操作 | python表达 |
---|---|
与 | & |
或 | “ |
异或 | ^ |
左移 | << |
右移 | “>>” |
可参考 https://www.jianshu.com/p/3a31065a8e58
注意!!!http://www.cnblogs.com/zhengyun_ustc/archive/2009/10/14/shifting.html
python中左移操作是无限位数的,详见上面链接。
左移运算符m《《 n表示把m左移n位。左移n位的时候,最左边的n位将被丢弃,同时在最右边补上n个0。
右移运算符m>>n表示把m右移n位。右移n位的时候,最右边的n位将被丢弃。如果数字是无符号数值,则用0填补左边n位。如果数字是一个有符号数值,则用数字的符号位填补最左边的n位。即:如果数字原先 是正数 在右移之后最左边补n个0;如果数字原先是负数 在右移之后最左边补n个1。
题目:把一个十进制数转换成二进制数,数里面1的个数
错误解法:
如果把负数0x80000000右移一位,并不是简单地把第1位的1移到第二位变成0x40000000,而是0xC0000000,对应11000000000000000000000000000000,所以如果一直右移下去最后会造成FFFFFFFF对应11111111111111111111111111111111陷入死循环。
补充知识点:
先补充一个知识点:计算机在做减法运算时,实际上内部是在做加法运算的。
右移后空出来的高位数值,有0和1两种形式,要想区分什么时候补0什么时候补1,只要掌握了用二进制数表示负数的方法就可以了。
二进制数中表示负数值时,一般会把最高位作为符号来使用,因此我们把这个最高位成为符号位。符号位为0表示正数,1表示负数。那么-1用8位二进制数怎么表示呢,很多人会认为是10000001,其实这是错的,二进制表示为11111111。计算机是用“二进制的补数”来表示负数的。补数就是用整数来表示负数,过程就是:取反+1。所谓取反,就是将各数位的0反转成1,1取反为0。大家现在就可以试试-1的8进制表示形式了。详情参见http://www.cnblogs.com/Helius/p/7142535.html
为什么使用补数后就能正确地表示负数了呢?大家可以再详细的看看上图,有一个位溢出去了,而溢出的那一位数计算机是不进行处理的。
有一个法则大家必须牢记:”将二进制数的值取反后加1的结果,和原来的值相加,结果为0”这个法则。
总之,要想结果为0,就必须通过补数来实现。当然,结果不为0的运算同样可以通过使用补数来得到正确的结果,不过,有一点需要注意,当运算结果为负数时,计算结果的值也是以补数的形式来表示的。
3-5的运算:
3:00000011
-5:11111011
00000011+11111011=11111110,最高位变成了1。这就代表结果为一个负数。那11111110表示的负数是多少呢?负负得正大家都知道,所以通过求解补数的补数,就可知道该值的绝对值。所以11111110,取反后加1后为00000010,十进制就是2。所以结果就是-2。
Q:想理解为什么左移就直接移不用考虑正负,正数明白,负数左移也不用考虑首位符号位,可以见如下例子:http://blog.csdn.net/yusliao/article/details/39152671
例如 4 <<2 就是16,二进制就是 00000100 <<00010000
-4<<2 就是-16 二进制就是 11111100 <<11110000
Leetcode191 Number of 1 bits 详解: http://blog.csdn.net/u011462357/article/details/79336685
规范的代码应具备:,合理的命名
清晰的书写:在面试过程中减慢写字的速度,把每个字母清晰地写出来是很有必要
清晰的布局:对齐、括号匹配、缩进
合理的命名:写代码时候应用完整的英文单词组合命名变量和函数,以便面试官一眼能读懂代码的意图。
面试官会关注思考的是否周全:是否完成了基本功能,输入边界值是否得到正确的输出,对不合规范的输入是否做了合理的错误处理
功能测试、边界测试、负面测试(错误的例子)
第一种:函数用返回值告知调用者是否出错。比如很多Windows的API就是这个类型(返回值0表示成果),不直观
第二种:当发生错误时设置一个全局变量,此时我们可以在返回值中传递计算结果了。这种方法比第一种方法更加方便(直观)。缺点是调用者很容易忘记检查全局变量,因此在调用出错的时候忘记做响应的错误处理,从而留下安全隐患。
第三种:抛出异常,C#有,C没有。优点:可以为不同类型的错误定义不同类型的异常,逻辑清晰;缺点:当抛出异常时,程序的执行会打乱正常顺序,对程序的性能有很大影响。
面试的时候采用哪种错误处理方式要看面试官的要求
要求实现数的乘方
面试小提示!非常重要!
由于计算机表示小数(包括float型和double型)都有误差,我们不能直接用等号(==)判断两个数是否相等,如果两个小数的差的绝对值很小,比如小于0.0000001,就可以认为它们相等
Leetcode50:http://blog.csdn.net/u011462357/article/details/79339875
书中的C++解法涉及到一个问题,为什么要在删除一个节点后还要把该节点赋为NULL。个人认为这是一种鲁棒性的体现,参见:https://www.2cto.com/kf/201510/447386.html。
重点:delete是释放指针指向的内存,而并不是指针本身所占有的内存。
Leetcode 237. Delete Node in a Linked List(和书上的例题很像,但没给头节点,也确定不是尾节点)
Write a function to delete a node (except the tail) in a singly linked list, given only access to that node.
Supposed the linked list is 1 -> 2 -> 3 -> 4 and you are given the third node with value 3, the linked list should become 1 -> 2 -> 4 after calling your function.
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def deleteNode(self, node):
"""
:type node: ListNode
:rtype: void Do not return anything, modify node in-place instead.
"""
node.val = node.next.val
node.next = node.next.next
时间复杂度:O(1)
思路重点:
注意:上述代码不完美,因为它基于假设:要删除的节点的确在链表中,我们需要O(n)的时间才能判断链表中是否包含某一节点。受到O(1)时间的限制,我们不得不把确保节点在链表中的责任推给了函数的调用者。面试时可以和面试官讨论这个假设,面试官会觉得我们考虑问题非常全面。(这段是书中说的)
详解参见我的链表专题:
http://blog.csdn.net/u011462357/article/details/79379267
详解参见我的链表专题:
http://blog.csdn.net/u011462357/article/details/79379267
详解参见我的树专题:http://blog.csdn.net/u011462357/article/details/79389115
本Markdown编辑器使用StackEdit修改而来,用它写博客,将会带来全新的体验哦:
Ctrl + B
Ctrl + I
Ctrl + Q
Ctrl + L
Ctrl + K
Ctrl + G
Ctrl + H
Ctrl + O
Ctrl + U
Ctrl + R
Ctrl + Z
Ctrl + Y
Markdown 是一种轻量级标记语言,它允许人们使用易读易写的纯文本格式编写文档,然后转换成格式丰富的HTML页面。 —— [ 维基百科 ]
使用简单的符号标识不同的标题,将某些文字标记为粗体或者斜体,创建一个链接等,详细语法参考帮助?。
本编辑器支持 Markdown Extra , 扩展了很多好用的功能。具体请参考Github.
Markdown Extra 表格语法:
项目 | 价格 |
---|---|
Computer | $1600 |
Phone | $12 |
Pipe | $1 |
可以使用冒号来定义对齐方式:
项目 | 价格 | 数量 |
---|---|---|
Computer | 1600 元 | 5 |
Phone | 12 元 | 12 |
Pipe | 1 元 | 234 |
定义 D
定义D内容
代码块语法遵循标准markdown代码,例如:
@requires_authorization
def somefunc(param1='', param2=0):
'''A docstring'''
if param1 > param2: # interesting
print 'Greater'
return (param2 - param1 + 1) or None
class SomeClass:
pass
>>> message = '''interpreter
... prompt'''
生成一个脚注1.
用 [TOC]
来生成目录:
使用MathJax渲染LaTex 数学公式,详见math.stackexchange.com.
更多LaTex语法请参考 这儿.
可以渲染序列图:
或者流程图:
即使用户在没有网络的情况下,也可以通过本编辑器离线写博客(直接在曾经使用过的浏览器中输入write.blog.csdn.net/mdeditor即可。Markdown编辑器使用浏览器离线存储将内容保存在本地。
用户写博客的过程中,内容实时保存在浏览器缓存中,在用户关闭浏览器或者其它异常情况下,内容不会丢失。用户再次打开浏览器时,会显示上次用户正在编辑的没有发表的内容。
博客发表后,本地缓存将被删除。
用户可以选择 把正在写的博客保存到服务器草稿箱,即使换浏览器或者清除缓存,内容也不会丢失。
注意:虽然浏览器存储大部分时候都比较可靠,但为了您的数据安全,在联网后,请务必及时发表或者保存到服务器草稿箱。