欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

js解leetcode(63)-简单

程序员文章站 2022-07-13 12:54:39
...

1.魔术索引

题目:

魔术索引。 在数组A[0...n-1]中,有所谓的魔术索引,满足条件A[i] = i。给定一个有序整数数组,编写一种方法找出魔术索引,若有的话,在数组A中找出一个魔术索引,如果没有,则返回-1。若有多个魔术索引,返回索引值最小的一个。

思路:简单的话,就是依次遍历,这个就不列代码了。这里说说二分法。

因为数组是有序的,所以可以借助二分法实现。首先,我们将数组每个成员减去下标,这样只需要找到成员为0的下标。

在理想情况下,只有1个元素符合条件,那么,假设第i个元素是0,那么左侧是负数,右侧是正数,所以简单的二分法。重点是多个元素为0,

比如[0,2,2,2],处理之后变成了[0,1,0,-1].还是用二分法,不过,如果中间位置的成员是0,那么往左找。如果中间位置不为0,先往左找,如果左侧返回结果是-1,那么再往右侧。

理想情况,时间复杂度O(logn),极端情况,时间复杂度是O(n)

/**
 * @param {number[]} nums
 * @return {number}
 */
var findMagicIndex = function(nums) {
  nums = nums.map((item, index) => {
    return item - index;
  });
  const l = nums.length;
  const search = (left, right) => {
    if (!nums[left]) return left;
    const mid = ~~((left + right) / 2);
    if (left == mid) return !nums[right] ? right : -1;
    if (!nums[mid]) return search(left, mid);
    const leftV = search(left, mid - 1);
    if (leftV < 0) return search(mid + 1, right);
    return leftV;
  };
  return search(0, l - 1);
};

2.汉诺塔问题

题目:

在经典汉诺塔问题中,有 3 根柱子及 N 个不同大小的穿孔圆盘,盘子可以滑入任意一根柱子。一开始,所有盘子自上而下按升序依次套在第一根柱子上(即每一个盘子只能放在更大的盘子上面)。移动圆盘时受到以下限制:
(1) 每次只能移动一个盘子;
(2) 盘子只能从柱子顶端滑出移到下一根柱子;
(3) 盘子只能叠在比它大的盘子上。

请编写程序,用栈将所有盘子从第一根柱子移到最后一根柱子。

你需要原地修改栈。

思路:这个游戏应该很多人玩过。其实是一个递归问题。假设盘子是ABC

只有一个盘子时,直接从A到C。

两个盘子时,先将一个盘子移到B,然后将最下面的盘子移到C,然后将第一个盘子移到C。。。

有n个盘子,将n-1个盘子移到B,然后将一个盘子移到C,然后将n-1个盘子移到C

发现了吗,就是以递归。对于n>1,分为三步即可

/**
 * @param {number[]} A
 * @param {number[]} B
 * @param {number[]} C
 * @return {void} Do not return anything, modify C in-place instead.
 */
var hanota = function (A, B, C) {
  const move = (n, from, cache, to) => {
    if (n === 1) {
      to.push(from.pop());
    } else {
      move(n - 1, from, to, cache);
      move(1, from, cache, to);
      move(n - 1, cache, from, to);
    }
  };
  move(A.length, A, B, C);
};

3.颜色填充

题目:

编写函数,实现许多图片编辑软件都支持的「颜色填充」功能。

待填充的图像用二维数组 image 表示,元素为初始颜色值。初始坐标点的横坐标为 sr 纵坐标为 sc。需要填充的新颜色为 newColor 。

「周围区域」是指颜色相同且在上、下、左、右四个方向上存在相连情况的若干元素。

请用新颜色填充初始坐标点的周围区域,并返回填充后的图像。

思路:深度优先遍历即可

/**
 * @param {number[][]} image
 * @param {number} sr
 * @param {number} sc
 * @param {number} newColor
 * @return {number[][]}
 */
var floodFill = function(image, sr, sc, newColor) {
  const h = image.length;
  if (!h) return image;
  const w = image[0].length;
  const color = image[sr][sc];
  if (color == newColor) return image;
  const dfs = (i, j) => {
    if (i < 0 || i >= h) return;
    if (j < 0 || j >= w) return;
    if (image[i][j] !== color) return;
    image[i][j] = newColor;
    dfs(i - 1, j);
    dfs(i + 1, j);
    dfs(i, j - 1);
    dfs(i, j + 1);
  };
  dfs(sr, sc);
  return image;
};

4.合并排序的数组

题目:

给定两个排序后的数组 A 和 B,其中 A 的末端有足够的缓冲空间容纳 B。 编写一个方法,将 B 合并入 A 并排序。

初始化 A 和 B 的元素数量分别为 m 和 n。

思路:插入排序或者归并排序的最后一步

/**
 * @param {number[]} A
 * @param {number} m
 * @param {number[]} B
 * @param {number} n
 * @return {void} Do not return anything, modify A in-place instead.
 */
var merge = function(A, m, B, n) {
  let left = 0,
    right = 0;
    A.splice(m)
  while (right < n) {
    while (A[left] < B[right] && left < m + right) {
      left++;
    }
    A.splice(left, 0, B[right]);
    left++;
    right++;
  }
  return A;
};

5.稀疏数组搜索

题目:稀疏数组搜索。有个排好序的字符串数组,其中散布着一些空字符串,编写一种方法,找出给定字符串的位置。

思路:单次遍历没什么好说的,二分可以说一下。

如果遇到空字符串,边界往右扩张(可以理解成mid往右+,直到遇到字符串,这时才比较)

因为字符串是有序的,所以可以比较

/**
 * @param {string[]} words
 * @param {string} s
 * @return {number}
 */
var findString = function(words, s) {
    let left = 0
    let right = words.length - 1
    while (left <= right) {
        let mid_bak = mid = (left + right) >> 1
        // 重点:对空字符串的处理,除了mid右移以外,还要处理右侧超出边界的问题
        while (mid <= right && !words[mid]) {
            mid++;
        }
        // console.log(left, mid, right)
        // 右侧超出边界后压缩边界
        if (mid > right) {  // 若mid超出右边界(即为右边界+1), 说明mid至right处都为空字符串
            right = mid_bak - 1; // 压缩右边界至mid_bak的位置
            continue;   // 进行下一次循环
        }
        if (words[mid] > s) {
            right = mid - 1
        } else if (words[mid] < s) {
            left = mid + 1
        } else {
            return mid
        }
    }

    return -1
};