Skip to content

202312

INFO

马上又年长了 1 岁,可技术没有与之递增,要有紧促感!

20231101

焦急等待开奖,还不知道路在哪里 2023118

20231126 攻克算法

20231201 react 框架需要重塑

1201

简单来说, Server Actions 可以直接让我们在 JSX 代码中操作 Server 相关的能力。

  • 你的问题主要在于读书不多而想得太多。——杨绛

1202

RAIL(response/animation/idle/load)

RAIL 是一个关于浏览器性能优化的指导原则,它提供了一种系统化的方法来评估和改善网页应用的性能。RAIL 是由 Google 提出的,旨在帮助开发人员更好地理解和优化用户体验。 RAIL 模型的核心理念是将用户的交互操作分解为四个关键阶段:

  • 响应(Response):在 100 毫秒以内响应用户的输入,使用户感觉到立即的反馈。这包括处理点击、滚动和触摸等用户交互。

  • 动画(Animation):保持动画流畅并以每秒 60 帧的速度进行渲染,以确保动画的平滑度和视觉连续性。

  • 空闲(Idle):利用主线程空闲时间执行后台任务,例如预加载资源、数据获取和计算等,以避免阻塞用户交互。

  • 加载(Load):在 5 秒内将页面内容加载完毕,并在此期间提供关键内容,以使用户能够尽快与页面进行交互。

RAIL 模型的目标是在每个阶段都提供良好的用户体验,并确保在关键性能指标上达到可接受的水平。通过使用 RAIL,开发人员可以更有针对性地优化网页应用的性能,提高用户满意度。 需要注意的是,RAIL 模型并不是一种具体的技术或工具,而是一种方法论和指导原则,它可以与其他性能优化技术和工具结合使用,帮助开发人员构建高性能的网页应用。

1203

  • 907,前端面试几大块:算法/项目/框架 生态/八股文,目前几个缺点,算法题刷的不够多,框架八股文总结的不够好,需要多总结,多背背 算法和框架两个大子项如何短时间内进步呢?

    做好重复记忆和多次训练以及思维导图

1204

  1. JSX 具有 JavaScript 的完整表现力,可以构建非常复杂的组件。但是灵活的语法,也意味着引擎难以理解,无法预判开发者的用户意图,从而难以优化性能。

2.Template 模板是一种非常有约束的语言,你只能以某种方式去编写模板。

  • Vue3.0 动静结合的 DOM diff

Vue3.0 提出动静结合的 DOM diff 思想,动静结合的 DOM diff 其实是在预编译阶段进行了优化。之所以能够做到预编译优化,是因为 Vue core 可以静态分析 template,在解析模版时,整个 parse 的过程是利用正则表达式顺序解析模板,当解析到开始标签、闭合标签和文本的时候都会分别执行对应的回调函数,来达到构造 AST 树的目的。

借助预编译过程,Vue 可以做到的预编译优化就很强大了。比如在预编译时标记出模版中可能变化的组件节点,再次进行渲染前 diff 时就可以跳过“永远不会变化的节点”,而只需要对比“可能会变化的动态节点”。这也就是动静结合的 DOM diff 将 diff 成本与模版大小正相关优化到与动态节点正相关的理论依据。

1205

  • 909
  • 每天做题,刷题,刷到 2 月份(刷到 1 月底就算是成功了一半),争取把常见的/热门的/常考的背好,真正让你写的时候,不慌,即使有一点没写对,慢慢调试,都是没问题的。量化:时间刷到 2 月份,算法刷到 100 题
  • 题目永远刷不完,我深知这一点,所以应该有个觉悟,把核心知识点掌握,理解透,下次再来复习时,理解的速度会快很多,然后不断重复,估计刷个十次八次应该就能记住 80%
  • 手写 js,最长公共前缀能写出来真的不容易啊
