js解leetcode(41)-中等

1.按权重随机选择

题目:

给定一个正整数数组 w ,其中 w[i] 代表下标 i 的权重(下标从 0 开始),请写一个函数 pickIndex ,它可以随机地获取下标 i,选取下标 i 的概率与 w[i] 成正比。

例如,对于 w = [1, 3],挑选下标 0 的概率为 1 / (1 + 3) = 0.25 (即,25%),而选取下标 1 的概率为 3 / (1 + 3) = 0.75(即,75%)。

也就是说,选取下标 i 的概率为 w[i] / sum(w) 。

思路:将数组的元素按权重拼成一个区间,每个区间的长度对应的就是它这个数本身。所以随机获取下标其实就是随机在总长度获取某个点,判断点落在哪个区间上。

每次操作时间复杂度O(1),空间复杂度O(1)

/**
 * @param {number[]} w
 */
var Solution = function (w) {
  const l = w.length;
  this.list = new Array(l).fill(0);
  this.list[0] = w[0];
  for (let i = 1; i < l; i++) {
    this.list[i] = this.list[i - 1] + w[i];
  }
  this.sum = this.list[l - 1];
};

/**
 * @return {number}
 */
Solution.prototype.pickIndex = function () {
  const r = Math.random() * this.sum;
  return this.list.findIndex((i) => i >= r);
};

/**
 * Your Solution object will be instantiated and called as such:
 * var obj = new Solution(w)
 * var param_1 = obj.pickIndex()
 */

2.扫雷游戏

题目:

让我们一起来玩扫雷游戏!

给定一个代表游戏板的二维字符矩阵。 'M' 代表一个未挖出的地雷,'E' 代表一个未挖出的空方块,'B' 代表没有相邻(上,下,左,右,和所有4个对角线)地雷的已挖出的空白方块,数字('1' 到 '8')表示有多少地雷与这块已挖出的方块相邻,'X' 则表示一个已挖出的地雷。

现在给出在所有未挖出的方块中('M'或者'E')的下一个点击位置(行和列索引),根据以下规则,返回相应位置被点击后对应的面板:

如果一个地雷('M')被挖出,游戏就结束了- 把它改为 'X'。
如果一个没有相邻地雷的空方块('E')被挖出,修改它为('B'),并且所有和其相邻的未挖出方块都应该被递归地揭露。
如果一个至少与一个地雷相邻的空方块('E')被挖出,修改它为数字('1'到'8'),表示相邻地雷的数量。
如果在此次点击中,若无更多方块可被揭露,则返回面板。

思路:一个典型的dfs。在点击时,先判断是否是雷,然后如果是空白块,判断周围地雷数量;如果周围存在地雷,那么就修改当前节点的值;如果周围没有地雷,就继续递归处理周围八个点

时间复杂度O(mn),空间复杂度O(1)

/**
 * @param {character[][]} board
 * @param {number[]} click
 * @return {character[][]}
 */
var updateBoard = function(board, click) {
  const h = board.length;
  if (!h) return board;
  const w = board[0].length;
  const [m, n] = click;
  if (board[m][n] === "M") {
    board[m][n] = "X";
    return board;
  }
  const check = (i, j) => {
    if (i < 0 || i >= h) return 0;
    if (j < 0 || j >= w) return 0;
    if (board[i][j] === "M") return 1;
    return 0;
  };
  const search = (i, j) => {
    if (i < 0 || i >= h) return;
    if (j < 0 || j >= w) return;
    if (board[i][j] === "M") return;
    if (board[i][j] === "E") {
      const c =
        check(i + 1, j) +
        check(i + 1, j - 1) +
        check(i + 1, j + 1) +
        check(i - 1, j) +
        check(i - 1, j - 1) +
        check(i - 1, j + 1) +
        check(i, j + 1) +
        check(i, j - 1);
      board[i][j] = c === 0 ? "B" : `${c}`;
      if (!c) {
        search(i + 1, j);
        search(i + 1, j - 1);
        search(i + 1, j + 1);
        search(i - 1, j);
        search(i - 1, j - 1);
        search(i - 1, j + 1);
        search(i, j + 1);
        search(i, j - 1);
      }
    }
  };
  search(m, n);
  return board;
};

3.数组中的k-diff数对

题目:

给定一个整数数组和一个整数 k,你需要在数组里找到不同的 k-diff 数对,并返回不同的 k-diff 数对 的数目。

这里将 k-diff 数对定义为一个整数对 (nums[i], nums[j]),并满足下述全部条件:

0 <= i, j < nums.length
i != j
|nums[i] - nums[j]| == k
注意,|val| 表示 val 的绝对值。

思路:先理解题目,数对不同只是数字不同,且[m,n]和[n,m]等价。

用map记录每个数字出现的次数,然后判断k是否等于0。k等于0时,数对的数量就是次数不少于2的字符数量。k不等于0,那么若i和i+k存在,则次数+1

时间复杂度O(n),空间复杂度O(n)

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var findPairs = function(nums, k) {
  if (k < 0) return 0;
  const map = new Map();
  for (const i of nums) {
    map.set(i, (map.get(i) || 0) + 1);
  }
  if (k == 0) {
    return [...map.values()].filter((i) => i >= 2).length;
  }
  let res = 0;
  for (const i of map.keys()) {
    if (map.get(i) >= 1 && map.get(i + k) >= 1) {
      res++;
    }
  }
  return res;
};

4.把二叉搜索树转化为累加树

题目:

给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。

提醒一下,二叉搜索树满足下列约束条件:

节点的左子树仅包含键 小于 节点键的节点。
节点的右子树仅包含键 大于 节点键的节点。
左右子树也必须是二叉搜索树。

思路:因为是二叉搜索树,所有大于等于当前节点的节点,都在当前节点的右侧。又因为节点的值互不相同,所以后序遍历即可

时间复杂度O(n),空间复杂度O(h)

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {TreeNode}
 */
var convertBST = function(root) {
  if (!root) return root;
  let sum = 0;
  const search = (root) => {
      if(!root)return
      search(root.right);
      sum+=root.val
      root.val=sum
      search(root.left);
  };
  search(root);
  return root;
};

5.复数乘法

题目:

给定两个表示复数的字符串。

返回表示它们乘积的字符串。注意,根据定义 i2 = -1 。

思路:先分割字符,然后对虚数部分,用parseInt截取整数,然后按照乘法运算计算即可

时间复杂度O(1),空间复杂度O(1)

/**
 * @param {string} a
 * @param {string} b
 * @return {string}
 */
var complexNumberMultiply = function(a, b) {
  let [a1, ai] = a.split("+");
  let [b1, bi] = b.split("+");
  ai = Number.parseInt(ai);
  bi = Number.parseInt(bi);
  return `${Number(a1) * Number(b1) - ai * bi}+${a1 * bi + ai * b1}i`;
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值