刷的脑壳疼,在螺旋矩阵卡了很久,其他的 easy 题都也被卡,目前进度为 2-3 medium / day。
Monday (科普知识)
反码、补码
二进制的第一位是符号位,0是+,1是-,如果是1,怎么得到具体数字? 二进制数全都取反,再+1就是对应结果的的绝对值 。 例如-1的二进制数全为1,则将后31个1全取反并+1,得到 000…1 的十进制数就是1 。
如何把随机出现从 x 概率变为 x^3 概率?
Math.Max(Math.Random(),Math.Max(Math.Random(),Math.Random()));
注意:Random生成一个[0,1)
如何在 1-5(int)随机函数上生成1-7的随机函数?
直接把1-5改成随机生成0、1的函数,1、2返回0,3就return重来,4、5就返回1 。
再根据读书器返回0、1的函数处理:
|
|
注意:
- 如果直接 相乘 是不行的,因为只返回 0、1 乘了 7 就变成 0、7 。会缺失中间的数。
- 0-7 有了,我们要 1-7 ,那只能 0-6 随机再+1 。1-7 只要遇 7 重来就行了。或者直接 0 重来。就不用再 +1。
为什么不能直接 (f() « 2) + (f() « 1) 呢?直接得到 0-6
- 因为左移两位得到要么是0要么是4,左移一位是0或2,不移动0、1 。得到的具体数字不是范围,再将其相加,产生的和才是一个范围。
如何改变一个任一固定概率的随机0、1函数变为产生0、1都为50%的函数?
运行两次该函数,两次得到0的概率为 p^2 ,两次得到 1 的概率为 (1-p)^2 ;而一次 0 一次 1 的概率是 p*(1-p); 所以只要两次返回一次为 0 一次为 1 就行。不然就重新执行。
Tuesday
206. 反转链表
这题一定要按清楚头指针 pre、next 指针只是指针,不是一个结点指向另一个结点的指针。定义出这两个指针、画好图就很容易操作。这是单链表的反转,至于双链表就是多加了一个 last 指针指向上一个,只需要在存 next 时多存一个 last ,其他无需改动。
704. 二分查找
首先把 left 、mid 、 right 都定义出来。mid 的赋值,左右指针的跳转都在循环内完成,注意要 left=mid+1,right = mid-1,不然藏在边界的 target 就查不到了。
27. 移除元素
暴力解法:需要注意,i–;是因为既然当前值为 ?的点的右边所有点一切都左移了一位,所以现在的 i 指向的是已删除(被覆盖)的位置,该位置补了后面那位没被扫描的数字,而该次循环结束就要 i++了,所以会指向这个没扫描的下一个进行扫描,就漏掉一个了。再一个注意溢出边界问题,还有一个就是无限循环容易发生是因为 for 循环条件不能是 < length。而应该是 <size 这个自定义的,会随着更新而更新。
Wednesday
977. 有序数组的平方
这一题犯了一个总是犯的错误,总是忘记写返回值,以后第一步确定返回值,不明则??表示。
该题暴力解法就是平方再排序美滋滋~,但是时间复杂度为O(n^2),有O(n)的解法:双指针。
双指针解法一定要注意边界。
209. 长度最小的子数组
暴力解法要注意必须双层循环。为了避免要判断第一次 >target,把 len 初始值设为Interger.MAX_VALUE。滑动窗口:注意循环条件的边界。
Thursday
59. 螺旋矩阵 II
该题一定要注意别自己瞎套,while 的条件按照(循环次数)来。偏移量每次+2,从左到右,从上到下的循环条件要-offset。
203. 移除链表元素
先把头的 val 确定 ≠ val、≠null 再去定义 cur 等等其他结点,记得依次讨论头不为空(头的 val 为 val)、头为空(return head把整个链表有可能为空的情况删除整个链表了直接提前退出)。
不为空 && 头的 val == val 一定要把 ≠null 写在 && 前面,不然先判断 head.val 如果说 head == null ,那就直接报错了。
删除一定要 XXX.next = XXX.next 这样操作,自己定义的 cur 、 next 都只存一个地址,cur = nextNode 就是 cur 指针走到了 nextNode 这个位置。
Friday
707. 设计链表
只要把get、addIndex、delete写出来就行了,另外两个addHead、addTail直接调用这个addIndex就行了,至于get、delete都是用addIndex里面for查找的逻辑找到,主线就是写出addIndex,注意在addIndex里面 size++ 就够了,不要反复 ++ ;
另外自己定义一个 ListNode 的 class ,构造方法只要空参。成员变量 int val、 ListNode next;
24. 两两交换链表中的结点
非必要情况下,不要定义那么多 next、cur 结点,不然判空很头大,如果是在 while 内,cur、next、pre 都在变换,判空繁琐,在初始化时也要判空,还是尽量只定义一个 pre 结点,反正操作链表的元素有个 pre 就够了。
19.删除链表的倒数第N个节点
暴力解法:注意考虑传入的值的合法性。
进阶版本:首先一边扫描肯定无从下手,想想,倒数第 n 个结点,是正着数的第几个 ?
- 显而易见:size-n 个,那如何拼凑出 size ?那是肯定要扫描一遍完整的链表结点的。
如果扫描 size++ 出长度那必然要再操作一遍,落入了扫描多次的圈套,so what?
- 定义一个 fast 指针、一个 slow 指针,fast 扫描全文,而 slow 指向要被删除的结点的上一结点。如何凑出 size -n?先让 fast 走 n 次,再让 fast 和 slow 一起走剩下的 size-n次,此时fast 指向了最后一个元素,slow 指向了删除的结点的上一结点。
持续更新中…….. 敬请期待