Skip to content
On This Page

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];
};
  • 长时间不写 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 岁了