LeetCode Top100之543,581,617题

543. 二叉树的直径
① 题目描述

中文描述:https://leetcode-cn.com/problems/diameter-of-binary-tree/

② 二叉树求深度的变种
  • 之前,求二叉树的深度是从根节点开始,递归得到其左子树、右子树的深度,然后选其中的较大者加1,便是二叉树的深度。其实,就是二叉树的层次或高度
  • 现在求二叉树的直径,可能是包含根节点,也可能在其左子树或右子树中找到直径。而且直径不是节点个数,而是节点之间的边数,即节点个数-1
  • 如果通过求二叉树的深度,获得的左右子树的深度,直接相加便是包含根节点的树的直径。
  • 代码如下,运行时间9ms
public int diameterOfBinaryTree(TreeNode root) {
     if (root == null) {
         return 0;
     }
     int left1 = 0, left2 = 0, right1 = 0, right2 = 0;
     left1 = maxDepth(root.left);
     right1 = maxDepth(root.right);
     if (root.left != null) {// 包含左孩子的最大直径
         left2 = diameterOfBinaryTree(root.left);
     }
     if (root.right != null) {// 包含右孩子的最大直径
         right2 = diameterOfBinaryTree(root.right);
     }
     return Math.max(Math.max(left1 + right1, left2), right2);
 }
 public int maxDepth(TreeNode root) {
     if (root == null) {
         return 0;
     }
     return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
     
 }
581. 最短无序连续子数组
① 题目描述

中文题目:https://leetcode-cn.com/problems/shortest-unsorted-continuous-subarray/

② 自己的想法:从前往后找start,从后往前找end
  • 如果,从当前数开始直到数组末尾,如果后面的数都大于等于当前数,则继续往后查找start。否则,当前数便是无序数组的起始数。
  • 如果,从当前数开始直到数组头部,如果前面的数都小于等于当前数,则继续往前查找end。否则,当前数便是无序数组的最后一个数。
  • 代码如下,运行时间73ms:
public int findUnsortedSubarray(int[] nums) {
    int start = 0;
    int end = -1;// 避免整个数组没有无序子数组
    for (int i = 0; i < nums.length - 1; i++) {
        boolean flag = false;
        for (int j = i + 1; j < nums.length; j++) {
            if (nums[j] < nums[i]) {
                start = i;
                flag = true;
                break;
            }
        }
        if (flag) {// 第一次出现非升序的下标便是整个需要排序的子数组的start,找到便退出
            break;
        }
    }
    for (int i = nums.length - 1; i > 0; i--) {
        boolean flag = false;
        for (int j = i - 1; j >= 0; j--) {
            if (nums[j] > nums[i]) {// 第一次出现非降序的下标便是整个需要排序的子数组的end,找到便退出
                end = i;
                flag = true;
                break;
            }
        }
        if (flag) {
            break;
        }
    }
    return end - start + 1;
}
③ 先排序再比较
  • 将数组复制到新的数组中,对新数组进行排序后,从前往后比较,找出start;从后往前比较找出end。
  • 如果start和end都为0,说明原始数组是全局有序的;否则,返回end - start + 1
  • 代码如下,运行时间7ms
public int findUnsortedSubarray(int[] nums) {
    int[] copy = new int[nums.length];
    int start = 0;
    int end = 0;
    System.arraycopy(nums, 0, copy, 0, nums.length);
    Arrays.sort(copy);
    for (int i = 0; i < nums.length; i++) {
        if (copy[i] != nums[i]) {
            start = i;
            break;
        }
    }
    for (int i = nums.length - 1; i >= 0; i--) {
        if (copy[i] != nums[i]) {
            end = i;
            break;
        }
    }
    return (end == 0 && start == 0) ? 0 : (end - start + 1);
}
617. 合并二叉树
① 题目描述

中文题目:https://leetcode-cn.com/problems/merge-two-binary-trees/

② 合并到新的二叉树上
  • 除非root1root2都为null,每次都创建新的节点,并且val要么为0 + t2.val,要么为t1.val + t2.val,要么为t1.val + 0
  • 递归构造新节点的左右孩子,返回新节点。
  • 代码如下,运行时间1ms
public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
     if (t1 == null && t2 == null) {
         return null;
     }
     TreeNode t3 = new TreeNode((t1 == null ? 0 : t1.val) + (t2 == null ? 0 : t2.val));
     t3.left = mergeTrees(t1 == null ? null : t1.left, t2 == null ? null : t2.left);
     t3.right = mergeTrees(t1 == null ? null : t1.right, t2 == null ? null : t2.right);
     return t3;
 }
③ 自己想到的,但未成功实现:合并到t1上
  • 合并过程中,将会有四种情况:
    t1 = null 并且 t2 = null,直接返回null
    ② 只有t1 = null,直接返回t2,将t2整体直接挂到root节点上;
    ③ 只有t2 = null,直接返回t1,将t1整体直接挂到root节点上;
    ④ 都不为null,更新t1的val,并继续查找当前节点的左子树和右子树。
  • 其中①和②可以合并为,返回t2。
  • 代码如下,运行时间0ms
public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
    if ((t1 == null && t2 == null) || t1 == null) {
        return t2;
    }
    if (t2 == null) {
        return t1;
    }
    t1.val = t1.val + t2.val;
    t1.left = mergeTrees(t1.left, t2.left);
    t1.right = mergeTrees(t1.right, t2.right);
    return t1;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值