左神_中级班_06

本文介绍了多个涉及数据结构和算法的问题,包括将字符串数组转化为目录结构并按字母顺序排列,将二叉搜索树转换为双向循环链表,寻找二叉树中最大搜索二叉子树的节点个数,以及解决二叉树遍历和路灯配置问题。此外,还涉及了求解连续子数组最大和与矩阵子区域最大累计和的算法。这些问题展示了对二叉树操作、递归和数组处理的深入理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.给你一个字符串类型的数组arr,譬如:
String[] arr = { “b\cst”, “d\”, “a\d\e”, “a\b\c” };
你把这些路径中蕴含的目录结构给画出来,子目录直接列在父目录下面,并比父目录
向右进两格,就像这样:
a
b
c
d
e
b
cst
d
同一级的需要按字母顺序排列,不能乱。

public class Problem01_GetFolderTree {

	public static class Node {
		public String name;
		public TreeMap<String, Node> nextMap;  //有序表:同一级的需要按字母顺序排列,不能乱

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

	public static void print(String[] folderPaths) {
		if (folderPaths == null || folderPaths.length == 0) {
			return;
		}
		Node head = generateFolderTree(folderPaths);//生成前缀树
		printProcess(head, 0); //打印
	}

	public static Node generateFolderTree(String[] folderPaths) {
		Node head = new Node("");
		for (String foldPath : folderPaths) {
			String[] paths = foldPath.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 printProcess(Node head, int level) {//深度优先遍历
		if (level != 0) {
			System.out.println(get2nSpace(level) + head.name);
		}
		for (Node next : head.nextMap.values()) {
			printProcess(next, level + 1);
		}
	}

	public static String get2nSpace(int n) {//打印空格
		String res = "";
		for (int i = 1; i < n; i++) {
			res += "  ";
		}
		return res;
	}

	public static void main(String[] args) {
		String[] arr = { "b\\cst", "d\\", "a\\d\\e", "a\\b\\c" };
		print(arr);
	}

2.剑指 Offer 36. 二叉搜索树与双向链表
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。(二叉树的递归套路)

class Solution {
    public static class Info{//定义信息的类
        public Node start;
        public Node end;
        public Info(Node start,Node end){
            this.start=start;
            this.end=end;
        }
    }
    public Node treeToDoublyList(Node root) {
        if(root==null){
            return null;
        }
        Info info = dfs(root);//递归的建立双向链表
		info.end.right=info.start;//最终需要把链表的头和尾连到一起
		info.start.left=info.end;
		return info.start;
    }
    public static Info dfs(Node head){
        if(head==null){
            return new Info(null,null);
        }
        Info leftInfo=dfs(head.left);//左子树连成双向链表的头尾信息
        Info rightInfo=dfs(head.right);//右子树连成双向链表的头尾信息
        if(leftInfo.end!=null){
            leftInfo.end.right=head;
        }
        if(rightInfo.start!=null){
            rightInfo.start.left=head;
        }
        head.left=leftInfo.end;
        head.right=rightInfo.start;
        return new Info(leftInfo.start!=null ? leftInfo.start : head,rightInfo.end!=null ? rightInfo.end : head);
    }
    
}

3.找到一棵二叉树中,最大的搜索二叉子树,返回最大搜索二叉子树的节点个数。

	public static Node getMaxBST(Node head) {
		return process(head).maxBSTHead;
	}

	public static class ReturnType {
		public Node maxBSTHead;
		public int maxBSTSize;
		public int min;
		public int max;

		public ReturnType(Node maxBSTHead, int maxBSTSize, int min, int max) {
			this.maxBSTHead = maxBSTHead;
			this.maxBSTSize = maxBSTSize;
			this.min = min;
			this.max = max;
		}
	}

	public static ReturnType process(Node X) {
		// base case : 如果子树是空树
		// 最小值为系统最大
		// 最大值为系统最小
		if (X == null) {
			return new ReturnType(null, 0, Integer.MAX_VALUE, Integer.MIN_VALUE);
		}
		// 默认直接得到左树全部信息
		ReturnType lData = process(X.left);
		// 默认直接得到右树全部信息
		ReturnType rData = process(X.right);
		// 以下过程为信息整合
		// 同时以X为头的子树也做同样的要求,也需要返回如ReturnType描述的全部信息
		// 以X为头的子树的最小值是:左树最小、右树最小、X的值,三者中最小的
		int min = Math.min(X.value, Math.min(lData.min, rData.min)); //注意是min
		// 以X为头的子树的最大值是:左树最大、右树最大、X的值,三者中最大的
		int max = Math.max(X.value, Math.max(lData.max, rData.max));
		// 如果只考虑可能性一和可能性二,以X为头的子树的最大搜索二叉树大小
		int maxBSTSize = Math.max(lData.maxBSTSize, rData.maxBSTSize);
		// 如果只考虑可能性一和可能性二,以X为头的子树的最大搜索二叉树头节点
		Node maxBSTHead = lData.maxBSTSize >= rData.maxBSTSize ? lData.maxBSTHead
				: rData.maxBSTHead;
		// 利用收集的信息,可以判断是否存在可能性三
		if (lData.maxBSTHead == X.left && rData.maxBSTHead == X.right
				&& X.value > lData.max && X.value < rData.min) {
			maxBSTSize = lData.maxBSTSize + rData.maxBSTSize + 1;
			maxBSTHead = X;
		}
		// 信息全部搞定,返回
		return new ReturnType(maxBSTHead, maxBSTSize, min, max);
	}

4.已知一棵二叉树中没有重复节点,并且给定了这棵树的中序遍历数组和先序遍历
数组,返回后序遍历数组。
比如给定:
int[] pre = { 1, 2, 4, 5, 3, 6, 7 };
int[] in = { 4, 2, 5, 1, 6, 3, 7 };
返回:
{4,5,2,6,7,3,1}

public static int[] getPosArray1(int[] pre, int[] in) {
		if(pre==null&&in==null){
			return null;
		}
		int N=pre.length;
		int [] pos=new int[N];
		Map<Integer,Integer> map=new HashMap<>();//为了从in数组中找元素方便
		for(int i=0;i<N;i++){
			map.put(in[i],i);
		}
		set(pre,0,N-1,in,0,N-1,pos,0,N-1,map);//递归函数:pre数组从开始到结束的范围,in和pos类似
		return pos;
	}
	//利用pre[prei....prej]与in[ini...inj]
	//填好pos[posi...posj]
	public static void set(int[] pre, int prei, int prej, int[] in, int ini, int inj, int[] pos, int posi, int posj, Map<Integer, Integer> map){
		if(prej<prei){
			return;
		}
		if(prei==prej){//表明只有一个元素了,直接赋值
			pos[posi]=pre[prei];
			return ;
		}
		pos[posj]=pre[prei];//pre的第一个元素是pos的最后一个元素
		int find=map.get(pre[prei]);//找到元素在in中的位置
		set(pre,prei+1,prei+find-ini,in,ini,find-1,pos,posi,posi+find-ini-1,map);
		set(pre,prei+find-ini+1,prej ,in,find+1,inj ,pos,posi+find-ini,posj-1,map);
	}

5.小Q正在给一条长度为n的道路设计路灯安置方案。
为了让问题更简单,小Q把道路视为n个方格,需要照亮的地方用’.‘表示, 不需要
照亮的障碍物格子用’X’表示。小Q现在要在道路上设置一些路灯, 对于安置在
pos位置的路灯, 这盏路灯可以照亮pos - 1, pos, pos + 1这三个位置。
小Q希望能安置尽量少的路灯照亮所有’.‘区域, 希望你能帮他计算一下最少需
要多少盏路灯。
输入描述:
输入的第一行包含一个正整数t(1 <= t <= 1000), 表示测试用例数
接下来每两行一个测试数据, 第一行一个正整数n(1 <= n <= 1000),表示道路
的长度。第二行一个字符串s表示道路的构造,只包含’.‘和’X’。
输出描述:
对于每个测试用例, 输出一个正整数表示最少需要多少盏路灯。

//s中只有'.'或者'X'两种字符
	//路灯可以影响左中右三个位置
	//至少需要多少灯可以把.都点亮
	private static int minLight3(String test) {
		char[] chars = test.toCharArray();
		int light=0;
		int index=0;
		//当你来到i位置,一定保证之前的灯,彻底不会影响到i位置
		while(index<chars.length){
			if(chars[index]=='X'){
				index++;
			}else{//chars[index]=='.'
				if(index+1==chars.length){
					light++;
					break;
				}else{//如果下面有位置
					if(chars[index+1]=='X'){
						light++;
						index=index+2;
					}else{//下一个位置是.  ->   .  . (放灯)
						light++;
						index=index+3;
					}
				}
			}
		}
		return light;
	}

6.(相似左神中级6-6)剑指offer42.连续子数组最大和

	public int maxSubArray(int[] nums) {
        if(nums==null||nums.length==0){
            return 0;
        }
        int sum=Integer.MIN_VALUE;
        int cur=0;
        for(int i=0;i<nums.length;i++){
            cur+=nums[i];
            if(cur>sum){
                sum=cur;
            }
            if(cur<0){
                cur=0;
            }
        }
        return sum;
    }

7.给定一个整型矩阵,返回子矩阵的最大累计和.(化简为子数组最大值)
计算0-0,0-1,0-2,1-1,1-2,2-2的和,找出最大的

	public static int maxSum1(int[][] matrix) {
		if(matrix==null||matrix.length==0||matrix[0].length==0){
			return 0;
		}
		int max=Integer.MIN_VALUE;
		for(int i=0;i<matrix.length;i++){  //开始的行号i
			int [] s=new int [matrix[0].length];  //当算0-2时,s为了把之前的都加起来。
			for(int j=i;j<matrix.length;j++){  //结束的行号j,i-j是讨论的范围
				int cur=0;
				for(int k=0;k<s.length;k++){
					s[k]+=matrix[j][k];
					cur+=s[k];
					if(cur>max){
						max=cur;
					}
					if(cur<0){
						cur=0;
					}
				}
			}
		}
		return max;
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值