js
// 二叉树最大深度
function maxDepth(root) {
  if (!root) return 0
  let leftH = maxDepth(root.left)
  let rightH = maxDepth(root.right)
  let h = 1 + Math.max(leftH, rightH)
  return h
}
// 二叉树最小深度
function minDepth(root) {
  if (!root) return 0
  let leftH = minDepth(root.left)
  let rightH = minDepth(root.right)
  if (root.left != null && root.right == null) {
    return leftH + 1
  } else if (root.left == null && root.right != null) {
    return rightH + 1
  }
  return 1 + Math.min(leftH, rightH)
}
// 最长公共前缀
// 输入:strs = ["flower","flow","flight"]
// 输出:"fl"
// 横向扫描
var longestCommonPrefix = function (arr) {
  var findLong = (str1, str2) => {
    var len = Math.min(str1.length, str2.length)
    var index = 0
    while (index < len && str1[index] === str2[index]) {
      index++
    }
    return str1.substr(0, index)
  }
  if (!arr || arr[0].length == 0) return ""
  var prefix = arr[0]
  for (let i = 0; i < arr.length; i++) {
    let item = arr[i]
    prefix = findLong(prefix, item)
    if (item.length === 0) {
      break
    }
  }
  return prefix
}

// 纵向扫描
var longestCommonPrefix = function (arr) {
  if (!arr || arr[0].length == 0) return ""
  var count = arr.length
  let len = arr[0].length // 以第一个为参考标准 进行纵向扫描
  for (let i = 0; i < len; i++) {
    for (let j = 1; j < count; j++) {
      if (i === arr[j].length || arr[0].charAt(i) != arr[j].charAt(i)) {
        return arr[0].substr(0, i)
      }
    }
  }
  return arr[0]
}
// 纵向扫描2
var longestCommonPrefix = function (strs) {
  if (!strs.length) return ""
  let prefix = strs[0]
  for (let i = 0; i < prefix.length; i++) {
    for (let j = 1; j < strs.length; j++) {
      if (prefix[i] !== strs[j][i]) {
        return prefix.slice(0, i)
      }
    }
  }
  return prefix
}
longestCommonPrefix(["flower", "flow", "flight"])
  • 长时间不写 promise,还是会忘记 Promise.resolve/Promise.finally
  • 手写 class 和模拟继承两个题还是不知道怎么写,怎么调用?跌跌撞撞
js
function mockExtends(child, parent, staticProp) {
  let proto = Object.create(parent.proptotype)
  proto.constructor = child
  child.prototype = proto
  Object.setPrototypeOf(child, parent)
}

const checkNew = function (instance, con) {
  if (!(instance instanceof con)) {
    throw new TypeError(
      `Class constructor ${con.name} cannot be invoked without 'new'`
    )
  }
}
const defineProperties = function (target, obj) {
  for (const key in obj) {
    Object.defineProperty(target, key, {
      configurable: true,
      enumerable: false,
      value: obj[key],
      writable: true,
    })
  }
}
const createClass = function (con, proto, staticAttr) {
  proto && defineProperties(con.prototype, proto)
  staticAttr && defineProperties(con, staticAttr)
  return con
}
// 用法
function Person(name) {
  checkNew(this, Person)
  this.name = name
}
var PersonClass = createClass(
  Person,
  {
    getName: function () {
      return this.name
    },
  },
  {
    getAge: function () {},
  }
)
  • 问题:如何要表示除了某个单词之外的任意东西呢?某位字符可以是任何东西,但是就是不能是 xxx, 使用 ^ 符号,强烈推荐,再次推荐一本书正则表达式
js
[^abc]

常见简写方式:

js
\d // 数字
\D // 非数字
\w // [0-9a-zA-Z_]
\W // [^0-9a-zA-Z_]
\s // [\t\v\n\r\f]
\S // [^\t\v\n\r\f]
1. {m,} // 至少出现m次
2. {m} // 出现m次
3. ? // 出现0次或者1次,等价于{0,1}
4. + // 至少出现1次,等价于{1,}
5. * // 出现>=0次,等价于{0,}
  • 贪婪匹配 VS 惰性匹配?正则本身是贪婪的,会尽可能的多匹配符合模式的字符
