LeetCode1482. 制作 m 束花所需的最少天数 / 剑指 Offer 32 . 从上到下打印二叉树I/II/III

Posted Zephyr丶J

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode1482. 制作 m 束花所需的最少天数 / 剑指 Offer 32 . 从上到下打印二叉树I/II/III相关的知识,希望对你有一定的参考价值。

LeetCode1482. 制作 m 束花所需的最少天数

2021.5.9每日一题

题目描述

给你一个整数数组 bloomDay,以及两个整数 m 和 k 。

现需要制作 m 束花。制作花束时,需要使用花园中 相邻的 k 朵花 。

花园中有 n 朵花,第 i 朵花会在 bloomDay[i] 时盛开,恰好 可以用于 一束 花中。

请你返回从花园中摘 m 束花需要等待的最少的天数。如果不能摘到 m 束花则返回 -1 。
示例 1:

输入:bloomDay = [1,10,3,10,2], m = 3, k = 1
输出:3
解释:让我们一起观察这三天的花开过程,x 表示花开,而 _ 表示花还未开。
现在需要制作 3 束花,每束只需要 1 朵。
1 天后:[x, _, _, _, _]   // 只能制作 1 束花
2 天后:[x, _, _, _, x]   // 只能制作 2 束花
3 天后:[x, _, x, _, x]   // 可以制作 3 束花,答案为 3

示例 2:

输入:bloomDay = [1,10,3,10,2], m = 3, k = 2
输出:-1
解释:要制作 3 束花,每束需要 2 朵花,也就是一共需要 6 朵花。而花园中只有 5 朵花,无法满足制作要求,返回 -1 。

示例 3:

输入:bloomDay = [7,7,7,7,12,7,7], m = 2, k = 3
输出:12
解释:要制作 2 束花,每束需要 3 朵。
花园在 7 天后和 12 天后的情况如下:
7 天后:[x, x, x, x, _, x, x]
可以用前 3 朵盛开的花制作第一束花。但不能使用后 3 朵盛开的花,因为它们不相邻。
12 天后:[x, x, x, x, x, x, x]
显然,我们可以用不同的方式制作两束花。

示例 4:

输入:bloomDay = [1000000000,1000000000], m = 1, k = 1
输出:1000000000
解释:需要等 1000000000 天才能采到花来制作花束

示例 5:

输入:bloomDay = [1,10,2,9,3,8,4,7,5,6], m = 4, k = 2
输出:9

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-number-of-days-to-make-m-bouquets
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

二分查找的典型题型,因为所求时间具有二分性,小于这个时间不行,大于这个时间可以,所以可以用二分查找来找这个特定的时间
还有就是实现怎么判断在一个给定时间下,能形成花束,也简单

class Solution {
    int[] bloomDay;
    int m;
    int k;
    public int minDays(int[] bloomDay, int m, int k) {
        //这个咋做来着,最小最大两个边界然后二分?
        //然后判断该数能做几个花?写一下
        this.bloomDay = bloomDay;
        this.m = m;
        this.k = k;
        int l = bloomDay.length;
        if(m * k > l)
            return -1;
        int left = Integer.MAX_VALUE;
        int right = 0;
        //找最小最大值
        for(int i = 0; i < l; i++){
            left = Math.min(left, bloomDay[i]);
            right = Math.max(right, bloomDay[i]);
        }
        while(left < right){
            int mid = (right - left) / 2 + left;
            if(bloom(mid)){
                right = mid;
            }else{
                left = mid + 1;
            }
        }
        return left;
    }
    //判断能种几朵
    public boolean bloom(int mid){
        int count = 0;
        int num = 0;
        for(int i = 0; i < bloomDay.length; i++){
            if(mid >= bloomDay[i]){
                count++;
            }
            if(mid < bloomDay[i]){
                count = 0;
            }
            if(count == k){
                num++;
                count = 0;
            }
        }
        return num >= m;
    }
}

剑指 Offer 32 - I. 从上到下打印二叉树

题目描述

从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。

例如:
给定二叉树: [3,9,20,null,null,15,7],

    3
   / \\
  9  20
    /  \\
   15   7

返回:

[3,9,20,15,7]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

