左神算法之中级提升(6)二叉树的递归套路

目录

【案例1】

【题目描述】

 【思路解析】

【代码实现】

【案例2】

【题目描述】

【思路解析】

【代码实现】

【案例3】

【题目描述】

 【思路解析】

【代码实现】

【案例4】

【题目描述】 2018年美团面试题

【思路解析】

【代码实现】

【案例5】

【题目描述】

【思路解析】

 【代码实现】


【案例1】

【题目描述】

 【思路解析】

(8条消息) 详解前缀树和贪心算法_Studying~的博客-CSDN博客

(8条消息) 详解图论算法 图的宽度优先遍历 图的深度优先遍历 图的拓扑排序算法 kruskal算法 prim算法 Dijkstra算法_Studying~的博客-CSDN博客

先根据这个字符串类型的数组,先生成一个前缀树,然后再对这个前缀树进行深度优先遍历,在深度优先遍历时,根据层数来控制输出的空格即可。

【代码实现】

import java.util.HashMap;

/**
 * @ProjectName: study3
 * @FileName: Ex1
 * @author:HWJ
 * @Data: 2023/7/24 15:38
 */
public class Ex1 {
    public static void main(String[] args) {
        String[] folderPaths = {"a\\b\\c", "b\\f\\k"};
        ex(folderPaths);
    }

    public static void ex(String[] folderPaths){
        Node node = generateFolderTree(folderPaths);
        process(node, 0);
    }

    // 构建前缀树
    public static Node generateFolderTree(String[] folderPaths){
        Node head = new Node(" "); // 系统根目录,前缀树头节点
        for (String folderPath : folderPaths) {
            //  folderPath.split("\\\\") 的split函数里面即含转义匹配又含正则匹配
            // 通过转义匹配  \\\\ 被解释为 \\ , \\再通过正则匹配解释为 \,所以这\\\\最终被解释为\。
            String[] paths = folderPath.split("\\\\");
            Node cur = head;
            for (int i = 0; i < paths.length; i++) {
                // 根据前缀树规则,如果不存在这条路径就新建,存在就复用
                if (!cur.nextMap.containsKey(paths[i])){
                    cur.nextMap.put((paths[i]), new Node(paths[i]));
                }
                cur = cur.nextMap.get(paths[i]);
            }
        }

        return head;
    }

    // 深度优先遍历
    public static void process(Node node, int level){
        if(level != 0){
            System.out.println(print2Space(level) + node.name);
        }
        for (Node cur : node.nextMap.values()) {
            process(cur, (level + 1));
        }

    }

    // 得到相应的空格
    public static String print2Space(int n){
        String s = "";
        for (int i = 1; i < n; i++) {
            s += "  ";
        }
        return s;
    }

}

class Node {
    public String name;
    public HashMap<String, Node> nextMap;

    public Node(String name) {
        this.name = name;
        this.nextMap = new HashMap<>();
    }
}

【案例2】

【题目描述】

【思路解析】

这里使用二叉树的递归套路,假设一个以Node节点开头的二叉树,如果他的左子树能转为一个双向链表,且他的右子树也能转为一个双向链表,则我们只需要将左子树的双向链表的末尾连向Node节点,右子树的双向链表的开头连向Node节点。然后左子树的双向链表的头,右子树的双向链表的尾就作为整个双向链表的头和尾。

【代码实现】

/**
 * @ProjectName: study3
 * @FileName: Ex2
 * @author:HWJ
 * @Data: 2023/7/29 9:08
 */
public class Ex2 {
    public static void main(String[] args) {

    }

    public static Node convert(Node head){
        if (head == null){
            return null;
        }
        return process(head).start;
    }

    // 搜索二叉树转为双向链表后返回的头和尾信息。
    public static class Info{
        public Node start;
        public Node end;

        public Info(Node start, Node end) {
            this.start = start;
            this.end = end;
        }
    }

    // 节点类
    public static class Node{
        public int value;
        public Node right;
        public Node left;

        public Node(int value) {
            this.value = value;
        }
    }

    public static Info process(Node X){
        if (X == null){
            return new Info(null, null);
        }
        Info leftHeadEnd = process(X.left);
        Info rightHeadEnd = process(X.right);
        if (leftHeadEnd.end != null){
            leftHeadEnd.end.right = X;
            X.left = leftHeadEnd.end;
        }
        if (rightHeadEnd.start != null){
            X.right = rightHeadEnd.start;
            rightHeadEnd.start.left = X;
        }
        return new Info(leftHeadEnd.end != null ? leftHeadEnd.end : X,
                rightHeadEnd.end != null ? rightHeadEnd.end : X);
    }
}

【案例3】

【题目描述】

