0%

问题

给定一个函数 rand5(),它可以随机、等概率地生成 0 到 4 之间的整数。现在希望使用该函数和确定性的计算过程,实现函数 rand7(),它可以随机、等概率地生成 0 到 6 之间的整数。

阅读全文 »

今天天气很好,天很晴朗,能见度也很高。坐在窗前,看着太阳一点点沉下去,色彩变得温暖橙黄。于是想到下去骑车拍落日,顺便完成今天的运动量。
向着日落的方向骑行,没过多久便日落西山,只留下一片余晖。

感叹落日的美景与白日的结束之余,一个问题浮现在脑海:我需要至少以多快的速度追赶落日,才能追上它?

香港西环的落日
深圳莲花山的落日 北京望京的落日
阅读全文 »

如果你使用 Java 开发,你应该听说过 Java 8 引进的 Lambda 表达式,以及用于处理容器类的 Streams API;
如果你用过 JavaScript,你应该也知道高阶函数(如 map/reduce, filter, sort),以及闭包、箭头函数、generator 之类的概念;
如果你上手过 Kotlin,你可能会被里面漫天飞舞的 let, apply, also, with 函数,以及一层层的花括号包裹的 Lambda 表达式感到印象深刻。

这些新鲜玩意初看起来似乎没有那么直观,甚至很别扭:这些代码块什么时候执行、如何被执行,很难一眼看出来!
尝试用一下后,你或许会想“搞这么花里胡哨的,这不就是省得给接口取名字的语法糖嘛”,然后继续写你的匿名内部类;
又或者,你会对这种简洁又新奇的写法感到欲罢不能,恨不得将整个项目都改写为花括号嵌套花括号,最后连自己都看不明白写了个啥。

但这些“新鲜玩意”其实并不新鲜,其历史甚至可以追溯到图灵第一次提出通用图灵机的概念之前!

这篇文章将试图以程序员的视角介绍函数式编程的概念,以及你为什么应该学习使用它的几个理由。

阅读全文 »

前言

这里的建议大多数应用于 Java 语言,其他编程语言也可以适当参考。
有一些更通用的、关于如何编写整洁代码的建议,可以参考《整洁代码之道》

阅读全文 »

阅读全文 »

最近写 LeetCode 踩了个坑,记录一下。

对于 PriorityQueue 和 ArrayList:

1
2
PriorityQueue<Integer> queue;
ArrayList<Integer> list;

下面两个操作是等价的:

1
2
3
4
5
// #1
for (Integer i: list)
queue.add(i);
// #2
queue.addAll(list);

然而下面代码中,前两个操作与第三个操作是不等价的:

1
2
3
4
5
6
7
8
// #1
for (Integer i: queue)
list.add(i);
// #2
list.addAll(i);
// #3
while (!queue.isEmpty())
list.add(queue.poll());

原因是 PriorityQueue.poll 操作会改变原有队列:弹出堆顶元素,再调整堆使其保持最小堆性质,这一改变对于维护其出列的有序性是必要的。另一方面,如果没有出列再调整这一过程,优先队列并不能保证遍历的有序性:只是简单的前序遍历。
换句话说就是 queue.poll 方法取出元素的顺序是有序的,而 addAll 方法与使用 for-each 循环遍历优先队列不改变原有优先队列,也就不能保证遍历顺序是有序的。这两个顺序不一样

Android Service 简介

Service 是一种可在后台执行长时间运行操作而不提供界面的应用组件。服务可由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行。此外,组件可通过绑定到服务与之进行交互,甚至是执行进程间通信 (IPC)。例如,服务可在后台处理网络事务、播放音乐,执行文件 I/O 或与内容提供程序进行交互。

服务分三种类型:

  1. 前台服务:执行一些用户能注意到的操作,如播放音乐。前台服务必须显示通知。
  2. 后台服务:执行用户不会直接注意到的操作。
  3. 绑定服务:应用组件通过调用 bindService 绑定到服务。绑定服务提供客户端-服务器接口,以便组件与服务进行交互。绑定服务仅当应用组件绑定时才会启动,当全部绑定被取消时,服务会被销毁。

服务可以既是启动服务(通过 startService 启动)又是绑定服务(通过 bindService 启动),取决于是否实现 onStartCommand()onBind() 回调方法。

阅读全文 »