C++:刷LeetCode踩过的坑
最近在刷Leetcode的时候踩了不少坑,这里列一下提醒自己以后注意。
- 循环体的条件部分,虽然《C++Primer》说以
!=
做判断,用各种类型的size_type
做循环变量是个好习惯,但是这只适用于以遍历为目的简单循环。当循环条件比较复杂时,循环条件可能一开始就不成立,这种情况下使用<
或>
没有问题,而使用!=
就会得到错误结果,容易陷入死循环。另外,无符号的size_type
类型与负数相比较时,会将负数转换为一个很大的无符号数,从而得到错误的结果。如果不能保证进行条件判断的变量都为无符号数,还是老老实实用int
比较简单。简单说,无符号数慎用<
,带符号数慎用!=
。 - 使用容器的
size()
函数时,一定注意其返回的是一个无符号数。将其直接作为循环的终止条件当然是不会出问题的,但是如果需要把size()-1
之类的作为循环终止条件的话,最好先把size
赋值给一个int
型的变量,再使用这个变量进行操作。 - 异常处理真的是个非常非常麻烦的事情。
- 当int可能溢出的时候,试试long long。
- 二分查找不需要对偶数长度的序列做特殊处理,单数情况拿中位数,偶数情况拿中间右侧的数当分割点就可以,左半部分
<
分割点,右半部分>=
分割点,l = mid + 1
,r = mid
,mid = l + (r - l) / 2 = (l + r) / 2 = (l + r) >> 1
。 - 循环体内少做特殊情况判断,没次多个判断浪费时间,程序正常流程能够处理的情况不要提前判断退出。
- 使用
stringstream
可实现多种类型向string
或char
的转换,利用<<
将数据输出到stringstream
,再使用>>
即可从流输入char
类型数据,使用str()
方法可以获得流中的string
。多次利用流需要使用clear()
等方法将状态位置位才能继续输入。 - 回溯算法递归剪枝的时候,应该在上一次递归中判断条件,不满足就不要进行下一次递归;而不是在下一次递归最开始的部分判断条件,不满足再返回。
- 递归的时候可以把传引用参数的实参作为类成员,能少传很多参数,看起来简洁一些。
- 用
target - current >= 0
的判断比另外维护一个sum
进行sum <= target
的判断更好些。 - 用
bitset<n>
和bool[n]
效果差不多,前者更好一些。 - 非内置类型作为参数,能用const引用尽量用,不要传值,不然太慢。
- 递归计数,一种方法是把数字作为参数传进去随前向递归过程递增,终止时返回这个数;另一种方法是令终止条件返回0,在回溯return语句中完成递增过程。
- 栈可以做深度优先搜索,队列则可用于广度优先搜索。
不定期更新。