数组中只出现一次的数字
1. 题目描述一个整型数组中,除了 2 个数字之外,其他数字都出现了 2 次。要求找出来这 2 个数字,时间复杂度 O(N),空间复杂度 O(1)
2. 思路分析因为空间复杂度限制,所以没法用哈希表。
如果只有 1 个数字出现 1 次,那么可以使用“异或”运算,最后的结果就是这个数字。
但题目中有 2 个数字,要考虑分组问题。将这两个数字分到 2 组中,然后再每组内分别异或:
全部异或,最终结果是 2 个数字异或结果
找到结果中第一个 1 出现的位数
按照此位是不是 1,将原数据分成 2 组
组内分别异或
3. 代码实现123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960/** * 找到num二进制表示中第一个1的位 * * @param {Number} num */function findFirstBitIsOne(num) { let indexBit = 0, ...
丑数
1. 题目描述把只包含因子 2、3 和 5 的数称作丑数(Ugly Number)。例如 6、8 都是丑数,但 14 不是,因为它包含因子 7。习惯上我们把 1 当做是第一个丑数。求按从小到大的顺序的第 1500 个丑数。
2. 解题思路2.1 思路一根据定义,将给定的数不断除 2、3、5,看看能不能除尽即可。然后从 1 遍历到 1500。
2.2 思路二前面速度慢是因为计算了太多非丑数。根据丑数定义,每一个丑数都是根据前面一个丑数乘以 2、3 或者 5 得到的。
在确保顺序的情况下,逐步计算即可。
3. 代码3.1 思路一实现123456789101112131415161718192021222324252627282930// 判断是否符合丑数定义function isUgly(number) { while (number % 2 === 0) { number /= 2 } while (number % 3 === 0) { number /= 3 } while ( ...
第一次只出现一次的字符
1. 题目描述在字符串中找到第一个只出现一次的字符。
2. 思路从头到尾遍历一遍,统计每个字符的出现次数,保存到哈希表中。
再重新遍历一遍,每次都检查哈希表中的次数是不是 1,是 1,直接返回,这就是第一个字符。
3. 代码实现123456789101112131415161718192021222324252627/** * * @param {String} str */function findFirstNoRepeatChar(str) { const chars = str.split('') const map = {} for (let char of chars) { if (char in map) { map[char] += 1 } else { map[char] = 1 } } for (let char of cha ...
最小的k个数
1. 题目描述输入 n 个整数,找出其中最小的 k 个数。例如输入 4、5、1、6、2、7、3、8 这 8 个数字,则最小的 4 个数字是 1、2、3、4。
2. 思路分析这里创建一个容量为 k 的最大堆。遍历给定数据集合,每次和堆顶元素进行比较,如果小于堆顶元素,则弹出堆顶元素,然后将当前元素放入堆。
由于堆大小为 k,所以弹出、推入操作复杂度为:O(logK)。因为有 n 个,总体复杂度为:O(nLogK)。
对比快排 partition 的思路,这种思路优点如下:
不会变动原数组
适合处理海量数据,尤其对于不是一次性读取的数据
3. 代码实现请先执行:yarn add heap 或者 npm install heap
代码如下;
12345678910111213141516171819202122232425262728293031323334353637383940const Heap = require('heap')function compare(a, b) { if (a < b) { return ...
深入koa源码:核心库原理
最近读了 koa2 的源码,理清楚了架构设计与用到的第三方库。本系列将分为 3 篇,分别介绍 koa 的架构设计和 3 个核心库,最终会手动实现一个简易的 koa。这是系列第 2 篇,关于 3 个核心库的原理。
is-generator-function:判断 generatorkoa2 种推荐使用 async 函数,koa1 推荐的是 generator。koa2 为了兼容,在调用use添加中间件的时候,会判断是否是 generator。如果是,则用covert库转化为 async 函数。
判断是不是 generator 的逻辑写在了 is-generator-function 库中,逻辑非常简单,通过判断Object.prototype.toString.call 的返回结果即可:
12function* say() {}Object.prototype.toString.call(say) // 输出: [object GeneratorFunction]
delegates:属性代理delegates和 koa 一样,这个库都是出自大佬 TJ 之手。它 ...
深入koa源码:手动实现玩具版koa
最近读了 koa2 的源码,理清楚了架构设计与用到的第三方库。本系列将分为 3 篇,分别介绍 koa 的架构设计和 3 个核心库,最终会手动实现一个简易的 koa。这是系列第 3 篇,模拟实现玩具版 koa。
源码和测试代码放在了:simple-koa
准备设计思想和第三方库原理都在前 2 篇详细说明了。这篇主要目的是做一个验证检验,在语法使用 ES6/7 的语法。
在开始前,安装一下需要用到的库:
12npm install --save koa-compose koa-convert is-generator-functionnpm install --save events
测试文件为了说明效果,先按照正常使用 koa 的逻辑编写了测试文件。当启动它的时候,它的预期行为是:
监听 3000 端口
加载中间件
浏览器访问localhost:3000,屏幕打印hello
服务器的控制台依次输出:1inner => 2innter => 2outer => 1outer
代码如下:
123456789101112131415161718192 ...
深入koa源码:架构设计
最近读了 koa 的源码,理清楚了架构设计与用到的第三方库。本系列将分为 3 篇,分别介绍 koa 的架构设计和 3 个核心库,最终会手动实现一个简易的 koa。
koa 的实现都在仓库的lib目录下,如下图所示,只有 4 个文件:
对于这四个文件,根据用途和封装逻辑,可以分为 3 类:req 和 res,上下文以及 application。
req 和 res对应的文件是:request.js 和 response.js。分别代表着客户端请求信息和服务端返回信息。
这两个文件在实现逻辑上完全一致。对外暴露都是一个对象,对象上的属性都使用了getter或setter来实现读写控制。
上下文对应的文件是:context.js。存了运行环境的上下文信息,例如cookies。
除此之外,因为request和response都属于上下文信息,所以通过delegate.js库来实现了对request.js和response.js上所有属性的代理。例如以下代码:
12345678910/** * Response delegation. */delegate(proto, 'res ...
WebSocket学习和群聊实现
WebSocket协议可以实现前后端全双工通信,从而取代浪费资源的长轮询。在此协议的基础上,可以实现前后端数据、多端数据,真正的实时响应。在学习WebSocket的过程中,实现了一个简化版群聊,过程和代码详细记录在这篇文章中。
简易版的实时群聊效果图如下:
1 概述1.1 WebSocket 是什么?
建立在 TCP 协议之上的网络通信协议
全双工通信协议
没有同源限制
可以发送文本、二进制数据等
1.2 为什么需要 WebSocket?了解计算机网络协议的人,应该都知道:HTTP 协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起,服务端对请求做出应答处理。
这种通信模型有一个弊端:HTTP 协议无法实现服务器主动向客户端发起消息。
因此,如果在客户端想实时监听服务器变化,必须使用 ajax 来进行轮询,效率低,浪费资源。
而 websocket 就可以使得前后端进行全双工通信(两方都可以向对方进行数据推送),是真正的平等对话。
2 WebSocket 客户端支持HTML5的浏览器支持 WebSocket 协议:
1var ws = ...
「译文」逐步替换Sass
翻译说明这是一篇介绍现代 css 核心特性的文章,并且借助 sass 进行横向对比,充分体现了 css 作为一门设计语言的快速发展以及新特性为我们开发者带来的强大生产力。
第一次尝试翻译技术文,为了让文章更通俗易懂,很多地方结合了文章本意和自己的说话风格。另外,时间有限水平有限,难免有些失误或者翻译不恰当的地方,欢迎指出讨论。
英文原文地址:https://cathydutton.co.uk/posts/why-i-stopped-using-sass/
正文开始我每年都要重新搭建和设计我的网站,这是一个非常不错的方式去跟进 HTML/CSS 的最新进展、开发模式和网站生成器。在上个月,我发布了新版本:从 Jekyll 和 GithubPages 迁移到 Eleventy 和 Netlify。
一开始,我并没有移除代码中所有的 sass 代码。这本不是我计划中的事情,但随着我不断查看 sass 代码,我一直在思考:它们是否给网站带来了价值,还是仅仅增加了复杂度和依赖性(特指对:scss)?随着这年 css 的发展,曾经让我使用 sass 的原因似乎不那么重要了。
其中一个例子就是我已经 ...
玩转 Nodejs 命令行
背景在做 cli 工具的时候,非常需要命令行相关的第三方库。一个比较稳健成熟的命令行应该考虑以下 4 种需求:
读取传入的各种参数,例如: –help, -v=123
逻辑处理和友好的 UI 交互,例如:提供列表选择
细致控制字体颜色和背景颜色
状态显示,例如:等待过程前面是转圈圈,完成过程前面自动换成对号
在开始前,安装一下需要用到的库:
1234npm install --save inquirernpm install --save commandernpm install --save inquirernpm install --save ora
下面的四个文件例子只需复制粘贴到文件通过 node.js 即可运行
读取参数: commander这里用到的是 commander 这个库。它的文档地址是:https://www.npmjs.com/package/commander
请先看下面代码:
12345678910111213141516171819202122232425262728293031323334353637383940414243const progra ...