面试套路 - js 基础
夫大人者,与天地合其德,与日月合其明,与四时合其序,与鬼神合其吉凶。——《周易》 在 JavaScript 中, (a == 1 && a == 2 && a == 3) 是否有可能为 true 参考解决思路:a是一个对象或函数,每次调用取值都不一样,以有序的规律变化就能实现多等 方案1:使用 getter1234567let temp = 1;Object.defineProperty(global, 'a', { get() { return temp++; }});console.log(a === 1 && a === 2 && a === 3); // true 方案2:重写valueOf/toString1234567const a = { value: 1, valueOf() { return this.value++; ...
面试套路 — Linux
弱小和无知不是生存的障碍,傲慢才是。 SHELL 所能支持的最大字符串的长度是 1024 字符。 删除文件是否需要对该文件具有写权限,为什么?删除文件不需要该文件的写权限,需要文件所在目录的写权限以及执行权限。因为删除文件修改的该文件父级即其所在目录的内容,所以需要目录的写权限。 同时,删除文件先要进入到目录,进入是目录的一个操作,所以需要该目录的执行操作。 文件描述符每次打开文件都会返回一个新的文件描述符,即使是针对的同一个文件,例如: 1234while (true) { const fd = require('fs').openSync('/','r'); console.log(fd);} 上述代码中每次都打开根目录(注意linux中的文件是泛指),最后肯定会由于打开的文件描述符(使用ulimit -n)过多而报错。 1234567891011121314Error: ENFILE: file table overflow, open '/' ...
一些想读的书
软件具有熵的特质,长期迭代维护的项目总会遇到可维护性逐渐降低的问题。 软件工程 《码农翻身》 《编码》 算法 《算法新解》 《计算机程序的构造和解释》 《我的第一本算法书》 《算法图解》 《素数之恋》 《啊哈·灵机一动》 网络 《图解 TCP/IP》 《图解 HTTP》 @2025-05-21 《http 权威指南》 后端 《Redis设计与实现》 @2025-04-20 《Node.js硬实战:115个核心技巧》 @2025-06-19 《JavaScript设计模式与开发实践》 @2025-06-28 前端 《前端工程化:体系设计与实践》 架构 《从零开始学架构》 《大型网站性能优化实践》 《深入高可用系统原理与设计》 @2025-04-06 《重构 - 改善既有代码的设计》 @2025-05-25 《修改代码的艺术》 产品 《硅谷产品-36讲直通世界级产品经理》 《用数据讲故事》 《硬战-人工智能时代的爆款产品》 《人人都是产品经理 2.0》 《阿里巴巴四十大道》 《吴军的谷歌方法论》 ...
你真的会二分查找么
二分查找思路非常简单,但是变种比较多,在这些变种中,尤其边界条件特别容易出错(特别是在追求完美简洁的代码的时候)。以下就是一个寻找第一个等于特定值的元素的简洁实现: 123456789101112def find_first_equal(arr, target): left = 0 right = len(arr) - 1 while left <= right: mid = (left + right) // 2 if arr[mid] >= target: right = mid - 1 else: left = mid + 1 if left < len(arr) and arr[left] == target: return left return -1 虽然以上的代码非常简洁,但是理解起来却非常烧脑。如果只是死记硬背上面的解法,过不了几天就会全部忘光,再次编写的时候还是 90%...
LeetCode 中的位运算
No136只出现1次的数字给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗? 使用计数器比较朴素的解法是对每个元素进行计数,最后统计出数量为1的那个数,这种算法比较通用,可以解决任意多元素出现任意次,因为可以解决的问题比较多,所以往往不是最好的算法,需要维护一个HashMap,占用O(N)的空间: 123456789101112var singleNumber = function (nums) { const counter = new Map(); for (const num of nums) { let count = counter.get(num) || 0; counter.set(num, ++count); } for (const [k, v] of counter) { if (v === 1) { return k; } ...
LeetCode No.55 跳跃游戏
给定一个非负整数数组,你最初位于数组的第一个位置。 数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个位置。 示例 1:输入: [2,3,1,1,4]输出: true解释: 我们可以先跳 1 步,从位置 0 到达 位置 1, 然后再从位置 1 跳 3 步到达最后一个位置。 示例 2:输入: [3,2,1,0,4]输出: false解释: 无论怎样,你总会到达索引为 3 的位置。但该位置的最大跳跃长度是 0 , 所以你永远不可能到达最后一个位置。 回溯法首先想到的是暴力法,针对每个位置可能走的步数一个个进行测试,如果这个步数能到达或者超过最后一个位置说明就可以到达,写代码的过程中注意将已经计算过的缓存起来,使用记忆化搜索防止重复计算。还可以从最大可能走的步数开始减少代替自增这样的小技巧来优化: 123456789101112131415161718192021222324252627282930313233var canJump = function (nums) { const cache = {}; /** *...
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 = []; ...