手写算法: 合并两个有序数组

88. 合并两个有序数组open in new window

思路

现在的两个数组都已经是排序好的。

  1. 没置两个指针分别指向 nums1 和 nums2 的尾部。

  2. 指针指向值大的个先进入数组,同时对应指针前移一位。

  3. 当 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

43. 手写 Quick Sortopen in new window

本题考点:修改原数组,不返回新数组

快速排序实现思路:每轮挑选一个基准元素 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

71. two-way generatoropen in new window

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

72. Array lengthopen in new window

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

74. Typed Array lengthopen in new window

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

68. if IIopen in new window

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

79. Equal IIIopen in new window

console.log(2.0 == "2" == new Boolean(true) == "1")

从左往右执行

2.0 == '2'; // true
true == new Boolean(true); // true ==> new Boolean(true) 会通过valueOf()转化成true

string

93. stringopen in new window

let a = 'bfe.dev';
a[0] = 'c';
console.log(a);

无法通过下标对字符串进行修改。

Equal

10. Equalopen in new window

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
Last Updated:
Contributors: kk