LeetCode No.542 寻找 0-1 矩阵中的最小距离
给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离。 两个相邻元素间的距离为 1 。 示例 1:输入: 1230 0 00 1 00 0 0 输出: 1230 0 00 1 00 0 0 示例 2:输入: 1230 0 00 1 01 1 1 输出: 1230 0 00 1 01 2 1 注意: 给定矩阵的元素个数不超过 10000。给定矩阵中至少有一个元素是 0。矩阵中的元素只在四个方向上相邻: 上、下、左、右。 方法一:多源广度优先搜索 对于矩阵中的每一个元素,如果它的值为0,那么离它最近的0就是它自己。如果它的值为1,那么我们就需要找出离它最近的0,并且返回这个距离值。那么我们如何对于矩阵中的每一个1,都快速地找到离它最近的0呢? 我们不妨从一个简化版本的问题开始考虑起。假设这个矩阵中恰好只有一个0,我们应该怎么做?由于矩阵中只有一个0,那么对于每一个1,离它最近的0就是那个唯一的0。如何求出这个距离呢?我们可以想到两种做法: 如果0在矩阵中的位置是(i0, j0),1在矩阵中的位置是 (i1,...
LeetCode No.234 回文链表
请判断一个链表是否为回文链表。 示例 1: 输入: 1->2输出: false示例 2: 输入: 1->2->2->1输出: true进阶:你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题? 转化成数组后使用双指针首先想到的方法是遍历链表,将链表中的元素添加进数组,然后使用双指针解法,一个指针从前向后扫描,另一个指针从后向前扫描,一旦发现两个指针所指向的元素不同则不是回文,否则两个指针向中间靠拢,如果两个指针相遇,则是回文。这种思路其实是判断回文字符串。 1234567891011121314151617var isPalindrome = function (head) { let arr = []; let cur = head; while (cur) { arr.push(cur.val); cur = cur.next; } let i = 0, j = arr.length - 1; while (i < j) { if (arr[i] !==...
LeetCode No.19 删除链表中的倒数第 k 个元素
很容易想到的是先求出链表中元素的总个数,然后删除正数第n-k个元素,代码如下(下面的代码使用了虚拟头结点优化判断删除头结点的情况) 1234567891011121314151617181920var removeNthFromEnd = function (head, n) { let count = 0; let cur = head; while (cur) { cur = cur.next; count++; } const dummyHead = new ListNode(-1); dummyHead.next = head; let prev = dummyHead; cur = head; let cnt = 0; while (cnt < count - n) { prev = cur; cur = cur.next; cnt++; } prev.next = cur.next; return...
LeetCode No22.括号生成
题目描述如下: 数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。 示例: 12345678输入:n = 3输出:[ "((()))", "(()())", "(())()", "()(())", "()()()" ] 暴力破解初看这一题,首先想到的是n个左括号和n个右括号的数组进行全排列得到所有的序列,然后从序列中过滤出合法的括号序列和重复序列(因为字符是有重复的,可能导致全排列本身中出现序列重复), 代码如下: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647var generateParenthesis = function (n) { // 方案1:获取数组全排列,判断全排列中合法的括号 const arr = []; ...
如何实现 async/await
基于Promise的异步处理虽然解决了基于callback的过多嵌套的问题,但是可读性也还是比较差,流程控制也不是特别方便。所以ES7提出了async函数完美解决了上述问题。探究其原理async/await实际上是对Generator的封装,是一个语法糖,只不过generator出现不久后就被async/await取代了。 ES6 新引入了 Generator 函数,可以通过 yield 关键字,把函数的执行流挂起,通过 next()方法可以切换到下一个状态,为改变执行流程提供了可能,从而为异步编程提供解决方案。 可以看出yield和async/await已经非常相似了,他们都提供了暂停执行的功能,但是二者又有以下几点不同: async/await自带执行器,不需要手动调用 next()就能自动执行下一步 async函数返回值是 Promise 对象,而 Generator 返回的是生成器对象 await能够返回 Promise 的 resolve/reject 的值 我们对 async/await...
如何实现一个 Promise
先来看下Promise的常见应用: 观察者模式观察上面的这个例子,我们来分析Promise的调用流程: Promise的构造方法接受一个executor函数,在new Promise的时候这个executor立即执行 executor内部的异步任务被放入微任务队列等待执行 then被执行,收集成功/失败回调,放入成功/失败队列 executor的异步任务被执行,触发resolve/reject,从成功/失败队列中取出回调依次执行 由上面的分析得知这是一种典型的观察者模式。这是典型的“收集依赖->触发依赖->取出依赖执行”的方式,被广泛运用于观察者模式 ,在Promise中执行顺序是“then收集依赖->异步触发resolve->resolve执行依赖”。由此我们可以勾勒出Promise的大致形状: 123456789101112131415161718192021222324252627282930class Promise{ constructor(executor){ ...
股票投资从入门到放弃
...
一些好用的轮子和工具
canvas绘图阿里的数据可视化的底层框架g2,无需从头到尾操作原生canvas api了,画线、矩形、圆形、贴图等非常便利。 提高效率的chrome拓展 双向修改CSS的工具livestyle
一些生活技能
我当然不喜欢贫穷,人穷志短,成天为衣食住行操心是很毁人的。但我从不梦想着大富大贵,因为人一旦把赚钱当作目的,就永远也不会觉得够。富了终归可以更富,走上这条路的人,很少能够自己停下来。有大量触目惊心的权钱交易的案例已经证明,对金钱的贪欲会使人不顾一切,甚至不要性命。千万不要以为,这些一失足成千古恨的人是天生的坏人。事实上,他们与我们中间许多人的区别只在于,他们恰好处在一个直接面对巨大诱惑的位置上。赚多少钱是个够?永远也没够!不管是谁,赚钱的目的,不过是为了更幸福。但有时候,我们走得太远,慢慢忘记了为什么出发。 健身食材香蕉 燕麦 鸡胸 鸡蛋...
Koa 源码解析
洋葱圈的实现我们这样使用中间件: 123456789101112131415161718192021222324252627const Koa = require('koa');const app = new Koa();// loggerapp.use(async (ctx, next) => { await next(); // 1 const rt = ctx.response.get('X-Response-Time'); // 2 console.log(`${ctx.method} ${ctx.url} - ${rt}`);});// x-response-timeapp.use(async (ctx, next) => { const start = Date.now(); // 3 await next(); // 4 const ms = Date.now() - start; // 5 ...