1.单词接龙
题目:
给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则:
每次转换只能改变一个字母。
转换过程中的中间单词必须是字典中的单词。
说明:
如果不存在这样的转换序列,返回 0。
所有单词具有相同的长度。
所有单词只由小写字母组成。
字典中不存在重复的单词。
你可以假设 beginWord 和 endWord 是非空的,且二者不相同。
思路:首先,我们需要一个辅助函数去比较两个单词的不同字符的数量。。、然后,从起始单词开始,我们依次取找下一个和它相差一个字符的单词,直到找到目标单词
/**
* @param {string} beginWord
* @param {string} endWord
* @param {string[]} wordList
* @return {number}
*/
var ladderLength = function(beginWord, endWord, wordList) {
if (!wordList.includes(endWord)) return 0;
if (beginWord.length < 2) return 2;
const wordSet = new Set(wordList);
const findDis = (s1, s2) => {
let count = 0;
for (let i = 0, l = s1.length; i < l; i++) {
if (s1[i] !== s2[i]) count++;
}
return count;
};
let stack = [[beginWord, 1]];
while (stack.length) {
let [word, transNumber] = stack.pop();
if (word === endWord) return transNumber;
for (let str of wordSet) {
if (findDis(word, str) === 1) {
stack.unshift([str, transNumber + 1]);
wordSet.delete(str);
}
}
}
return 0;
};
2.求根到叶子节点数字之和
题目:
给定一个二叉树,它的每个结点都存放一个 0-9 的数字,每条从根到叶子节点的路径都代表一个数字。
例如,从根到叶子节点路径 1->2->3 代表数字 123。
计算从根到叶子节点生成的所有数字之和。
说明: 叶子节点是指没有子节点的节点。
思路:遍历,遍历节点的时候记录之前的父节点的值即可,遇到叶子节点就累加
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @return {number}
*/
var sumNumbers = function(root) {
if (!root) return 0;
const stack = [
{
node: root,
val: "",
},
];
let res = 0;
while (stack.length) {
const item = stack.shift();
const v = item.val + item.node.val;
if (!item.node.left && !item.node.right) {
res+= +v;
continue;
}
if (item.node.left) {
stack.push({
node: item.node.left,
val: v,
});
}
if (item.node.right) {
stack.push({
node: item.node.right,
val: v,
});
}
}
return res;
};
3.被围绕的区域
题目:
给定一个二维的矩阵,包含 'X'
和 'O'
(字母 O)。
找到所有被 'X'
围绕的区域,并将这些区域里所有的 'O'
用 'X'
填充。
思路:标记法。从四个边缘开始找,遇到字母O就深度遍历,并把遇到的O标记。然后遍历矩阵,遇到标记的O就还原,没标记的O就变为X
/**
* @param {character[][]} board
* @return {void} Do not return anything, modify board in-place instead.
*/
var solve = function(board) {
const m = board.length;
if (m == 0) return; // [] 情况的特判
const n = board[0].length;
const dfs = (i, j) => {
if (i < 0 || i == m || j < 0 || j == n) return; // 越界了
if (board[i][j] == 'O') { // 遇到O,染为NO
board[i][j] = 'NO';
dfs(i + 1, j); // 对四个方向的邻居进行dfs
dfs(i - 1, j);
dfs(i, j + 1);
dfs(i, j - 1);
}
};
for (let i = 0; i < m; i++) {
if (board[i][0] == 'O') dfs(i, 0); // 从最外层的O,开始DFS
if (board[i][n-1] == 'O') dfs(i, n-1); // 从最外层的O,开始DFS
}
for (let j = 1; j < n - 1; j++) {
if (board[0][j] == 'O') dfs(0, j); // 从最外层的O,开始DFS
if (board[m-1][j] == 'O') dfs(m-1, j); // 从最外层的O,开始DFS
}
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (board[i][j] === 'NO') board[i][j] = 'O'; // 恢复为O
else if (board[i][j] === 'O') board[i][j] = 'X'; // O变为X
}
}
};
4.分割回文串
题目:
给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。
返回 s 所有可能的分割方案。
/**
* @param {string} s
* @return {string[][]}
*/
var partition = function(s) {
let res = [];
if (s.length === 0) {
return res;
}
findPalidrome(0, s, res, []);
return res;
};
function findPalidrome(start, s, res, curArr) {
if (start === s.length) {
res.push(curArr);
return;
}
for (let i = start; i < s.length; i++) {
let subStr = s.slice(start, i + 1);
if (subStr && isPal(subStr)) {
findPalidrome(i + 1, s, res, [...curArr, subStr]);
}
}
}
function isPal(str) {
let len = Math.floor(str.length / 2);
if (len === 0) {
return true;
}
let add = str.length % 2 === 0 ? 0 : 1;
let subStr = str.slice(0, len);
for (let i = 0; i < len; i++) {
if (subStr[len - i - 1] !== str[len + add + i]) {
return false;
}
}
return true;
}
5.克隆图
题目:
给你无向 连通 图中一个节点的引用,请你返回该图的 深拷贝(克隆)。
图中的每个节点都包含它的值 val(int) 和其邻居的列表(list[Node])。
class Node {
public int val;
public List<Node> neighbors;
}
测试用例格式:
简单起见,每个节点的值都和它的索引相同。例如,第一个节点值为 1(val = 1),第二个节点值为 2(val = 2),以此类推。该图在测试用例中使用邻接列表表示。
邻接列表 是用于表示有限图的无序列表的集合。每个列表都描述了图中节点的邻居集。
给定节点将始终是图中的第一个节点(值为 1)。你必须将 给定节点的拷贝 作为对克隆图的引用返回。
思路:从第一个节点开始遍历,然后用map记录每一个新节点,遇到需要这些节点的地方直接返回引用,用set记录遍历过的节点,防止死循环
/**
* // Definition for a Node.
* function Node(val, neighbors) {
* this.val = val === undefined ? 0 : val;
* this.neighbors = neighbors === undefined ? [] : neighbors;
* };
*/
/**
* @param {Node} node
* @return {Node}
*/
var cloneGraph = function(node) {
if(!node)return node
const map = new Map();
const set = new Set();
const stack = [node];
let head;
while (stack.length) {
const item = stack.pop();
if (set.has(item.val)) continue;
const newItem = findChild(item, set, map);
head = head || newItem;
newItem.neighbors = newItem.neighbors.map((child) => {
return findChild(child, set, map);
});
set.add(newItem.val)
stack.push(...newItem.neighbors);
}
function findChild(child, set, map) {
if (map.has(child.val)) return map.get(child.val);
const node = new Node(child.val, child.neighbors);
map.set(child.val, node);
return node;
}
return head;
};