每日的知识积累,包括 1 个 Ts 类型体操,两个 Leetcode 算法题,三个前端八股文题,四个英语表达积累。
1. 一个类型体操
If
题目
实现一个 IF 类型,它接收一个条件类型 C ,一个判断为真时的返回类型 T ,以及一个判断为假时的返回类型 F。 C 只能是 true 或者 false, T 和 F 可以是任意类型。
例如:
type A = If<true, "a", "b">; // expected to be 'a'
type B = If<false, "a", "b">; // expected to be 'b'
分析
接受三个泛型,根据第一个泛型是否为 true 决定返回后面两个中的一个。使用 extends 即可,在 Ts 中三目运算和相等都使用 extends.
尝试写出
type If<Condition, Candidate1, Candidate2> = Condition extends true
? Candidate1
: Candidate2;
测试用例
type C = If<true, "a", "b">; // "a"
type D = If<false, "a", "b">; // "b"
参考答案
type If<C extends boolean, T, F> = C extends true ? T : F;
经验总结
在 Ts 中三目运算和相等都使用 extends.
2. 两个 Leetcode 题目
刷题的顺序参考这篇文章 LeeCode 刷题顺序
2.1 [645] 错误的集合
集合 s 包含从 1 到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合 丢失了一个数字 并且 有一个数字重复 。
给定一个数组 nums 代表了集合 S 发生错误后的结果。
请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。
示例 1:
输入:nums = [1,2,2,4]
输出:[2,3]
示例 2:
输入:nums = [1,1]
输出:[1,2]
提示:
2 <= nums.length <= 104
1 <= nums[i] <= 104
尝试实现:
/**
* @param {number[]} nums
* @return {number[]}
*/
var findErrorNums = function (nums) {
nums.sort((a, b) => a - b);
var length = nums.length;
var wrongnum;
var total = nums[0];
for (var i = 1; i < length; i++) {
if (nums[i] === nums[i - 1]) {
wrongnum = nums[i];
}
total += nums[i];
}
return [wrongnum, wrongnum - (total - ((1 + length) * length) / 2)];
};
我的思路:
- 先排序,找到那个重复的数字
- 然后求和,计算出多了多少或者少了多少
- 根据重复的数字和差值找到正确的数字
得分结果: 42.74% 67.74%
经验总结: 题目一定要好好审,不然会事倍功半。
2.2 [697] 数组的度
给定一个非空且只包含非负数的整数数组 nums,数组的 度 的定义是指数组里任一元素出现频数的最大值。
你的任务是在 nums 中找到与 nums 拥有相同大小的度的最短连续子数组,返回其长度。
示例 1:
输入:nums = [1,2,2,3,1] 输出:2 解释: 输入数组的度是 2 ,因为元素 1 和 2 的出现频数最大,均为 2 。 连续子数组里面拥有相同度的有如下所示: [1, 2, 2, 3, 1], [1, 2, 2, 3], [2, 2, 3, 1], [1, 2, 2], [2, 2, 3], [2, 2] 最短连续子数组 [2, 2] 的长度为 2 ,所以返回 2 。 示例 2:
输入:nums = [1,2,2,3,1,4,2] 输出:6 解释: 数组的度是 3 ,因为元素 2 重复出现 3 次。 所以 [2,2,3,1,4,2] 是最短子数组,因此返回 6 。
提示:
nums.length 在 1 到 50,000 范围内。 nums[i] 是一个在 0 到 49,999 范围内的整数。
尝试完成:
/**
* @param {number[]} nums
* @return {number}
*/
var findShortestSubArray = function (nums) {};
我的思路:
- 遍历一次数组,使用一个对象 info 统计如下信息,每一个元素的频数以及最开始出现的位置和最后一次出现的位置
- 使用一个数组 maxNums 记录频数最大的元素们(可能有同时为最大频数的元素),使用 maxCount 记录但付钱的最大频数,并保持更新
得分结果: 37.50% 15.39%
经验总结: 在初始化的时候,应该是:
if (!info[_num]) {
info[_num] = {
count: 1,
start: i,
end: i,
};
}
而不是:
if (!info[_num]) {
info[_num] = {
count: 1,
start: i,
end: null,
};
}
空间得分比较低的原因可能是保存多余的数据。
3. 三个前端题目
- 为什么在 js 中 0.1+0.2!==0.3?如何使其相等?
- js 中存储数据遵循 IEEE754 双精度浮点数标准。这个规定要求使用 64bit 存储一个双精度的浮点数,其中 1bit 表示符号位,11bit 表示指数位,剩下的 52 位表示尾数,也就是说 js 中对于一个浮点数的存储是有限位的;
- 0.1 虽然在十进制中很好表示,但是在二进制中却是一个无限循环小数,因为不论 2 的几次方都不可能凑到 10;所以使用
0.1.toString(2)可以清楚的看到这个截断了的无限循环小数;同理 0.2 也是这样; - 所以两个无限小数相加并且被截断之后,其结果必然产生截断误差,所以 0.1+0.2 才不等于 0.3;
- 为了避免这种情况,应该手动设置一个最小误差,比如 1e-9:
function add(a, b) {
return parseFloat((a + b).toFixed(9));
}
// 验证
console.log(add(0.1, 0.2) === 0.3);
- 手写一个函数,实现 Object.create 方法。
Object.create 方法的作用为:
Object.create() 方法是 JavaScript 中用于创建一个新对象的方法。它的作用是以指定的原型对象作为新对象的原型,并可选择性地为新对象定义属性和方法。
Object.create(proto, [propertiesObject]) 接受两个参数:
- proto:必需,表示新对象的原型。它可以是一个对象字面量、null 或者其他已存在的对象。新对象将继承 proto 对象的属性和方法。
- propertiesObject(可选):一个可选的对象,用于定义新对象的属性和方法。该对象的每个属性都是通过属性描述符来定义的,类似于 Object.defineProperty()的第二个参数。
借用原型设计模式实现 Object.create:
function myCreate(proto, propertiesObject) {
if (Object(proto) !== proto && proto !== null) {
throw new TypeError("Object prototype may only be an Object or null");
}
// 创建一个空函数
function F() {}
// 指定此函数的原型
F.prototype = proto;
// 创建待返回实例
const obj = new F();
// 往实例对象上添加属性
if (propertiesObject !== undefined) {
Object.defineProperties(obj, propertiesObject);
}
// 返回实例对象
return obj;
}
- 手写一个函数,实现 instanceof 操作符。
- x instanceof y 的作用原理就是,在 x 的原型链上寻找 y,如果找到了就返回 true,如果找不到就返回 false;
- 根据其作用原理,其实现过程也就呼之欲出了:首先判断 x 是不是 object 类型的,如果不是直接返回 false 就可以了。如果是的话,则逐级比较 x 的原型和 y 是否相等,知道 x 原型链的尽头,也就是 null。如果此时 y 与任何一层原型都不相等,则返回 false,否则返回 true。
- 实现代码如下:
function myInstanceof(obj, cons) {
if (Object(obj) !== obj) return false;
let _p = obj.__proto__;
while (_p !== null) {
if (_p == cons.prototype) return true;
_p = _p.__proto__;
}
return false;
}
4.四句英语积累
- analyse -- examine or study in details
- We [analysed the results] of the survey and found that most of our customers are satisfied with our products.
- The new software will help us to [analyse market data].
- approach -- to deal with
- We need to find a different way of [approaching this problem].
- Jack, do you have a suggestion on how we can [approach this situation]?