js
let regex = /\d{2,5}/g
let string = "123 1234 12345 123456"
// 贪婪匹配
// string.match(regex) // [ 123, 1234, 12345, 12345 ]

// 惰性匹配
let regex2 = /\d{2,5}?/g
// string.match(regex) // [ 12, 12, 34, 12, 34, 12, 34, 56  ]

量词后面加一个?,即变成了惰性匹配

js
贪婪量词        惰性量词
{m,n}            {m,n}?
{m,}             {m,}?
?                   ??
+                   +?
*                   *?

1206

  • 910,与其自我紧张更希望被干掉拿补偿,与其干掉还希望能在继续 🐶1 年
  • 算法题这棵大树早晚要被我干掉,在不断重复肌肉记忆的时候,稍微多一丢丢思考就行,要求不高
  • 看到了一个牛皮的独立开发者,不仅技术强,产品思维也很厉害730 天:从 0 到每月 45000 美金,看完之后,自己 emo 了很久,对于未来充满迷茫

1207

  • 每次面试都这么痛苦,为啥呢?能促使你学习,面对自己的不足,不是挺好的一件事,可自己就是那么没用,老是特别紧张,能不能想到一种办法让自己不紧张?

痛苦说明自己在进步

  • 树转数组
js
var listTree = [
  {
    id: 1,
    name: "部门1",
    pid: 0,
    children: [
      {
        id: 2,
        name: "部门1-1",
        pid: 1,
        children: [
          {
            id: 4,
            name: "部门1-1-1",
            pid: 2,
            children: [],
          },
        ],
      },
      {
        id: 3,
        name: "部门1-2",
        pid: 1,
        children: [
          {
            id: 5,
            name: "部门1-2-1",
            pid: 3,
            children: [],
          },
        ],
      },
    ],
  },
  {
    id: 6,
    name: "部门2",
    pid: 0,
    children: [
      {
        id: 7,
        name: "部门2-1",
        pid: 6,
        children: [],
      },
    ],
  },
  {
    id: 8,
    name: "部门3",
    pid: 0,
    children: [],
  },
]
// BFS
function treeToArr(tree) {
  if (!tree) return []
  let queue = []
  queue = queue.concat(tree)
  let res = []
  while (queue.length) {
    let cur = queue.shift()
    if (cur.children && cur.children.length) {
      queue = queue.concat(cur.children)
      delete cur.children
    }
    res.push(cur)
  }
  return res
}
treeToArr(listTree)

1208

最近一周经历过三场面试,给自己一个清晰的认识,总结来说:

  • 框架八股文准备不足(思维导图继续补充完善)
  • 算法基础实在太差了,这个任重道远(每天要保持刷算法的节奏)
  • 脑子不够灵活,前端解决实际问题能力不够,这方面不是练习就能提升的,很头痛(如何举一反三?)

总结就是 太笨了,知识死记硬背,没有太多自己的沉淀,随便出一个稍微变种的题目就能把自己挂了,比如说

js
// 增加数组原型 group 方法,实现自定义分类
// 预期结果
var result = {
  bigger: [4, 5],
  smaller: [1, 2, 3],
}
var array = [1, 2, 3, 4, 5] // sorted
var res = array.group((num, index, array) => {
  return num > 3 ? "bigger" : "smaller"
})

看看人家三年的面试题,比你问的问题难多了,我 7 年自叹不如!

  • 你一开始准备 100 道题,后面觉得不够,准备了 150 道 JS 题,你想这下肯定够了吧,谁知道面试的时候,可能需要储备 100*5 = 500 道题,你就是井底之蛙,啥也不懂,脑子也不够灵活,简直废物一个! 算法: 300,目前已有 150,每天 2-3 道题,三个月 150 道题差不多 js: 200,目前已有 140 在补充 60 道题

