LeetCode刷题总结(基础篇)

概述

最近刷了一些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<
  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. 写算法题时设置的静态变量最好在每次程序开始时进行初始化,因为模拟编译器可能会多次调用该方法发造成结果出错。
  39. 注意Integer整型越界问题,必要时强制转化若干变量为long。
  40. 对于n个数字,至少需要做多少次n-1个数字的+1操作,可以通过数学推导获得。始终把握一点:最小数参与了所有的+1操作,然后列出等式求解。
  41. 当一个复杂运算需要调用的次数过多时,可以通过逆向思维来解题。例如找出两个n位数相乘的最大水仙花数,不应该对每两个n位数的乘积进行水仙花数判断,而应该构造水仙花数,再去判断是否有两个n位数的乘积能够和该水仙花数相等。

你可能感兴趣的:(算法)