「这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战」 110. 平衡二叉树
思路
假设当前任意节点为node;
如何判断node是平衡二叉树?
是不是左侧层级与右侧层级之差小于1?
哪如何找节点node的左侧层级和右侧层级呢?
答案:递归!
递归一定有结束条件,结束条件是什么?节点为空;
下面这句话是核心:
节点为空是不是叶子节点?将节点为空表示层级为0;叶子节点的上一级是不是整个树的倒数第二层级?
在递归回退的时候,将子节点层树+1;并且是子节点左右层级的最大值+1;
然后在递归回退的时候,对比当前节点node的左右子节点层级,层级超过1的时候,整个树为非平衡树;
代码如下,细看备注
var isBalanced = function (root) {
let sign = true //假设所有的二叉树都是平衡二叉树
function helper(node) {
//递归结束条件,节点为空,递归结束
if (node === null) return 0
// 左侧子节点层级
let left = helper(node.left)
//右侧子节点层级
let right = helper(node.right)
//计算层级差
if (Math.abs(left - right) > 1) {
//层级差超过1,非平衡二叉树
sign = false
}
//计算,取当前节点最大层级
return Math.max(left, right) + 1
}
//调用一个递归函数
helper(root)
return sign
}
剑指 Offer 55 - I. 二叉树的深度
看一眼就是递归呀;递归的时候记录当前走到第几层了;记录一下;当递归到最后一层;将记录的层级与其他节点层级对比找到最大值即可
var maxDepth = function (root) {
let result = 0
function helper(node, level) {
// 递归结束条件
if (node === null) {
//递归结束,找到当前节点所在层级与最大层级较大值保存
result = Math.max(level, result)
return
}
// 左侧层级
helper(node.left, level + 1)
//右侧层级
helper(node.right, level + 1)
}
// 递归
helper(root, 0)
return result
}
35. 搜索插入位置
在题目要求中看到这句话:使用时间复杂度为 O(log n)
的算法;请先把架子搭好
const len = 10;//数据长度
let left = 0;
let right = len;
while(left < right){
// 这里考虑一下为什么是 left + (right-left)/2 而不是直接(left+right/2)
const mid = Math.floor(left + (right-left)/2)
if(mid < target){
left = mid
}else{
right = mid
}
}
本题思路也是这样,不同点是边界处理:
var searchInsert = function (nums, target) {
let len = nums.length
let left = 0
let right = len - 1;
// left=right时要计算一次,因为需要加入的目标值可能在left与right之间
while (left <= right) {
const mid = Math.floor(left + (right - left) / 2)
if (nums[mid] === target) return mid
if (nums[mid] < target) {
left = mid + 1
} else {
right = mid - 1
}
}
return left
}
13. 罗马数字转整数
思路:找规律
先找到数据表达的规律;
对于罗马数字,如果左侧数值小于右侧数值;应该是右侧减去左侧;
比如:IV = 5-1 = 4; IX = 10-1 = 9
如果左侧数值大于右侧数值;应该是右侧加上左侧;
比如:VI = 5+1 = 6; LVIII = 50 + 5 + 3 = 58;
推广到整个罗马数字字符串中,对任意罗马数字从左到右有: 右侧数值大于当前数值,将当前数值减去;否则加上;
从左到右便利一次字符串即可转换为阿拉伯数字
var romanToInt = function (s) {
const map = { I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1000 }
const len = s.length
let result = 0
for (let i = 0; i < len; i++) {
const c = map[s[i]]
if (i < len - 1 && map[s[i]] < map[s[i + 1]]) {
result -= map[s[i]]
} else {
result += map[s[i]]
}
}
return result
}
344. 反转字符串
正常解一行代码搞定,但是题目有要求:必须原地修改输入数组并且使用 O(1) 的额外空间解决这一问题;
直接左右调换即可;数组,可以用两个指针分别只想数组头尾;依次相互调换即可
var reverseString = function (s) {
const len = s.length
let left = 0
let right = len - 1
while (left < right) {
const t = s[left]
s[left] = s[right]
s[right] = t
left++
right--
}
return s
}