这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天
一、课程主要内容
1、Leftpad事件
2、代码实践1:交通灯
3、代码实:2:洗牌
4、代码实践3:抽红包
二、内容重点
1、Leftpad事件
重点:代码不够简洁、性能有待提升
解决方案:使用repeat方法替代while循环(时间复杂度为O(n)),由于repeat方法使用2进制幂的方法得到待补齐的长度,进一步减小时间复杂度,为O(log2n);
2、代码实践1:交通灯状态切换
版本1:对于后续交通灯状态转换使用setTimeout回调嵌套,代码可读性差,且难以维护;
版本2(数据抽象):将交通灯状态数据抽象成一个数组,利用递归调用依次触发当前状态的定时器。
版本3(过程抽象):利用函数式编程思想,拟定整个交通灯轮询为高阶函数,以设置各个交通灯状态数据的函数为参数,以调用当前交通灯状态的函数为返回值。
版本4(异步):使用 async await编程,更加直观、可读性强。
3、代码实践2:洗牌
(1)错误写法:使用sort方法,在该方法的回调中使用相等概率随机选取升序或降序排列。因为sort方法是两两交换比较,对于n个数,第一个数出现在最后一位的概率为 1/2^(n-1),如果随机排序的概率应该是1/n, 所以不准确。
(2)正确写法:使用for循环,从最后一张牌开始,从0到当前牌的位置随机选取一个数,将该数对于的索引上的牌与当前牌交换。
例如一共n张牌,从第n张牌开始,从0n-1随机选一个数,将第n张牌与该数对应的牌交换,所以第n张牌到任意一个位置上的概率都为1/n;而对于第n-1张牌,从 0n-2随机选一个数,将第n-1张牌与该数对应的牌交换,第n-1张牌到任意一个位置上的概率都为1/(n-1),然而由于第n-1张牌有可能在上一轮与第n张牌交换过,故第n-1张牌在上一轮未被移动过的概率为1-1/n = (n-1)/n,所以第n-1张牌到任意一个位置上的概率都为1/n;
*使用生成器可以解决只需要部分牌结果的问题。
4、代码实践3:拆红包
(1)切西瓜法:选取最大的一个数拆分。较平均
(2)抽牌法: 将金额排成从1到总数递增的数列,从中随机抽取(红包数-1)个数作为"隔板数”,然后将这些“隔板数”和金额总数一起升序排列,将该数列从末尾开始,后一个数减去前一个数得到单个红包金额。
三、课程总结
通过此次课程,我熟悉了JS代码优化的原则和案例,掌握了代码实践案例中解决问题的思路和方法,收获颇丰。