广度优先搜索,层序遍历,直接写

class Solution {
    public int[] levelOrder(TreeNode root) {
        //广度优先搜索吗?
        if(root == null)
            return new int[]{};
        List<Integer> list = new ArrayList<>();

        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()){
            TreeNode temp = queue.poll();
            list.add(temp.val);
            if(temp.left != null){
                queue.offer(temp.left);
            }
            if(temp.right != null){
                queue.offer(temp.right);
            }
        }
        int[] res = new int[list.size()];
        for(int i = 0; i < list.size(); i++){
            res[i] = list.get(i);
        }
        return res;
    }
}

剑指 Offer 32 - II. 从上到下打印二叉树 II

题目描述

从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。

例如:
给定二叉树: [3,9,20,null,null,15,7],

    3
   / \\
  9  20
    /  \\
   15   7

返回其层次遍历结果:

[
  [3],
  [9,20],
  [15,7]
]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-ii-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

一时间忘了怎么标记一层的结束了,想的是在每层结束加个结点来标记,惭愧惭愧

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        //怎么标记一层结束呢,对,size大小
        if(root == null)
            return new ArrayList<>();
        List<List<Integer>> res = new ArrayList<>();

        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()){
            int size = queue.size();
            List<Integer> list = new ArrayList<>();
            while(size > 0){
                TreeNode temp = queue.poll();
                list.add(temp.val);
                if(temp.left != null){
                    queue.offer(temp.left);
                }
                if(temp.right != null){
                    queue.offer(temp.right);
                }
                size--;
            }
            res.add(list);
        }
        return res;
    }
}

剑指 Offer 32 - III. 从上到下打印二叉树 III

题目描述

请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。

例如:
给定二叉树: [3,9,20,null,null,15,7],

    3
   / \\
  9  20
    /  \\
   15   7

返回其层次遍历结果:

[
  [3],
  [20,9],
  [15,7]
]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-iii-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        //判断是奇数层还是偶数层,然后打印?
        //而且这次是用栈,后入先出?栈不行,双端队列
        //如果当前层是奇数,需要从左到右打印,而下一层需要从右到左,因此该层加入队列中应该是加在队列尾部,
        //下一层弹出的时候从尾部弹出
        //如果当前层是偶数,从右到左打印了,那么加入子节点应该是从右到左加入,然后下一层反向弹出
        //咋写了
        List<List<Integer>> res = new ArrayList<>();
        if(root == null)
            return res;
        int index = 1;  //层数
        Deque<TreeNode> deque = new LinkedList<>();
        deque.offer(root);
        while(!deque.isEmpty()){
            int size = deque.size();
            List<Integer> list = new ArrayList<>();
            while(size > 0){
                if(index % 2 == 1){
                    TreeNode temp = deque.pollFirst();
                    list.add(temp.val);
                    if(temp.left != null){
                        deque.offerLast(temp.left);
                    }
                    if(temp.right != null){
                        deque.offerLast(temp.right);
                    }
                }
                if(index % 2 == 0){
                    TreeNode temp = deque.pollLast();
                    list.add(temp.val);
                    if(temp.right != null){
                        deque.offerFirst(temp.right);
                    }
                    if(temp.left != null){
                        deque.offerFirst(temp.left);
                    }
                }
                size--;
            }
            index++;
            res.add(list);
        }
        return res;
    }
}

懵懵懂懂AC了,感觉这个方法也行,但是总是感觉不够精巧,看了题解,果然,还能更巧:
层序遍历正常,输出按奇偶层数正反向即可

以上是关于LeetCode1482. 制作 m 束花所需的最少天数 / 剑指 Offer 32 . 从上到下打印二叉树I/II/III的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode1482. 制作 m 束花所需的最少天数 / 剑指 Offer 32 . 从上到下打印二叉树I/II/III

LeetCode 1482[二分法 优化] 制作m束花所需的最少天数 HERODING的LeetCode之路

1482. 制作 m 束花所需的最少天数(二分查找)

1482. 制作 m 束花所需的最少天数(二分查找)

制作m束花所需的最少天数

1482. 制作 m 束花所需的最少天数 (Java/c++二分查找)