找到一颗二叉树中,最大的搜索二叉子树,返回最大搜索二叉子树的头结点。

 【思路解析】

对于这个二叉树的任意一个节点X,有两种情况。

(1) 他作为最大搜索二叉子树的头结点。则他需要满足左子树是搜索二叉树,右子树是搜索二叉树。左子树的最大值小于X节点的值,右子树的最小值大于X节点的值。

(2)他不作为最大搜索二叉子树的头结点。 需要他左子树的最大搜索二叉子树的头结点和大小的信息,还有需要他右子树的最大搜索二叉子树的头结点和大小的信息。通过比较大小,就得到了以X节点下的最大搜索二叉子树。

所以对于任意一个节点我们需要他的信息为,以他为头结点的子树是否是搜索二叉树,子树的最大值,子树的最小值,子树的最大搜索二叉子树的头节点,子树的最大搜索二叉子树的大小。

【代码实现】

/**
 * @ProjectName: study3
 * @FileName: Ex3
 * @author:HWJ
 * @Data: 2023/7/29 9:48
 */
public class Ex3 {
    public static void main(String[] args) {

    }

    public static class Node {
        public int value;
        public Node left;
        public Node right;

        public Node(int value) {
            this.value = value;
        }
    }

    public static class Info {
        public Node head; // 最大搜索二叉子树的头结点
        public int max; // 这颗树的最大值。
        public int min; // 这棵树的最小值
        public boolean isBst; // 这棵树是否为搜索二叉树
        public int size; // 最大搜索二叉子树的大小

        public Info(Node head, int max, int min, boolean isBst, int size) {
            this.head = head;
            this.max = max;
            this.min = min;
            this.isBst = isBst;
            this.size = size;
        }
    }

    public static Info process(Node x) {
        if (x == null) {
            return new Info(null, Integer.MIN_VALUE, Integer.MAX_VALUE, true, 0);
        }
        Info leftBst = process(x.left);
        Info rightBst = process(x.right);
        int min = Math.min(x.value, Math.min(leftBst.min, rightBst.min));
        int max = Math.max(x.value, Math.max(leftBst.max, rightBst.max));
        boolean isBst = false;
        int size = Math.max(leftBst.size, rightBst.size);
        Node head = size == leftBst.size ? leftBst.head : rightBst.head;
        if (leftBst.isBst && rightBst.isBst) {
            if (leftBst.max < x.value && x.value < rightBst.min) {
                size = leftBst.size + rightBst.size + 1;
                isBst = true;
                head = x;
            }
        }
        return new Info(head, max, min, isBst, size);
    }

}

【案例4】

【题目描述】 2018年美团面试题

【思路解析】

设计两个变量,max和cur,max初始为系统最小Integer.MIN_VALUE,cur初始为0,遍历数组,cur+=arr[i],如果能使max更新则更新,如果不能则不变,如果cur<0,则使cur=0;

【代码实现】

/**
 * @ProjectName: study3
 * @FileName: Ex4
 * @author:HWJ
 * @Data: 2023/7/29 11:00
 */
public class Ex4 {
    public static void main(String[] args) {

    }

    public static int getMaxScore(int[] arr){
        if (arr == null || arr.length == 0){
            return 0;
        }
        int cur = 0;
        int max = Integer.MIN_VALUE;
        for (int i = 0; i < arr.length; i++) {
            cur += arr[i];
            max = Math.max(cur, max);
            cur = Math.max(cur, 0);
        }
        return max;
    }
}

【案例5】

【题目描述】

子矩阵只能为长方形或者正方形。

【思路解析】

利用矩阵压缩技巧,对于子矩阵则它有多种情况,最优解可以出现在 第i行到第j行的最优长方形中,所以我们遍历各种矩阵,然后将矩阵压缩成一个一维数组,然后找到这个一维数组的最优解。

 【代码实现】

/**
 * @ProjectName: study3
 * @FileName: Ex5
 * @author:HWJ
 * @Data: 2023/7/29 11:12
 */
public class Ex5 {
    public static void main(String[] args) {

    }

    public static int getMaxMatrix(int[][] map){
        if (map == null || map.length == 0 || map[0].length == 0){
            return 0;
        }
        int max = Integer.MIN_VALUE;
        int cur = 0;
        int[] s = null;
        // 开始的行号i
        for (int i = 0; i < map.length; i++) {
            s = new int[map[i].length];
            for (int j = i; j < map.length; j++) { // 以i行号开始,以j行号结尾
                cur = 0;
                for (int k = 0; k < map[0].length; k++) {
                    s[k] += map[j][k];
                    cur += s[k];
                    max = Math.max(cur, max);
                    cur = Math.max(0, cur);
                }
            }
        }
        return max;
    }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Studying~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值