LeetCode基础题总结
1.HashMap中的containsKey是将key直接进行hash,从连续的存储单元中找到指定下标。
2.注意Integer整型的溢出,可以根据同号相加为异号判断溢出。
3.最长公共前缀——找到最短的String、将该String设置为前缀、遍历strs数组,若都有该前缀则返回,若没有则将前缀的lenth-1。
4.使用链表时最好创建有头结点的链表。
5.构建字符串使用StringBuilder,int转string使用String.valueOf。
6.动态规划使用递归的复杂度为2的n次方,因为有些计算会重复进行多次。可以考虑使用map对计算结果进行存储(填表),为了进一步优化空间复杂度,可以使用迭代的方式替换递归的方式。
7.比较大小用Math.max。
8.时间复杂度为对数形式时考虑使用了二分法。
9.若要交换两个输入数据,可以通过调用自身方法来实现。
10.在树的递归过程中,子树的判空尽量不要在操作父节点时通过root.left!=null判空,而应该直接在递归操作子树时通过root!=null判空。
11.使用List更加耗费时间,因此能用数组尽量用数组,可以在程序的最后,根据需要将数组转化成List返回。
12.异或是个好东西。a&1可以用来判断a的最后一位是否为0,也就意味着可以判断a的奇偶性;a>>1是除以2;1<<a是2的a次方。
13.位运算是个好东西,例如h&(2的n次方-1)和h&(2的n次方)等价但不等效。
14.题目要求不开辟多余空间时,可以考虑位运算。
15.列表中判断是否有环可以使用集合将每一个节点添加判断,空间复杂度为On;还可以使用赛跑的思想,设置两个不同移动速度的指针,指针1一次移动1步,指针2一次移动2步,若有环,则指针2总会追上指针1。
16.寻找个数超过数组二分之一的众数可以通过一次遍历的count加减完成,最终留下的大于0的count即为众数。
17.计算n阶乘后缀有几个0时,考虑10都是由2*5所得,所以n阶乘中出现5的次数等于阶乘结果中后缀0的个数。
18.涉及到二进制时,考虑使用位运算符。
19.位运算符中:n&1为摩操作,n>>1为除2操作,n<<1为乘2操作。
20.当分母可能为0时,可以使用num==0?1:num进行规避。
21.Deque是双端队列的接口,LinkedList和Deque都是双端队列的实现类,一个是顺序存储一个是链式存储,也可以当做栈进行使用。
22.如果某一种哈希技术在进行查找时,其最坏情况的内存访问次数为 O(1) 时,则称其为完美哈希,设计完美哈希的基本思想是利用两级的哈希策略,而每一级上都使用全域哈希。通过适当地选择第一次哈希函数,预期使用的的总存储空间仍为 O(n)。
23.在BST中,节点左子孙的值都小于等于节点的值,节点右子孙的值都大于等于节点的值。在BST中寻找两个节点的最小公共元祖可以通过将root节点与两个节点的值进行比较。若两个目标节点的值都小于该节点,则寻找该节点左子树;若两个目标节点的值都大于该节点,则寻找该节点右子树;其余情况则直接返回root得到结果。因为只有如下两种情况:1-两个目标节点分别位于root的左子树和右子树;2-其中一个目标节点就等于root节点。
24.涉及到字符串中的字母操作,可以考虑使用长度为256的int数组进行操作。
25.Stack用于深度优先遍历,Queue用于广度优先遍历。
26.数根是将一正整数的各个位数相加(即横向相加),若加完后的值大于等于10的话,则继续将各位数进行横向相加直到其值小于十为止,或是,将一数字重复做数字和,直到其值小于十为止,则所得的值为该数的数根。公式法求树根:n的根为 (n-1)%9+1。(九余数定理)
27.当输入的数值规模可能会很大时,应考虑将数值的规模不断缩小,而不是尝试去达到那个数值。
28.二分查找中, mid = left + (right - left) / 2而不是mid = (right - left) / 2,是为了防止left不为0,存在偏移量。循环条件是mid < target,说明target在mid右侧,left = mid + 1;mid > target,说明target在mid左侧,right = mid - 1;相等则返回mid。
29.Integer.bitCount可以对整数中1的位数进行计数,可用于判断是否是2的幂。
30.Integer.toString(5,3)代表将5转化为3进制,返回的是字符串形式。
31.str.matches(“^10*$”)用于匹配1开头的字符串,并且后面以若干个0结尾。
32.判断一个数n是否是i的幂次数可以有如下几种思路:对n不断模i;用范围内最大的i的幂次数对n取模;用数学公式推导;用Integer自带的方法去转进制再对字符串进行匹配。
33.StringBuilder是对字符串本身进行修改,所以进行apend操作后无需复制,该对象已经被更改。
34.2进制转16进制的思想是,将数组通过与运算(&15)进行模16操作,取得对应的字母相加,然后将2进制数通过无符号右移4位(>>>4)进行除16操作直至该数为0。
35.创建List数组时如果知道数组大小或者大小的上限,应该直接指定数组的大小,List扩容的过程十分耗费资源。
36.对非常大的数字进行模操作,可以通过设置一个临时变量来记录数据间隔,这样能大大地降低模操作的运算规模。
37.处理边界问题时,例如处理int型的数据,可以使用long的边界作为算法边界,返回结果时再转化为int,这样使得数据的边界更好处理。
38.写算法题时设置的静态变量最好在每次程序开始时进行初始化,因为模拟编译器可能会多次调用该方法发造成结果出错。
注意Integer整型越界问题,必要时强制转化若干变量为long。
39.对于n个数字,至少需要做多少次n-1个数字的+1操作,可以通过数学推导获得。始终把握一点:最小数参与了所有的+1操作,然后列出等式求解。
40.当一个复杂运算需要调用的次数过多时,可以通过逆向思维来解题。例如找出两个n位数相乘的最大水仙花数,不应该对每两个n位数的乘积进行水仙花数判断,而应该构造水仙花数,再去判断是否有两个n位数的乘积能够和该水仙花数相等。