Algorithm:
225: Implement Stack using Queues (Easy)
232: Implement Queue using Stacks (Easy)
栈和队列互相表达虽然很简单,但是有多种办法,比如使用队列时的双队列、单队列、操作头部、操作尾部、peek优化等,最终可以实现非常简洁的代码。使用栈实现队列虽然不像实现栈时可以只用一个队列,但是用两个队列实现栈可以达到所有操作平均复杂度o1,技巧是定义第二个队列为只用来输出的栈,只有它空了时候才一次性把另一个栈搬过来,不用每次操作都搬,注意peek这里需要用临时变量暂存,加速peek,这点需要同时考虑两个栈的数据情况。
17: Letter Combinations of a Phone Number (Medium)
16.11: Diving Board LCCI (Easy)
50: Pow(x, n) (Medium)
有陷阱的一题,注意 int 的最小值 -2^31 转成正数是会溢出的(int 最大值 2^31 - 1),需要用 long 表达。另外非递归实现使用了位运算技巧,按位拆分,不容易想出来TODO。
Review:
Principles to Handle Thousands of Connections in Java Using Netty
之前只知道基于 epoll 调用实现的同步非阻塞模式是解决 C10K 连接问题的核心。这篇文章介绍了 Java 应用在这方面的一些原则(经验),主要有以下几个方面:
- 调整应用程序,尽量使用异步处理(用 mq 操作数据库、异步调用依赖 api),使用尽量少的线程,不要阻塞事件循环等
- 使用长连接(keep-alive)缓存连接;新建连接需要有队列机制,避免大量新连接冲击
- 设置 TCP 收发缓存
- 使用 DirectByteBuffer 减少垃圾回收压力
- 平衡吞吐和延迟
Tip:
Redis 内存估算与压缩
思考这样一个场景,在广告投放业务中为了存储和查询某设备的投放策略,数据是每天定期更新,存储在 Redis 中,使用设备号的 md5 作为 key, 数据日期 yyyyMMdd 作为 value,这样的 10亿 条数据占用多少内存?答案是大概 100 GB 多一些。
仔细分析 md5 长度 32 位,加上 8 位日期一共 40Byte,但是实际占用空间超过了 100B,这是因为 Redis 内部数据结构需要辅助空间,包括数据类型、指针、编码、超时等元信息。
在 Redis 中,键的类型是字符串,值的类型有字符串、列表、哈希、集合、有序列表、HyperLogLog 等。其中列表是使用双向循环链表实现,哈希是支持渐进式扩容缩容的哈希表实现,有序集合是使用跳表实现。但是在某些条件下,比如数据条数较小并且每条数据量不大时,这三种结构都会使用压缩列表 ziplist 实现。比如哈希在 field 数量 512 以内且 field 和 value 都小于 64 字节时用 ziplist 实现。压缩列表 ziplist 是一种数组实现,节点中有长度信息以支持不同长度的节点(因此不支持随机访问,需要 O(n) 访问),因为数据量小并且连续,可以有效利用 CPU 缓存机制加速。
回到当前问题,为了减少 Redis 内容使用,可以利用压缩列表特性进行优化。先对原来的键也就是设备号md5取模进行分桶,通过计算保证每个分桶小于 512 个元素,以分桶号作为哈希键,md5 作为 field,数据日期作为 value。查询时先计算分桶号,再 HGET bukectId md5 获得结果。
Share:
How To Be More Disciplined
- FINDING HIS REASON WHY
- DEVELOPING DISCIPLINE THROUGH SINGULAR ACTIVITIES
- PRE-PLANNING FOR TEMPTATION
如何更加自律
- 动机与缘由,这是开始思考和决定变好的起始。强烈的动机能成为一个良好的开始,但是并不能持久,常常造成三天打鱼两天晒网的情况。
- 通过单一活动锻炼自律。这是一个非常重要的策略,没人是万能的,尤其是没有自律时,同时定下好几个需要靠自律的目标是非常不切实际的。
- 对诱惑进行预先备案。比如刻意回避、冷静时刻、执行预先的替代行为等。