面试官说:你不要太着急,想好了有思路再去下手,总结起来除了话术要循序渐进,还要自己平时多积累,不可能现场在想在总结,这个肯定会有问题,给人一种说话说不全的感觉

1209

  • 913,随时做好战斗的准备,多积累面试题,不错过每一天
  • 现在的面试题不再拘谨于过去已出现的面试题,要灵活运用已学的知识点,发散思维

1211

  • 915,忙了一天降级,Nodejs 端渲染页面逻辑还没处理完,明天继续处理
  • 算法题手写岛屿数量和螺旋矩阵
js
function numIslands(grid) {
  let dfs = (grid, r, c) => {
    if (!isArea(grid, r, c) || grid[r][c] != "1") return
    grid[r][c] = "2"
    dfs(grid, r - 1, c)
    dfs(grid, r + 1, c)
    dfs(grid, r, c - 1)
    dfs(grid, r, c + 1)
  }
  var isArea = (grid, r, c) =>
    r >= 0 && r < grid.length && c >= 0 && c < grid[0].length
  let count = 0
  for (let r = 0; r < grid.length; r++) {
    for (let c = 0; c < grid[0].length; c++) {
      if (grid[r][c] == "1") {
        dfs(grid, r, c)
        count = count + 1
      }
    }
  }
  return count
}
// 螺旋矩阵
// 输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
// 输出:[1,2,3,6,9,8,7,4,5]
var spiralOrder = function (nums) {
  if (!nums.length) return []
  let res = []
  let up = 0
  let down = nums.length - 1
  let left = 0
  let right = nums[0].length - 1
  while (true) {
    // 从左向右
    for (let i = left; i <= right; i++) {
      res.push(nums[up][i])
    }
    if (++up > down) break
    // 从上往下
    for (let i = up; i <= down; i++) {
      res.push(nums[i][right])
    }
    if (--right < left) break
    // 从右往左
    for (let i = right; i >= left; i--) {
      res.push(nums[down][i])
    }
    if (--down < up) break
    // 从上往下
    for (let i = down; i >= up; i--) {
      res.push(nums[i][left])
    }
    if (++left > right) break
  }
  return res
}

1212

  • 916,Promise 不能只简单实现基础版,Promise/A+实现规范
  • 算法题还需要进一步补充弹药库,现在掌握的算法题太少了,不够成系统

1213

  • 917,准备购买血糖仪,准备打印照片以及洗照片和相框
  • 老妈每天要吃这么多药,连续吃三个月?算一下每天要花多少钱就知道了
md
胃复春胶囊 4 粒 每日三次 一天 12 粒
枸酸莫沙必利片 1 片 每日三次 一天三片
奥美拉陛肠溶胶囊 1 粒 每日两次 一天 2 粒
康复新液 10ml 每日三次 一天 30ml

1214

1215

  • 919,接雨水/每日温度/螺旋矩阵/岛屿数量,继续保持,每天至少 1 道
  • 手写异步串行,长时间不写忘记了
js
function asyncSeries(arr) {
  let [first, ...others] = arr
  return (...arg) => {
    return others.reduce((pre, cur) => {
      return pre.then((val) => cur(...val))
    }, Promise.resolve(first(...arg)))
  }
}

1216

  • 920,上海温度低于 0 度

二叉树的类型

  • 满二叉树:如果一棵二叉树只有度为 0 的结点和度为 2 的结点,并且度为 0 的结点在同一层上,则这棵二叉树为满二叉树。
  • 完全二叉树:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层(h 从 1 开始),则该层包含 1~ 2^(h-1) 个节点。
  • 二叉搜索树: 二叉搜索树是一个有序树。若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉排序树
  • 平衡二叉搜索树:又被称为 AVL(Adelson-Velsky and Landis)树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过 1,并且左右两个子树都是一棵平衡二叉树。

