左神_基础提升班_05_Morris遍历和树形dp

1.Morris遍历

morris:
开始时,cur来到头结点位置
(1)如果cur没有左孩子,cur向右移动(cur=cur.right);
(2)如果cur有左孩子,找到左子树上最右的节点mostRight:
a. 若mostRight的右指针指向空,让其指向cur,然后cur向左移动(cur=cur.left);
b. 若mostRight的右指针指向cur,让其指向null,然后cur向右移动(cur=cur.right);
(3)cur为空时遍历停止;

	public static class Node {
		public int value;
		Node left;
		Node right;
		public Node(int data) {
			this.value = data;
		}
	}
	public static void morris(Node head){
		if(head==null){
			return;
		}
		Node cur=head;
		Node mostRight=null;
		while(cur!=null){//过流程
			mostRight=cur.left; //mostRight是cur的左孩子
			if(mostRight!=null){//有左子树
				while(mostRight.right!=null&&mostRight.right!=cur){
					mostRight=mostRight.right;
				}
				//mostRight变成了cur左子树上,最右的节点
				if(mostRight.right==null){//第一次到达cur
					mostRight.right=cur;
					System.out.println(cur.value+" ");
					cur=cur.left;
					continue;
				}else{//mostRight.right==cur
					System.out.println(cur.value+" ");
					mostRight.right=null;
					cur=cur.right;
				}
			}else {
				System.out.println(cur.value+" ");
				cur=cur.right;
			}
		}
	}

morris改先序:
经过一次:直接打印
经过两次:第一次打印

public static void morrisPre(Node head){
		if(head==null){
			return;
		}
		Node cur=head;
		Node mostRight=null;
		while(cur!=null){
			mostRight=cur.left;
			if(mostRight!=null){
				while(mostRight.right!=null&&mostRight.right!=cur){
					mostRight=mostRight.right;
				}
				if(mostRight.right==null){
					mostRight.right=cur;
					System.out.println(cur.value+" ");
					cur=cur.left;
					continue;
				}else{
//					System.out.println(cur.value+" ");跟原本的遍历只这一步不同
					mostRight.right=null;
					cur=cur.right;
				}
			}else {
				System.out.println(cur.value+" ");
				cur=cur.right;
			}
		}
	}

morris改中序:
经过一次:直接打印
经过两次:第二次打印

	public static void morrisIn(Node head) {
		if(head==null){
			return;
		}
		Node cur=head;
		Node mostRight=null;
		while(cur!=null){
			mostRight=cur.left;
			if(mostRight!=null){
				while(mostRight.right!=null&&mostRight.right!=cur){
					mostRight=mostRight.right;
				}
				if(mostRight.right==null){
					mostRight.right=cur;
					cur=cur.left;
					continue;
				}else{
					System.out.println(cur.value+" ");
					mostRight.right=null;
					cur=cur.right;
				}
			}else {
				System.out.println(cur.value+" ");
				cur=cur.right;
			}
		}
	}

morris改后序:
经过一次:直接打印
经过两次:第二次到:逆序打印左子树右边界
最后逆序打印整棵树右边界

	public static void morrisPos(Node head) {
		if(head==null){
			return;
		}
		Node cur=head;
		Node mostRight=null;
		while(cur!=null){
			mostRight=cur.left;
			if(mostRight!=null){
				while(mostRight.right!=null&&mostRight.right!=cur){
					mostRight=mostRight.right;
				}
				if(mostRight.right==null){
					mostRight.right=cur;
					cur=cur.left;
					continue;
				}else{
					mostRight.right=null;
					printEdge(cur.left);
					cur=cur.right;
				}
			}else {
				cur=cur.right;
			}
		}
		printEdge(head);
	}

	public static void printEdge(Node head) {
		Node tail = reverseEdge(head);
		while(tail!=null){
			System.out.println(tail.value+" ");
			tail=tail.right;
		}
		reverseEdge(tail);
	}

	public static Node reverseEdge(Node from) {
		Node pre=null;
		while(from!=null){
			Node next=from.right;
			from.right=pre;
			pre=from;
			from=next;
		}
		return pre;
	}

2.二叉树节点间的最大宽度
(1)经过头:左height+1+右height
(2)不经过头:左子树maxDistance与右子树maxDistance中较大的

	public static class ReturnType{
		public int maxDistance;
		public int h;
		public ReturnType(int maxDistance,int h){
			this.maxDistance=maxDistance;
			this.h=h;
		}
	}
	
	public static ReturnType process(Node head) {
		if(head==null){
			return new ReturnType(0,0);
		}
		ReturnType processLeft = process(head.left);
		ReturnType processRight = process(head.right);
		int includeHead=processLeft.h+processRight.h+1;
		int max = Math.max(Math.max(processLeft.maxDistance, processRight.maxDistance), includeHead);
		int height=Math.max(processLeft.h,processRight.h)+1;
		return new ReturnType(max,height);
	}

3.派对员工最大快乐值
(1)头来:直接下属不来的最大快乐值加上自己的
(2)头不来:直接下属可以选择来或不来的最大快乐值

	public static class Employee{
		public int happy;
		public List<Employee> nexts;
	}
	public int getMaxHappy(Employee boss){
		Info info = process(boss);
		return Math.max(info.buMaxHappy,info.laiMaxHappy);
	}
	public static class Info{
		public int buMaxHappy;
		public int laiMaxHappy;
		public Info(int lai,int bu){
			this.laiMaxHappy=lai;
			this.buMaxHappy=bu;
		}
	}
	public Info process(Employee x){
		if(x.nexts.isEmpty()){//x是基层员工的时候
			return new Info(x.happy,0);
		}
		int lai=x.happy;//x来的情况下,整棵树的最大收益
		int bu=0;//x不来的情况下,整棵树的最大收益
		for (Employee next : x.nexts) {
			Info info = process(next);
			lai+=info.buMaxHappy; //注意这里只能加不来的happy
			bu+=Math.max(info.buMaxHappy,info.laiMaxHappy);
		}
		return new Info(lai,bu);
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值