每日的知识积累,包括 1 个 Ts 类型体操,两个 Leetcode 算法题,三个前端八股文题,四个英语表达积累。
1. 一个类型体操
题目
实现内置的Exclude <T, U>类型,但不能直接使用它本身。
从联合类型T中排除U的类型成员,来构造一个新的类型。
type Result = MyExclude<'a' | 'b' | 'c', 'a'> // 'b' | 'c'
分析
联合类型的本质是在同一时间可以同时表示多个类型,对于 Ts 而言,会自动遍历联合类型的每一种可能,然后将各个计算结果再联合起来输出。
尝试写出
type MyExclude<T, K> = T excludes K ? never : T;
测试用例
type Result = MyExclude<'a' | 'b' | 'c', 'a'> // 'b' | 'c'
参考答案
type MyExclude<T, U> = T extends U ? never : T;
经验总结
使用 in 操作符也可以遍历联合类型。
type Up<T> = {
[K in T]: Uppercase<K>
}[T];
type C = Up<"a" | "b" | "c">
2. 两个 Leetcode 题目
刷题的顺序参考这篇文章 LeeCode 刷题顺序
2.1 [41] 缺失的第一个正数
给你一个未排序的整数数组 `nums` ,请你找出其中没有出现的最小的正整数。
请你实现时间复杂度为 `O(n)` 并且只使用常数级别额外空间的解决方案。
**示例 1:**
输入: nums = [1,2,0]
输出: 3
解释: 范围 [1,2] 中的数字都在数组中。
**示例 2:**
输入: nums = [3,4,-1,1]
输出: 2
解释: 1 在数组中,但 2 没有。
**示例 3:**
输入: nums = [7,8,9,11,12]
输出: 1
解释: 最小的正数 1 没有出现。
**提示:**
- `1 <= nums.length <= 105`
- `-231 <= nums[i] <= 231 - 1`
尝试实现:
/**
* @param {number[]} nums
* @return {number}
*/
var firstMissingPositive = function (nums) {
const length = nums.length;
for (let i = 0; i < length; i++) {
const num = nums[i];
if (num >= 1 && num <= length) {
} else {
nums[i] = undefined;
}
}
for (let i = 0; i < length; i++) {
const num = nums[i];
if (num) {
const _i = Math.abs(num) - 1;
const _num = nums[_i];
if (typeof _num === 'undefined') nums[_i] = null;
if (_num > 0) nums[_i] = -_num;
}
}
for (let i = 0; i < length; i++) {
const num = nums[i];
if (num > 0 || num === undefined) {
return i + 1;
}
}
return length + 1;
};
我的思路:
- 第 1 次遍历:清除数组中的冗余元素;根据题意,冗余元素指的就是那些在 [1,n] 之外的元素,将其替换成 undefined, 其中 n 为输入数组的长度。
- 第 2 次遍历:现在只剩下在 [1,n] 之间的元素和 undefined 元素了, 遍历的时候,对每一个元素做如下处理:如果为数字,则取绝对值 - 1,记为 _i, 找到 _i 对应的元素,如果为正数则变成相反数,如果为 undefined 则变成 null
- 第 3 次遍历:上次遍历之后,剩下的正数或者 undefined 元素的下标值 + 1 对应不存在的正数,找到最小的这个数即可。
得分结果: 56.74% 60.53%
经验总结: 少些了一个 Math.abs
2.2 [274] H 指数
给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返回该研究者的 **h 指数。
根据维基百科上 h 指数的定义:h 代表“高引用次数” ,一名科研人员的 h 指数 是指他(她)至少发表了 h 篇论文,并且 至少 有 h 篇论文被引用次数大于等于 h 。如果 h 有多种可能的值,h 指数** 是其中最大的那个。
示例 1:
输入: citations = [3,0,6,1,5]
输出: 3
解释: 给定数组表示研究者总共有 5 篇论文,每篇论文相应的被引用了 3, 0, 6, 1, 5 次。
由于研究者有 3 篇论文每篇 至少 被引用了 3 次,其余两篇论文每篇被引用 不多于 3 次,所以她的 h 指数是 3。
示例 2:
输入: citations = [1,3,1]
输出: 1
**提示:**
- `n == citations.length`
- `1 <= n <= 5000`
- `0 <= citations[i] <= 1000`
尝试完成:
/**
* @param {number[]} citations
* @return {number}
*/
var hIndex = function (citations) {
citations.sort((a, b) => b - a);
let H = 0;
for (let i = 0; i < citations.length; i++) {
if (citations[i] >= i + 1) {
H = i + 1;
} else {
return H;
}
}
return H;
};
我的思路:
- 将输入的数组从大到小进行排列
- 排列完毕之后进行遍历,提供几个测试用例,考虑极端情况,满足即可,例如
[0] [3, 3] [1] [2,2,2,2] [3,2,1] - 以
[3,2,1]为例,我们比较当前元素和其下标值+1的大小,如果前者大于等于后者,则记录下标值+1,以其作为最新 H 指数; - H 指数从最小值 0 开始随着遍历增加,如果上述条件均不满足,则返回当前 H 指数的值。
得分结果: 49.59% 31.29%
经验总结: 自己给自己提供一些极端情况下的测试用例. 特别是边界值,需要额外考虑,这样呢能够在考虑的时候完善逻辑。
3. 三个前端题目
- 如何获取安全的 undefined 的值? 在回答这个问题之前,先看一些事实:
- 如果在浏览器中运行
const undefined = 20;则浏览器报错:Identifier 'undefined' has already been declared'; 而如果运行的是:const null = 20;浏览器报错为:unexpected token 'null'; - 也就是说对于浏览器来说 undefined 只是一个普通的 identifier 而不是 token;也就是说** undefined 是标识符而不是保留字**!
- 这一点在 node 环境中表现的更加的透彻:
let undefined = 20;
console.log(undefined); // 20
- 所以 undefined作 为标识符其值是有被篡改的风险的。在实际中一般使用
void 0 或者 void(0)表示 undefined 的含义,因为这个表达式的返回值恒为此。
- typeof NaN 的结果是什么?
先说结论,返回值为:
'number'注意这里的字符串和小写。
NaN 有几个特性,一个是不和自身相等;第二个是在 Object.is 中又是相等的;第三个是表示的语义为: not a number
- isNaN 和 Number.isNaN 的区别是什么?
- 两者表示完全不同的语义,是完全不相同的两个方法!
- isNaN(x) 是在判断
x is not a number的正确性; - 而 Number.isNaN(x) 是在判断
x is NaN的正确性;
-
对于 isNaN(x) 来说,只要 x 不是一个 num 就会返回 true,反之返回 false。(注意这里我用的是num,也就是一种独特的东西,和 number 类型不是一回事)
那么,isNaN 对于 x 的判定规则是什么呢?其实非常简单,首先 x 如果值为 NaN,则 isNaN 认为 x 不是一个 num;其次,如果 x 不为 NaN,但却是 number 类型,则 isNaN 认为 x 是一个 num;最后,倘若 x 不是 number 类型的,isNaN 会尝试将 x 转成 number 类型(这种转化不同于 Number(x) 的强制类型转化,是内部机制),而转化的结果有三种:①NaN,②报错,③其他;
如果是第一种则 isNaN 认为 x 不是 num,如果是第三种,isNaN 认为 x 是 num。什么时候会出现情况 ② 呢,如果 x 的类型是 bigint 或者 symbol 就会使 isNaN 报错。
-
对于 Number.isNaN(x) 来说,情况就简单的多了,只要 x 不是 NaN 就返回 false,否则返回 true.
这里补充js中的哪些计算会返回 NaN 来:
- NaN
- Number.NaN
- 'abc' - 1
- 0 / 0
- Math.aqrt(-1)
- Number({})
- Number('abc')
4.四句英语积累
- fill in for somebody -- 代理某人工作
- Susan is on holiday this week, so [I'm filling in for her].
- The boss asked me to [fill in for him] next week, because he has to go to an important conference.
- look into something -- try to find more info about something
- The customer didn't accept our new offer. [We're not sure why], so the boss has asked me to [look into it].
- I'm very sorry about the delay. I'll look into it immediately and get back to you within the next 2 hour.