1217

  • 921,0117951 0217 981 0317 1011 过完年即超过第一家公司
  • 看了下从 7 月开始有意练习手写代码,远远不够,需要理解+手写,重复肌肉记忆,重复肌肉记忆
  • 什么时候才能练习完基本的手写代码部分,到底什么时候,我对目前的进度有点不满意了,打不到预期,预期是元旦左右要搞完基本的手写代码题
  • 从 12 月 17 号开始刷 DP 题目,状态转移,如何转移的,刷到 12 月底,也就是 13 道题

1218

  • 922
  • 服务上云,把物理机全都下掉,首先压测得到需要的服务器配置,然后容器部署扩容,然后更改路径,最后物理机缩容
  • 怀念小时候的时光,现在长大了,经济压力越来越大

1219

  • 923
  • 昨晚偷懒了,没刷题,今天给补回来,看到一个 27 岁的前端程序猿,刷到了 330 道题,挺厉害的,比我强太多了,所以还需要磨练自己,保持刷题的习惯,贵在坚持
  • 手写 js,终于 cover 掉了几乎 99%的 Promise
js
// Promise
class Promise {
  constructor(exec) {
    this.value = undefined
    this.reason = undefined
    this.onFulfillCbs = []
    this.onRejectCbs = []
    this.status = "pending" // fulfilled rejected
    const resolve = (val) => {
      if (this.status === "pending") {
        setTimeout(() => {
          this.value = val
          this.status = "fulfilled"
          this.onFulfillCbs.forEach((fn) => fn(val))
        })
      }
    }
    const reject = (reason) => {
      if (this.status === "pending") {
        setTimeout(() => {
          this.reason = reason
          this.status = "rejected"
          this.onRejectCbs.forEach((fn) => fn(reason))
        })
      }
    }
    try {
      exec(resolve, reject)
    } catch (e) {
      reject(e)
    }
  }
  then(onFulfilled, onRejected) {
    // 参数校验,确保一定是函数
    onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (val) => val
    onRejected =
      typeof onRejected === "function"
        ? onRejected
        : (reason) => {
            throw reason
          }

    let p1 = new Promise((reoslve, reject) => {
      if (this.status === "pending") {
        this.onFulfillCbs.push(() => {
          this.resolvePromise(p1, onFulfilled(this.value), resolve, reject)
        })
        this.onRejectCbs.push(() => {
          this.resolvePromise(p1, onRejected(this.reason), resolve, reject)
        })
      }
      if (this.status === "fulfilled") {
        this.resolvePromise(p1, onFulfilled(this.value), resolve, reject)
      }
      if (this.status === "rejected") {
        this.resolvePromise(p1, onRejected(this.reason), resolve, reject)
      }
    })
    return p1
  }
  resolvePromise(p1, res, resolve, reject) {
    try {
      if (p1 == res) {
        throw new TypeError("Chaining cycle detected for promise")
      }
      if (res instanceof Promise) {
        res.then(resolve)
      } else {
        resolve(res)
      }
    } catch (err) {
      reject(err)
      throw Error(err)
    }
  }
  static resolve(val) {
    return new Promise((resolve, reject) => {
      if (val instanceof Promise) {
        val.then(resolve)
      } else {
        resolve(val)
      }
    })
  }
  static reject(reason) {
    return Promise.reject(reason)
  }
  finally(cb) {
    return this.then(
      (val) => {
        return Promise.resolve(cb()).then(() => val)
      },
      (reason) => {
        return Promise.resolve(cb()).then(() => reason)
      }
    )
  }
  // all/any/race/allSettled
  static all(arr) {
    return new Promise((resolve, reject) => {
      let res = []
      for (let [index, item] of arr.entries()) {
        Promise.resolve(item).then(
          (val) => {
            if (index == arr.length - 1) {
              resolve(res)
            }
            res[index] = val
          },
          (error) => {
            reject(error)
          }
        )
      }
    })
  }
  static allSetteld(arr) {
    return Promise.all(
      arr.map((item) => {
        Promise.resolve(item).then(
          (val) => {
            return {
              value: val,
              status: "fulfilled",
            }
          },
          (err) => {
            return {
              reason: err,
              status: "rejected",
            }
          }
        )
      })
    )
  }
}

