手写算法: 合并两个有序数组
思路
现在的两个数组都已经是排序好的。
没置两个指针分别指向 nums1 和 nums2 的尾部。
指针指向值大的个先进入数组,同时对应指针前移一位。
当 num2 数组已经遍历完成时,无论 num1 的指针是否遍历结束,此时 num1 已经是排序好的数组,直接返回即可。
var merge = function(nums1, m, nums2, n) {
let len1 = m - 1,
len2 = n - 1,
len = m + n - 1;
while (len2 >= 0) {
nums1[len--] = nums1[len1] > nums2[len2] ? nums1[len1--] : nums2[len2--];
}
return nums1;
};
// 优化完后
var merge = function(nums1, m, nums2, n) {
while (n > 0) {
nums1[m + n - 1] = nums1[m - 1] > nums2[n - 1] ? nums1[--m] : nums2[--n];
}
return nums1;
};
手写题: 手写 Quick Sort
本题考点:修改原数组,不返回新数组
快速排序实现思路:每轮挑选一个基准元素 pivot,把比它大的移动到一边,比它小的移动到另一边,从而把数组拆解成两个部分,这也叫做分治法。 基准元素最间单的就是拿数组的第一个元素,也可以随机选择一个元素作为基准元素。
function quickSort(arr, left = 0, right = arr.length - 1) {
if (left > right) return;
const index = partition(arr, left, right);
quickSort(arr, left, index - 1);
quickSort(arr, index + 1, right);
}
function partition(arr, left, right) {
const pivot = left++;
while (left <= right) {
if (arr[left] <= arr[pivot]) {
left++;
} else {
[arr[left], arr[right]] = [arr[right], arr[left]];
right--;
}
}
[arr[right], arr[pivot]] = [arr[pivot], arr[right]];
return right;
}
tips
✅ :arr[right] 最后跟 arr[pivot] 交换位置就是为了将最小或者最大移动到数组的两端。
JS 简答题
two-way generator
function* gen() {
yield 2 * (yield 100);
}
const generator = gen();
console.log(generator.next().value);
console.log(generator.next(1).value);
console.log(generator.next(1).value);
解析
可以看作是(2 * (yield 100)) 先执行里面的再执行外面的
// 执行里面的,传入100进去,
// {value: 100, done: false} done还没完成
console.log(generator.next().value); // 100
// 传入1代替了【yield 100】这一块,执行yield 2 * 1,{value: 2, done: false}
console.log(generator.next(1).value); // 2
// 上一步已经执行完yield了,此时{value: undefined, done: true}
console.log(generator.next(1).value);
🤔 再做一题
function* foo(x) {
var y = 2 * (yield x + 1);
var z = yield y / 3;
return x + y + z;
}
var it = foo(5);
console.log(it.next()); // 5传进来,5 + 1 = 6
console.log(it.next(3)); // 3 把(yield x + 1) 替换掉,2 * 3 = 6,此时y等于6,y/3得到2
console.log(it.next(88)); // 88 把 yield y / 3 和之前的所有都替换掉,此时z等于88,所以x+y+z 等于 5+6+88 = 99
console.log(it.next());
Array length
class MyArray extends Array {
get length() {
return 3;
}
}
const arr1 = new MyArray(10);
console.log(arr1.length);
const arr2 = new Array(10);
console.log(arr2.length);
解析
两个都是 10
🤔 为什么呢?
length 是 Array 的实例属性。子类不能修改该属性。
Typed Array length
class MyArray extends Uint8Array {
get length() {
return 3;
}
}
const arr1 = new MyArray(10);
console.log(arr1.length);
const arr2 = new Uint8Array(10);
console.log(arr2.length);
解析
Unit8Array数组类型表示一个 8 位无符号整型数组。 这个上一题很相似,但不同之处在于我们是从使用 ArrayBuffer 的 Uint8Array 类型数组扩展而来的,在这个情况下,子类构造函数可以能会覆盖它。
if II
if (
function foo() {
console.log('BFE');
}
) {
console.log('dev');
}
foo();
解析
"dev" ==> if 将语句转换成布尔值,再看是 true 还是 false。Boolean(function foo() {})为真,所以会执行里面的 log
Error ==> ReferenceError: foo is not defined,因为是函数表达式,不是函数声明,所以 foo 没有被提升,所以没有定义 foo,调用就会报错
Equal III
console.log(2.0 == "2" == new Boolean(true) == "1")
从左往右执行
2.0 == '2'; // true
true == new Boolean(true); // true ==> new Boolean(true) 会通过valueOf()转化成true
string
let a = 'bfe.dev';
a[0] = 'c';
console.log(a);
无法通过下标对字符串进行修改。
Equal
console.log(0 == false);
console.log('' == false);
console.log([] == false);
console.log(undefined == false);
console.log(null == false);
console.log('1' == true);
console.log(1n == true);
console.log(' 1 ' == true);
解析
1n 数据类型为 Bigint , 可以看作是 1。用全等运算符对比的话,那么就是 false
console.log(1n == true); // true
console.log(1n === true); // false
console.log(1n == 1); // true
console.log(1n === 1); // false