「这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战」
废话少说,我们来看题
剑指 Offer 55 - I. 二叉树的深度
输入一棵二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。
例如:
//给定二叉树 [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
//返回它的最大深度 3 。
思路:后续遍历,先遍历到最深(递归到末尾返回0),然后从后面一步一步比较取大的值返回,每次返回层数都加1,
var maxDepth = function (root) {
if (root == null) return 0
let left = maxDepth(root.left)
let right = maxDepth(root.right)
return 1 + Math.max(left, right)
};
然后我们来看一下,下一道题,我认为相当于这道题的升级版
110. 平衡二叉树
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。
输入: root = [3,9,20,null,null,15,7]
输出: true
var isBalanced = function (root) {
if (!root) return true
let left = counNode(root.left)
let right = counNode(root.right)
return Math.abs(left - right) <= 1 && isBalanced(root.left) && isBalanced(root.right)
};
var counNode = (root) => {
if (root == null) return 0
let left = counNode(root.left)
let right = counNode(root.right)
return 1 + Math.max(left, right)
}
------> 优化一下代码
var isBalanced = function (root) {
return balanced(root) !== -1
};
var balanced = function (node) {
if (!node) return 0
const left = balanced(node.left)
const right = balanced(node.right)
if (left === -1 || right === -1 || Math.abs(left - right) > 1) {
return -1
}
return Math.max(left, right) + 1
}
其实这俩个方式是一样的 只是判断条件写的方式不一样
35.搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
示例 1:
输入: nums = [1,3,5,6], target = 5
输出: 2
示例 2:
输入: nums = [1,3,5,6], target = 2
输出: 1
思路,target在数组中存在不,存在返回下标,不存在,target push到数组中,排序取下标值
var searchInsert = function (nums, target) {
var find = nums.findIndex(it => {
return it === target
})
if (find === -1) {
nums.push(target)
nums.sort((a, b) => a - b)
return nums.findIndex(it => {
return it === target
})
}
return find
};
13. 罗马数字转整数
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。
字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如, 罗马数字 2 写做 II ,即为两个并列的 1 。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。 X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。 给定一个罗马数字,将其转换成整数
// 思路就是找规律
// I ---> 1
// II ---> 2
// III ---> 3
// IV ---> 4
// V ---> 5
// 这道题其实是一个找规律的题 第i个字符和第i+1字符比较 i<i+1 时候i这时候就是负值
var romanToInt = function (s) {
const symbolValues = new Map();
symbolValues.set('I', 1);
symbolValues.set('V', 5);
symbolValues.set('X', 10);
symbolValues.set('L', 50);
symbolValues.set('C', 100);
symbolValues.set('D', 500);
symbolValues.set('M', 1000);
let ans = 0;
const n = s.length;
for (let i = 0; i < n; ++i) {
const value = symbolValues.get(s[i]);
if (i < n - 1 && value < symbolValues.get(s[i + 1])) {
ans -= value;
} else {
ans += value;
}
}
return ans;
};
console.log(romanToInt('IX'));
console.log(romanToInt('LVIII'));
console.log(romanToInt('MCMXCIV'));
344. 反转字符串
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
示例 1:
输入: s = ["h","e","l","l","o"]
输出: ["o","l","l","e","h"]
示例 2:
输入: s = ["H","a","n","n","a","h"]
输出: ["h","a","n","n","a","H"]
var reverseString = function(s) {
return s.reverse()
}; //这样可以通过,但是可定不是这么写的
// 思路 双指针
// 指针left初始时指向0号位置,right初始指向n-1的位置。双指针不断交换left和right位置的元素
var reverseString = function(s) {
const n = s.length;
for (let left = 0, right = n - 1; left < right; ++left, --right) {
[s[left], s[right]] = [s[right], s[left]];
}
};