trans(123456)

js
// trans(123456) —— 十二万三千四百五十六
// trans(100010001)—— 一亿零一万零一
function numToCn(n) {
  n = n.toString()
  let units = ["", "十", "百", "千"]
  let nums = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"]
  let res = ""
  let len = n.length - 1
  for (let i = 0; i <= len; i++) {
    let cur = n[i]
    if (cur != "0") {
      if (i >= 1 && n[i - 1] === "0") res += nums[0]
      res += nums[cur] + units[len - i]
    }
  }
  if (n.length === 2 && n[0] == "1") {
    res = res.slice(1)
  }
  return res
}
function trans(n) {
  let isLose = n < 0
  n = Math.abs(n).toString()
  let res = []
  let units = ["", "万", "亿"]
  let len = n.length // 5
  for (let i = len; i > 0; i -= 4) {
    res.push(numToCn(n.slice(Math.max(0, i - 4), i)))
  }
  for (let i = 0; i < res.length; i++) {
    res[i] = res[i] + units[i]
  }
  if (isLose) {
    res.push("负")
  }
  return res.reverse().join("")
}
trans(12345)

1220

  • 924,组织架构调整了,已经不知道调整几次了,习惯了,目前最重要的事做好打硬仗的准备,算法nodejs 知识点是每天必须要准备的。戈戈都已经要去拼多多了,还是挺厉害的,真心羡慕。自己也要努力,对得起这个年纪,最后一次选择了,希望自己能找到一个满意的下家
  • 继续 dp 手写,背包问题
js
// weight 1,3,4
// value 15 20 30
// 求背包容量是6如何装物品使价值最大化
function beibag(weight, value, size) {}
  • 今天要做的一个是 nodejs 中的进程和线程,一个是二叉树和数组之间的遍历以及多叉树的遍历,感觉现在对这块遍历特别混淆,说不清道不明的

1221

  • 925,每周三四都睡不着,也不知道有啥心事,总是感觉不安。始终没有找到归属感和责任感,希望下一家能为之奋斗努力!
  • 或许这是最后一次认真对待,开弓没有回头箭,干就对了,每天积累一点点,就行起房子似的,一点点看他起高楼。有点烦躁,不知道为啥,如果休息不好,会形成良性循环,到底啥时能复习 80%
  • 还有十天就走完 2023 年,时间过的真快,我还是这么穷

1222

  • 926,工作环境真的是醉了,克服一切阻力,远离这里,不在一个世界的人,不要有任何的交集。
  • 又到了一年一度的绩效考核时间,

1223

  • 927
  • 手撕快排,基本都是超时,过不了 AC
js
var sortArray = function (nums) {
  var partion = (nums, left, right) => {
    let pivot = right
    let leftIndex = left
    for (let i = left; i < right; i++) {
      if (nums[pivot] > nums[i]) {
        swap(nums, leftIndex, i)
        leftIndex++
      }
    }
    swap(nums, leftIndex, pivot)
    return leftIndex
  }
  var quickSort = (arr, left, right) => {
    if (left >= right) return
    mid = partion(arr, left, right)
    quickSort(arr, left, mid - 1)
    quickSort(arr, mid + 1, right)
    return nums
  }
  if (nums.length < 2) return nums
  return quickSort(nums, 0, nums.length - 1)
}
function swap(arr, i, j) {
  var temp = arr[i]
  arr[i] = arr[j]
  arr[j] = temp
}
  • 插入排序,比之前的好理解!!哇塞,确实好记多了
