1.二叉树的右视图
题目:给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
思路:可以用层序遍历的方式,将树转成二维数组,然后取每层的最后一个节点
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @return {number[]}
*/
var rightSideView = function(root) {
const res = [];
if (!root) return res;
const stack = [root];
while (stack.length) {
res.push(stack.map((i) => i.val));
const temp = [];
for (const item of stack) {
if (item.left) {
temp.push(item.left);
}
if (item.right) {
temp.push(item.right);
}
}
stack.splice(0, Infinity, ...temp);
}
return res.map((item) => item.pop());
};
也可以在遍历节点的时候记录当前节点的层数,然后将结果放入一个数组里,将层数作为下标
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @return {number[]}
*/
var rightSideView = function(root) {
const res = [];
const search = (root, level) => {
if (!root) return;
if (res[level] === undefined) {
res[level] = root.val;
}
search(root.right, level + 1);
search(root.left, level + 1);
};
search(root, 0);
return res;
};
2.岛屿数量
题目:
给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围
思路:深度优先遍历,然后将遍历过的岛屿修改为其他字符,这样遍历的次数就是岛屿的数量了
/**
* @param {character[][]} grid
* @return {number}
*/
var numIslands = function(grid) {
const h = grid.length;
if (!h) return 0;
const w = grid[0].length;
let count = 0;
const dep = (i, j) => {
if (i >= h || i < 0) return;
if (j >= w || j < 0) return;
if (grid[i][j] !== "1") return;
grid[i][j] = "*";
dep(i, j + 1);
dep(i, j - 1);
dep(i + 1, j);
dep(i - 1, j);
};
for (let i = 0; i < h; i++) {
for (let j = 0; j < w; j++) {
if (grid[i][j] == "1") {
count++;
dep(i, j);
}
}
}
return count;
};
3.数字范围按位与
题目:给定范围 [m, n],其中 0 <= m <= n <= 2147483647,返回此范围内所有数字的按位与(包含 m, n 两端点)。
思路:先排除特殊清理。如果两个数字的二进制字符串长度不一样,那么结果肯定是0
/**
* @param {number} m
* @param {number} n
* @return {number}
*/
var rangeBitwiseAnd = function(m, n) {
if(m.toString(2).length != n.toString(2).length) return 0
var res = m;
for(var i=m+1;i<=n;i++){
res &= i;
}
return res
};
4.课程表
题目:
你这个学期必须选修 numCourse 门课程,记为 0 到 numCourse-1 。
在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们:[0,1]
给定课程总量以及它们的先决条件,请你判断是否可能完成所有课程的学习?
思路:记录某个课程和它的前置课程,然后检查前置课程的前置课程是否有该课程(就是形成了环),如果没有说明可以修完,有环说明不能修完
/**
* @param {number} numCourses
* @param {number[][]} prerequisites
* @return {boolean}
*/
var canFinish = function(numCourses, prerequisites) {
const map = new Map();
const isCircle = (cur, pre) => {
const stack = [cur];
while (stack.length) {
const item = stack.pop();
if (map.get(item)) {
if (map.get(item).includes(pre)) return true;
stack.push(...map.get(item));
}
}
return false;
};
for (const [cur, pre] of prerequisites) {
if (isCircle(cur, pre)) return false;
if (map.get(pre)) {
map.get(pre).push(cur);
} else {
map.set(pre, [cur]);
}
}
return true;
}
也可以用拓扑排序。记录所有的课程,以及它们的前置课程的数量。某个课程的前置课程数量为0,说明可以休这门课,然后再解锁以这门课作为前置课程的课
/**
* @param {number} numCourses
* @param {number[][]} prerequisites
* @return {boolean}
*/
var canFinish = function(numCourses, prerequisites) {
const inDegree = new Array(numCourses).fill(0); // 入度数组
const map = {}; // 邻接表
for (let i = 0; i < prerequisites.length; i++) {
const [cur, pre] = prerequisites[i];
inDegree[cur]++; // 求课的初始入度值
if (map[pre]) {
// 当前课已经存在于邻接表
map[pre].push(cur); // 添加依赖它的后续课
} else {
// 当前课不存在于邻接表
map[pre] = [cur];
}
}
const queue = [];
for (let i = 0; i < inDegree.length; i++) {
// 所有入度为0的课入列
if (inDegree[i] == 0) queue.push(i);
}
let count = 0;
while (queue.length) {
const selected = queue.shift(); // 当前选的课,出列
count++; // 选课数+1
const toEnQueue = map[selected]||[]; // 获取这门课对应的后续课
for (const item of toEnQueue) {
inDegree[item]--;
if (!inDegree[item]) {
queue.push(item);
}
}
}
return count == numCourses; // 选了的课等于总课数,true,否则false
};
5.实现Trie(前缀树)
题目:实现一个 Trie (前缀树),包含 insert
, search
, 和 startsWith
这三个操作。
思路:用一个嵌套的对象记录单词,每个字符作为一级,并且记录末尾的字符
/**
* Initialize your data structure here.
*/
var Trie = function() {
this.root = {}
};
/**
* Inserts a word into the trie.
* @param {string} word
* @return {void}
*/
Trie.prototype.insert = function(word) {
let node = this.root
for (const c of word) {
if (!node[c]) node[c] = {}
node = node[c]
}
node.isWord = true
};
/**
* Returns if the word is in the trie.
* @param {string} word
* @return {boolean}
*/
Trie.prototype.search = function(word) {
const node = this.traverse(word)
return !!node && !!node.isWord
};
/**
* Returns if there is any word in the trie that starts with the given prefix.
* @param {string} prefix
* @return {boolean}
*/
Trie.prototype.startsWith = function(prefix) {
return !!this.traverse(prefix)
};
Trie.prototype.traverse=function(word) {
let node = this.root
for (const c of word) {
node = node[c]
if (!node) return null
}
return node
}