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`;
};