LeetCode664. 奇怪的打印机 / 剑指 Offer 55 - I. 二叉树的深度 / 剑指 Offer 55 - II. 平衡二叉树

Posted Zephyr丶J

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode664. 奇怪的打印机 / 剑指 Offer 55 - I. 二叉树的深度 / 剑指 Offer 55 - II. 平衡二叉树相关的知识,希望对你有一定的参考价值。

664. 奇怪的打印机

2021.5.24 每日一题,又开始新的一周了

题目描述

有台奇怪的打印机有以下两个特殊要求:

打印机每次只能打印由 同一个字符 组成的序列。
每次可以在任意起始和结束位置打印新字符,并且会覆盖掉原来已有的字符。
给你一个字符串 s ,你的任务是计算这个打印机打印它需要的最少打印次数。

 
示例 1:

输入:s = "aaabbb"
输出:2
解释:首先打印 "aaa" 然后打印 "bbb"。
示例 2:

输入:s = "aba"
输出:2
解释:首先打印 "aaa" 然后在第二个位置打印 "b" 覆盖掉原来的字符 'a'。

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

思路

这个动态规划没想出来,刚开始也没往这边想,想的是有什么技巧(每次都打印整个剩余长度的字符串)

定义dp[i][j]表示打印i到j最少需要多少次
如果s[i] = s[j], dp[i][j] = min(dp[i + 1][j], dp[i][j - 1]),打印i的同时打印j,不需要额外再打印一次
如果不相同,那么两边需要分别打印,也就是将区间分成两部分[i,k][k + 1, j],然后计算各个k的最小值
那遍历顺序呢,dp[i][j]和dp[i+][j] 和dp[i][j-]有关,因此i从大到小,j从小到大

class Solution {
    public int strangePrinter(String s) {
        //怎么看不懂这个题啊,啥意思,大概明白了,就是每次打印字符的数量是随意的
        //不过只能从开始和结尾打印,并且打印只能由同一个字符组成
        //感觉这题说的也不严谨,如果打印了与开头末尾相同的字符,那么下次打印是从下一个字符开始还是覆盖以后的地方开始
        //应该是覆盖到哪就从哪里开始
        
        //动态规划,dp表示打印i到j最少需要多少次
        int l = s.length();

        int[][] dp = new int[l][l];

        //初始化
        for(int i = 0; i < l; i++){
            dp[i][i] = 1;
        }
        char[] ss = s.toCharArray();
        //如果s[i] = s[j], dp[i][j] = min(dp[i + 1][j], dp[i][j - 1]),打印i的同时打印j
        //如果不相同,那么两边需要分别打印,也就是将区间分成两部分[i,k][k + 1, j],然后计算各个k的最小值

        //那遍历顺序呢,dp[i][j]和dp[i+][j] 和dp[i][j-]有关,因此i从大到小,j从小到大
        for(int i = l - 2; i >= 0; i--){
            for(int j = i + 1; j < l; j++){
                if(ss[i] == ss[j]){
                    dp[i][j] = Math.min(dp[i + 1][j], dp[i][j - 1]);
                }else{
                    dp[i][j] = 100;		//字符串最长100
                    for(int k = i; k < j; k++){
                        dp[i][j] = Math.min(dp[i][j], dp[i][k] + dp[k + 1][j]);
                    }
                }
            }   
        }
        return dp[0][l - 1];
    }
}

剑指 Offer 55 - I. 二叉树的深度

题目描述

输入一棵二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。

例如:

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

    3
   / \\
  9  20
    /  \\
   15   7
返回它的最大深度 3 。

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

思路

层序遍历

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int maxDepth(TreeNode root) {
        //层序遍历吧
        int k = 0;
        Queue<TreeNode> queue = new LinkedList<>();
        if(root != null)
            queue.offer(root);
        while(!queue.isEmpty()){
            int size = queue.size();
            while(size > 0){
                TreeNode node = queue.poll();
                if(node.left != null)
                    queue.offer(node.left);
                if(node.right != null)
                    queue.offer(node.right);
                size--;
            }
            k++;
        }
        return k;
    }
}

递归,当前子树的深度,就等于左子树深度与右子树深度的较大值加1

class Solution {
    public int maxDepth(TreeNode root) {
        //再写个递归的
        if(root == null)
            return 0;
        return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
    }
}

剑指 Offer 55 - II. 平衡二叉树

题目描述

输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。


示例 1:

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

    3
   / \\
  9  20
    /  \\
   15   7
返回 true 。

示例 2:

给定二叉树 [1,2,2,3,3,null,null,4,4]

       1
      / \\
     2   2
    / \\
   3   3
  / \\
 4   4
返回 false 。

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

思路

做了上一题,这个题有个很容易想到的思路就是判断每个子树是否是平衡二叉树,即判断每个子树的左右子树高度之差是否小于等于1,但是这样会重复遍历遍历多次单个节点,因此想更加优化的方法
就是从底部到顶部计算高度,采用后序遍历,先从底部节点开始判断是否是一颗平衡二叉树,如果是,就返回当前子树的高度,也就是左右子树高度的较大值加1,如果不是返回-1;并且加入剪枝,即如果已经判断到一个子树不是平衡二叉树了,就直接返回-1

class Solution {
    public boolean isBalanced(TreeNode root) {
        //是一个平衡二叉树要求当前结点的左右子树高度之差,不能大于1;同时子树也要求是平衡二叉树
        return helper(root) >= 0; 
    }

    public int helper(TreeNode root){
        if(root == null)
            return 0;
        int left = helper(root.left);
        int right = helper(root.right);

        //如果左右子树有一个不是平衡二叉树,就不行
        if(left == -1 || right == -1)
            return -1;
        //如果左右子树高度相差小于等于1,那么当前高度就是左右子树高度+1
        if(Math.abs(left - right) <= 1)
            return Math.max(left, right) + 1;
        return -1;
    }
}

以上是关于LeetCode664. 奇怪的打印机 / 剑指 Offer 55 - I. 二叉树的深度 / 剑指 Offer 55 - II. 平衡二叉树的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 664 奇怪的打印机[动态规划] HERODING的LeetCode之路

LeetCode 664. Strange Printer (DP)

664. 奇怪的打印机(区间DP)

664. 奇怪的打印机(区间DP)

664. 奇怪的打印机

java 664.奇怪的打印机(#WA Greedy).java