各类题的解决方案
话不多说,系统整理下解题的一些算法和解决方案
二叉树
二叉树大多使用递归的方式左右两个元素向下递归。比如:
计算二叉树最大深度
var maxDepth = function (root) {
if (root == null) return 0
return 1 + Math.max(maxDepth(root.left), maxDepth(root.right))
};
将二叉树以二维数组形式表现
var levelOrder = function(root) {
let ans = []
helper(root, ans, 0)
return ans
};
function helper(node, ans, i){
if (node == null) return
if (i == ans.length) ans.push([])
ans[i].push(node.val)
helper(node.left, ans, i + 1)
helper(node.right, ans, i + 1)
}
都是通过递归方式逐层向下去查找二叉树数据。
可能性问题
这类题一般是告诉你一组数据,然后求出可能性、最小值或最大值。比如:
给定几种面额的硬币和一个总额,使用最少的硬币凑成这个总额。
var coinChange = function (coins, amount) {
let max = amount + 1
let dp = new Array(amount + 1)
dp.fill(max)
dp[0] = 0
for (let i = 1; i < max; i++) {
for (let j = 0; j < coins.length; j++) {
if (coins[j] <= i) {
dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1)
}
}
}
return dp[amount] > amount ? -1 : dp[amount]
};
使用了动态规划(DP),将从 0 到目标额度所需的最小硬币数都列出来。
求出从矩阵左上角走到右下角,且只能向右向下移动,一共有多少种可能性。
var uniquePaths = function (m, n) {
const pos = new Array(m)
for (let i = 0; i < m; i++) {
pos[i] = new Array(n)
}
for (let i = 0; i < n; i++) {
pos[0][i] = 1
}
for (let i = 0; i < m; i++) {
pos[i][0] = 1
}
for (let i = 1; i < m; i++) {
for (let j = 1; j < n; j++) {
pos[i][j] = pos[i - 1][j] + pos[i][j - 1]
}
}
return pos[m - 1][n - 1]
};
这题就是使用了动态规划逐步列出每一格的可能性,最后返回右下角的可能性。
获取给定数组连续元素累加最大值
var maxSubArray = function (nums) {
let count = nums[0], maxCount = nums[0]
for (let i = 1; i < nums.length; i++) {
count = Math.max(count + nums[i], nums[i])
maxCount = Math.max(maxCount, count)
}
return maxCount
};
上面这题通过不断对比最大值来保留并返回最大值。
其实,可能性问题使用动态规划要比使用 DFS、BFS 算法更加简单而容易理解。(我使用 DFS 经常报 TLE)
查找
一般遇到的查找问题,如查找某个值一般会用到一下方法:
- 排序算法(排序便于查找)
- 二分查找
- 索引移动查找(这个方法名自己想的,大概就这个意思~)
查找横向和纵向都递增的二维矩阵中的某个值
var searchMatrix = function (matrix, target) {
if (matrix.length == 0) return false
let row = 0, col = matrix[0].length - 1
while (true) {
if (matrix[row][col] > target && col > 0) {
col--
} else if (matrix[row][col] < target && row < matrix.length - 1) {
row++
} else if (matrix[row][col] == target) {
return true
} else {
break
}
}
return false
};
先将位置定位在右上角,通过改变位置坐标来找到目标值。使用了索引移动查找法来找到结果。
找到数组中最左边和最右边的某个数字所在位置
var searchRange = function (nums, target) {
let targetIndex = binarySearch(nums, target, 0, nums.length - 1)
if (targetIndex == -1) return [-1, -1]
let l = targetIndex, r = targetIndex