js
function insertSort(arr) {
  for (let i = 1; i < arr.length; i++) {
    let j = i
    while (j > 0 && arr[j - 1] > arr[j]) {
      swap(arr, j - 1, j)
      j--
    }
  }
  return arr
}
function swap(arr, i, j) {
  let temp = arr[i]
  arr[i] = arr[j]
  arr[j] = temp
}
insertSort([11, 222, 1, 2, 55, 22, 10])

二叉树分类

二叉树分为满二叉树(full binary tree)和完全二叉树(complete binary tree)。

  • 满二叉树:一棵深度为 k 且有 2 ^ k - 1 个节点的二叉树称为满二叉树
  • 完全二叉树:完全二叉树是指最后一层左边是满的,右边可能满也可能不满,然后其余层都是满的二叉树称为完全二叉树(满二叉树也是一种完全二叉树)

二叉树结构

从图中我们可以看出二叉树是从上到下依次排列下来,可想而知可以用一个数组来表示二叉树的结构,从下标 index( 0 - 8 ) 从上到下依次排列。

二叉树结构

  • 二叉树左侧节点表达式 index*2 + 1。例如:以根节点为例求左侧节点,根节点的下标为 0,则左侧节点的序数是 1 ,对应数组中的值为 1
  • 二叉树右侧节点表达式 index*2 + 2。例如:以根节点为例求右侧节点,根节点的下标为 0,则右侧节点的序数是 2 ,对应数组中的值为 8
  • 二叉树叶子节点表达式 序数 >= floor( N / 2 )都是叶子节点(N 是数组的长度)。例如:floor( 9 / 2 ) = 4 ,则从下标 4 开始的值都为叶子节点

二叉堆特征

二叉堆是一个完全二叉树,父节点与子节点要保持固定的大小关系,并且每个节点的左子树和右子树都是一个二叉堆。

二叉堆根据排序不同,可以分为最大堆和最小堆

  • 最大堆:根节点的键值是所有堆节点键值中最大者,且每个父节点的值都比子节点的值大
  • 最小堆:根节点的键值是所有堆节点键值中最小者,且每个父节点的值都比子节点的值小

二叉堆

通过上面的讲述想必大家对二叉堆有了一定的理解,那么接下来就是如何实现。以最大堆为例,首先要初始化数组然后通过交换位置形成最大堆。

1225

  • 929 圣诞节快乐,周六和周日刷题不是很满意,拖沓了,这两天弥补一下
  • 没有自己负责的核心业务,早晚被干掉,还是继续蹲面试题不,没有安全感
  • 打开格局,拓宽职业道路,往后段靠一靠,延长程序员职业生涯。例如: 1.熟悉 Nodejs,需要掌握 Nestjs 框架 2.有容器化/存储/数据库/消息队列/编排调度等场景运维背景知识 3.还想再学一门新语言,学习 golang 或者 python,明年的规划
  • 先把记账系统整一整,整体走一遍流程

1226/27

js
// 如何拦截构造函数进行拦截调用
function Person(name) {
  this.name = name
}
var t1 = new Person("cpp") // ok
var notT1 = Person.call(t1, "cpp")
console.log(t1, notT1)
// 如何改造
function Person1(name) {
  if (new.target != undefined) {
    this.name = name
  } else {
    throw new Error("必须使用new关键词")
  }
}
var t1 = new Person1("cpp") // ok
var notT1 = Person1.call(t1, "cpp")

SWR 这个名字来自于 stale-while-revalidate?如何实现 swr 机制

1228

  • 932,过完年就快突破 1000 天了,正式突破第一家的在职时间
  • 继续练习手写 js, 对象扁平化和字符串相乘
js
// 实现变量的锁定
function mockFreeze(obj) {}

1229

  • 933
  • 元旦提前回南京了

1230

  • 年终回归,整理手写题和面试题
  • 明年技术上的规划和展望

1231

  • 935
  • 新年快乐,2024 年,正式迈入 33 岁了