leetcode Weekly Contest 144

本文解析了三道LeetCode算法题,包括IP地址转义、航班预订统计及二叉树节点删除,提供了多种解法并总结了解题思路。

rank:1313 / 3582
pass: 3/4

1108. Defanging an IP Address

Given a valid (IPv4) IP address, return a defanged version of that IP address.

A defanged IP address replaces every period “.” with “[.]”.

Example 1:

Input: address = “1.1.1.1”
Output: “1[.]1[.]1[.]1”

Example 2:

Input: address = “255.100.50.0”
Output: “255[.]100[.]50[.]0”

这题没有任何陷阱,直接调用replace就行了

1109. Corporate Flight Bookings

There are n flights, and they are labeled from 1 to n.

We have a list of flight bookings. The i-th booking bookings[i] = [i, j, k] means that we booked k seats from flights labeled i to j inclusive.

Return an array answer of length n, representing the number of seats booked on each flight in order of their label.
Example 1:

Input: bookings = [[1,2,10],[2,3,20],[2,5,25]], n = 5
Output: [10,55,45,25,25]

method 1 暴力解

对于每一个booking,从start到end依次加上k即可,但这道题很容易TLE,前两次都无法pass就是因为做了一些多余的操作浪费时间

public int[] corpFlightBookings(int[][] bookings, int n) {
        
        int[] res = new int[n];
        for(int i = 0; i < bookings.length; i++){
            int[] booking = bookings[i];
            int start = booking[0];
            int end = booking[1];
            int k = booking[2];

            int total = end-start;
            int j = 0;
            while (j <= total){
                int index = j+start-1;
                res[index] += k;
                j++;
            }
        }

        return res;
    }
method 2

method 1 中,对于每个booking,都要遍历start-end之间的数,如果end很大,那么将耗费大量的时间,因此考虑能不能将中间遍历的这些加法操作全部放到最后一次呢?
但是如果放到最后一次,就需要记录该booking中k有多大,并且从什么位置开始,从什么位置结束
因为对中间的所有数所加的k都是一样的,所以我们可以在i处便加k,最后一次遍历时res[i+1] += res[i] 即可,但怎么结束呢,我们可以在res[j-1] -= k就行,减一个k后就抵消了之前加的影响,从而不会影响到j之后的数

public int[] corpFlightBookings(int[][] bookings, int n) {
        int[] res = new int[n];
        for (int[] b : bookings) {
            res[b[0] - 1] += b[2];
            if (b[1] < n) res[b[1]] -= b[2];
        }
        for (int i = 1; i < n; ++i)
            res[i] += res[i - 1];
        return res;
    }
summary:
  1. 对大量的中间数做同一操作,考虑留到最后统一处理,减少事件复杂度
  2. 在开始处进行这个操作,在不需要这个操作的位置做一个负操作,而中间的位置只要赋值前一个即可

1110. Delete Nodes And Return Forest

Given the root of a binary tree, each node in the tree has a distinct value.

After deleting all nodes with a value in to_delete, we are left with a forest (a disjoint union of trees).

Return the roots of the trees in the remaining forest. You may return the result in any order.
在这里插入图片描述
Example 1:

Input: root = [1,2,3,4,5,6,7], to_delete = [3,5]
Output: [[1,2,null,4],[6],[7]]

method 1

递归处理,每次递归时的判断自己是否为待删节点,然后再判断左右子女是否为待删节点,如果子女为待删节点,直接将其置为null,再判断如果自己parent为null, 且自己又不是待删节点,那么就将自己加入res中

public List<TreeNode> delNodes(TreeNode root, int[] to_delete) {
        List<TreeNode> res = new ArrayList<>();
        nextIsExist(root, res, null, to_delete);
        return res;
    }

    public boolean nextIsExist(TreeNode root, List<TreeNode> res, TreeNode parent, int[] to_delete) {
        if (root == null) return false;

        int index = -1;
        for (int i = 0; i < to_delete.length; i++) {
            if (to_delete[i] == root.val){
                index = i;
                break;
            }
        }


        TreeNode nextParent = root;
        if (index > -1) nextParent = null;
        boolean leftExist = nextIsExist(root.left, res, nextParent, to_delete);
        if (leftExist) root.left = null;
        boolean rightExist = nextIsExist(root.right, res, nextParent, to_delete);
        if (rightExist) root.right = null;

        if (parent == null && index <= -1)
            res.add(root);

        if (index > -1) return true;
        else return false;
    }
method 2

dalao解法。 之前在做的时候就感觉自己的解法很strange,因为我的解法是找到被删除的点,然后从被删除的点切开,分别将被删除节点的父节点那一支和其子节点分别加入。
但我实际看其他人的做法,都是逐次将子节点添加进去,这个算法比较自然一点

  1. 当该节点是当前树的root节点,并且没有被删,那么就将其加入
  2. 如果子节点未删,那么就将子节点加入该节点
 Set<Integer> to_delete_set;
    List<TreeNode> res = new ArrayList<>();
    public List<TreeNode> delNodes(TreeNode root, int[] to_delete) {
        res = new ArrayList<>();
        to_delete_set = new HashSet<>();
        for (int i : to_delete)
            to_delete_set.add(i);
        helper(root, true);
        return res;
    }

    private TreeNode helper(TreeNode node, boolean is_root) {
        if (node == null) return null;
        boolean deleted = to_delete_set.contains(node.val);
        if (is_root && !deleted) res.add(node);
        node.left = helper(node.left, deleted);
        node.right =  helper(node.right, deleted);
        return deleted ? null : node;
    }

summary:

  1. 添加节点的方法更自然一点,不要想其他什么特殊操作

1111. Maximum Nesting Depth of Two Valid Parentheses Strings

感觉题目有点奇怪

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值