二叉树 · DFS
94 二叉树的中序遍历
递归版:辅助函数 + 递归出口
var inorderTraversal = function(root) {
let ans = []
const helper = (root) => {
if (!root) return
helper(root.left)
ans.push(root.val)
helper(root.right)
}
helper(root)
return ans
}
98 验证二叉搜索树
上下界递归(比中序遍历更本质)
题干:判断二叉树是否是合法的 BST(左子树所有值 < 根 < 右子树所有值)。
- 每个节点必须满足
low < node.val < high - 往左走 high 缩小为当前值,往右走 low 放大为当前值
var isValidBST = function (root) {
const dfs = (node, low, high) => {
if (!node) return true
const v = node.val
if (v <= low || v >= high) return false
return dfs(node.left, low, v) && dfs(node.right, v, high)
}
return dfs(root, -Infinity, Infinity)
}
中序遍历法
var isValidBST = function (root) {
let ansArr = []
let flag = true
const helper = (node) => {
if (!node) return
helper(node.left)
if (!ansArr.length) {
ansArr.push(node.val)
} else if (ansArr[ansArr.length - 1] < node.val) {
ansArr.push(node.val)
} else {
flag = false; return
}
helper(node.right)
}
helper(root)
return flag
}
101 对称二叉树
递归比较:左左=右右,左右=右左
var isSymmetric = function (root) {
if (!root) return true
const judgeSym = (root1, root2) => {
if (!root1 && !root2) return true
if (!root1 || !root2) return false
return root1.val === root2.val
&& judgeSym(root1.left, root2.right)
&& judgeSym(root1.right, root2.left)
}
return judgeSym(root.left, root.right)
}
200 岛屿数量
DFS 染色:遇到 1 就 count++,然后把整个岛 DFS 置 0
题干:二维网格中 '1' 是陆地 '0' 是水,计算岛屿数量。
- 遍历到 '1' 就 count++,然后 DFS 把连通的 '1' 全置为 '0'
- 不需要额外数组记录访问路径
var numIslands = function (grid) {
let m = grid.length, n = grid[0].length
let count = 0
const dfsRender = (i, j) => {
if (i < 0 || i >= m || j < 0 || j >= n) return
if (parseInt(grid[i][j]) === 0) return
grid[i][j] = '0' // 遍历后置为 0
dfsRender(i + 1, j)
dfsRender(i - 1, j)
dfsRender(i, j + 1)
dfsRender(i, j - 1)
}
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (parseInt(grid[i][j]) === 1) {
count++
dfsRender(i, j)
}
}
}
return count
}
139 单词拆分
动态规划:dp[i] = 前 i 个字符能否被拆分
题干:字符串 s 能否被拆分为字典中的单词组合。经典 DP,很多题有它的影子。
dp[i]= 长度为 i 的子串能否拆分- 双重循环:j 从 0 到 i,如果
dp[j]=true且s[j..i]在字典中 →dp[i]=true
var wordBreak = function (s, wordDict) {
const n = s.length
const dp = new Array(n + 1).fill(false)
const set = new Set(wordDict)
dp[0] = true
// 注意 i <= n,因为 i 是分界点,需要比长度大 1
for (let i = 1; i <= n; i++) {
for (let j = 0; j < i; j++) {
if (!dp[j]) continue
let trimWord = s.slice(j, i)
if (set.has(trimWord)) {
dp[i] = true
break
}
}
}
return dp[n]
}