leetCode 周末之旅

117 阅读4分钟

「这是我参与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]];
    }
};