一、分别按照二叉树先序,中序和后序打印所有的节点。
这道题就是书上的算法思想的实际使用,唯一需要特别注意到的是用递归的方式建树,还是比较巧妙的,因为一棵树的建立过程字符流是重复使用的,用递归的方式对根进行循环赋值。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Tree1 {
//建立一棵树
public static class Node {
public int value;
public Node left;
public Node right;
public Node(int data) {
this.value = data;
}
}
//前序遍历
public static void preOrderRecur(Node head) {
if (head == null) {
return;
}
System.out.print(head.value + " ");
preOrderRecur(head.left);
preOrderRecur(head.right);
}
//中序遍历
public static void inOrderRecur(Node head) {
if (head == null) {
return;
}
inOrderRecur(head.left);
System.out.print(head.value + " ");
inOrderRecur(head.right);
}
//后续遍历
public static void posOrderRecur(Node head) {
if (head == null) {
return;
}
posOrderRecur(head.left);
posOrderRecur(head.right);
System.out.print(head.value + " ");
}
public static Node treeGenerate(BufferedReader in) throws IOException {
String[] str = in.readLine().split(" ");
Node root = new Node(Integer.parseInt(str[0]));
//递归进行赋值
if (Integer.parseInt(str[1]) != 0) {
//左孩子,递归调用再读一行root即为左孩子
root.left = treeGenerate(in);
}
if (Integer.parseInt(str[2]) != 0) {
//右孩子,递归调用再读一行root即为左孩子
root.right = treeGenerate(in);
}
return root;
}
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String[] str1 = bf.readLine().split(" ");
Node root = treeGenerate(bf);
preOrderRecur(root);
System.out.println();
inOrderRecur(root);
System.out.println();
posOrderRecur(root);
}
}
二、二叉树的序列化
假设序列化的结果字符串为 str,初始时 str = "",遍历二叉树时,遇到 null 节点,则在 str 的末尾加上 "#!",否则加上"当前的节点值!"。
输出两行分别表示该二叉树的先序序列化和层序序列化
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
public class Main {
//建立一棵树
public static class Node {
public int value;
public Node left;
public Node right;
public Node(int data) {
this.value = data;
}
}
//先序遍历
public static StringBuilder preOrderRecur(Node head, StringBuilder sb) {
if (head == null) {
return sb.append("#!");
}
sb.append(head.value + "!");
preOrderRecur(head.left, sb);
preOrderRecur(head.right, sb);
return sb;
}
//层序遍历
public static StringBuilder layerOrder(Node head, StringBuilder sb) {
if (head == null) {
sb.append("#!");
}
Queue<Node> queue = new LinkedList<>();
queue.add(head);
sb.append(head.value).append("!");
while (!queue.isEmpty()) {
head = queue.poll();
if (head.left != null) {
sb.append(head.left.value).append("!");
queue.add(head.left);
} else {
sb.append("#!");
}
if (head.right != null) {
sb.append(head.right.value).append("!");
queue.add(head.right);
} else {
sb.append("#!");
}
}
return sb;
}
public static Node treeGenerate(BufferedReader in) throws IOException {
String[] str = in.readLine().split(" ");
Node root = new Node(Integer.parseInt(str[0]));
//递归进行赋值
if (Integer.parseInt(str[1]) != 0) {
//左孩子,递归再调用
root.left = treeGenerate(in);
}
if (Integer.parseInt(str[2]) != 0) {
//右孩子,递归再调用
root.right = treeGenerate(in);
}
return root;
}
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String[] str1 = bf.readLine().split(" ");
Node root = treeGenerate(bf);
StringBuilder res1 = new StringBuilder();
res1=preOrderRecur(root,res1);
System.out.println(res1);
StringBuilder res2 = new StringBuilder();
res2 = layerOrder(root,res2);
System.out.println(res2);
}
}
这题目用String就是超时,必须要用StringBuilder。注意一下层序遍历是通过一个queue来存储的
感觉需要补充一下jvm的知识了。
三、二叉树的遍历在二叉树中找到累计和为制定值得最长路径
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
public class Main {
//建立树的节点
public static class Node {
public int value;
public Node left;
public Node right;
public Node(int data) {
this.value = data;
}
}
//获取指定值的最长路径长度
public static int getMaxLength(Node head, int sum) {
//存储当前节点的最长路径值和所在的层数
HashMap<Integer, Integer> sumMap = new HashMap<Integer, Integer>();
sumMap.put(0, 0); //没有遍历节点
return preOrder(head, sum, 0, 1, 0, sumMap);
}
//
public static int preOrder(Node head, int sum, int preSum, int level, int maxLen, HashMap<Integer, Integer> sumMap) {
if (head == null) {
return maxLen; //记录其中的最大值
}
//当前节点的最大值计算
int curSum = preSum + head.value;
//集合中不存在当前值
if (!sumMap.containsKey(curSum)) {
sumMap.put(curSum, level);
}
//更新最大长度
if (sumMap.containsKey(curSum - sum)) {
//取两者的最大值
maxLen = Math.max(level - sumMap.get(curSum - sum), maxLen);
}
//递归调用
maxLen = preOrder(head.left, sum, curSum, level + 1, maxLen, sumMap);//左子树
maxLen = preOrder(head.right, sum, curSum, level + 1, maxLen, sumMap);//右子树
if (level == sumMap.get(curSum)) {
sumMap.remove(curSum);
}
return maxLen;
}
public static Node buildTree(BufferedReader bufr) throws IOException {
int left, right, data;
String[] datas = bufr.readLine().split(" ");
data = Integer.valueOf(datas[3]);
right = Integer.valueOf(datas[2]);
left = Integer.valueOf(datas[1]);
Node head = new Node(data);
if (left != 0) {
head.left = buildTree(bufr);
}
if (right != 0) {
head.right = buildTree(bufr);
}
return head;
}
public static void main(String[] args) throws Exception {
//采用输入流接收输入
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
//将第一次换行符前的所以输入以空格分开并保存成字符串的形式,根据题意这里保不保存都无所谓的,反正递归创建没有用的
String[] temp = bf.readLine().split(" ");
int nodeNum = Integer.parseInt(temp[0]);//节点数目
int firstNumber = Integer.parseInt(temp[1]); //第一个节点
//创建树,这句和下面的sum位置交换后就会报错,不知道为什么
Node root = buildTree(bf);
int sum = Integer.parseInt(bf.readLine());
//作为结果的输出流
StringBuilder sb = new StringBuilder();
System.out.println(getMaxLength(root, sum));
//printTree(root);
}
}
四、找到二叉树中的最大搜索二叉子树
本题非常的重要,有一个动态规划的固定套路
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static class Node {
public int value;
public Node left;
public Node right;
public Node(int value) {
this.value = value;
}
}
public static class ReturnData {
public int min;
public int max;
public Node head;
public int size;
public ReturnData(int min, int max, Node head, int size) {
this.min = min;
this.max = max;
this.head = head;
this.size = size;
}
}
public static ReturnData process(Node head) {
if (head == null) {
return new ReturnData(Integer.MAX_VALUE, Integer.MIN_VALUE, null, 0);
}
Node left = head.left;
ReturnData leftData = process(left);
Node right = head.right;
ReturnData rightData = process(right);
int includeItself = 0;
if (leftData.head == left && rightData.head == right
&& leftData.max < head.value
&& rightData.min > head.value) {
includeItself = leftData.size + 1 + rightData.size;
}
int maxSize = Math.max(Math.max(leftData.size, rightData.size), includeItself);
Node newHead = leftData.size > rightData.size ? leftData.head : rightData.head;
if (maxSize == includeItself) {
newHead = head;
}
return new ReturnData(Math.min(Math.min(leftData.min, rightData.min), head.value),
Math.max(Math.max(leftData.max, rightData.max), head.value), newHead, maxSize);
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
br.readLine();
Node root = buildTree(br);
System.out.println(process(root).size);
}
public static Node buildTree(BufferedReader br) throws IOException {
String[] str = br.readLine().split(" ");
int[] nodes = new int[str.length];
for (int i = 0; i < nodes.length; i++) {
nodes[i] = Integer.parseInt(str[i]);
}
Node root = new Node(nodes[0]);
if (nodes[1] != 0) {
root.left = buildTree(br);
}
if (nodes[2] != 0) {
root.right = buildTree(br);
}
return root;
}
}
五、找到二叉树中符合搜索二叉树条件的最大拓扑结构
递归使用很重要,这个解法用了很多递归很值得学习
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Tree5 {
//建立一棵树
public static class Node {
int value;
Node left;
Node right;
Node(int data) {
this.value = data;
}
}
public static int bstTopoSize1(Node head) {
//寻找所有节点的最大拓扑结构
if (head == null) {
return 0;
}
int max = maxTopo(head, head);
max = Math.max(bstTopoSize1(head.left), max);
max = Math.max(bstTopoSize1(head.right), max);
return max;
}
public static int maxTopo(Node h, Node n) {
//搜索以h为头节点的最大拓扑结构
if (h != null && n != null && isBSTNode(h, n, n.value)) {
//以h为头节点的满足要求,继续从左右子树开始搜索
return maxTopo(h, n.left) + maxTopo(h, n.right) + 1;
}
return 0;
}
public static boolean isBSTNode(Node h, Node n, int value) {
//判断n节点是否在以h节点为头节点的搜索二叉树上
if (h == null) {
return false;
}
if (h == n) {
return true;
}
return isBSTNode(h.value > value ? h.left : h.right, n, value);
}
public static Node treeGenerate(BufferedReader in) throws IOException {
String[] str = in.readLine().split(" ");
Node root = new Node(Integer.parseInt(str[0]));
//递归进行赋值
if (Integer.parseInt(str[1]) != 0) {
//左孩子,递归再调用
root.left = treeGenerate(in);
}
if (Integer.parseInt(str[2]) != 0) {
//右孩子,递归再调用
root.right = treeGenerate(in);
}
return root;
}
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
bf.readLine();
Node root=treeGenerate(bf);
System.out.println(bstTopoSize1(root));
}
}
六、二叉树的按层打印与ZigZag打印
给定一颗二叉树,分别实现按层和 ZigZag 打印二叉树。
ZigZag遍历: 意思是第一层从左到右遍历,第二层从右到左遍历,依次类推。
有个更好的办法就是读取一层,然后计算queue的长度,并且再将左子树右子树压入队列中
public static void printByLevel3(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
int level = 1;
queue.offer(root);
System.out.print("Level " + level++ + ":");
while (!queue.isEmpty()) {
int length = queue.size(); // - 核心点 区分:标识当前层和下一层的分界位置
//换行时刻
for (int i = 0; i < length; i++) {
TreeNode curr = queue.poll();
if (curr.left != null) {
queue.offer(curr.left);
}
if (curr.right != null) {
queue.offer(curr.right);
}
System.out.print(curr.value + " ");
}
//注:其中!queue.isEmpty()判断可忽略,这里只是为了打印好看,才加的判断
if (!queue.isEmpty()) {
System.out.print("\nLevel " + level++ + " : ");
}
}
}
书上的方法用的是俩个标志位last和nLast,也是很好的方法,难以理解一点。
之字打印目前比较好理解的就是用俩stack,存数据,再出来打印
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
//二叉树的按层打印与zigzag打印
public class Tree6 {
public static class Node {
int value;
Node left;
Node right;
Node(int data) {
this.value = data;
}
}
public static void printByLevel(Node head) {
if (head == null) return;
Queue<Node> queue = new LinkedList<>();
int level = 1;
Node last = head;
Node nLast = null;
queue.add(head);
System.out.print("Level " + (level++) + " : ");
while (!queue.isEmpty()) {
head = queue.poll();
System.out.print(head.value + " ");
if (head.left != null) {
queue.add(head.left);
nLast = head.left;
}
if (head.right != null) {
queue.add(head.right);
nLast = head.right;
}
if(head==last&&!queue.isEmpty()){
System.out.print("\nLevel "+(level++)+" : ");
last=nLast;
}
}
System.out.println();
}
public static Node treeGenerate(BufferedReader in) throws IOException {
String[] str = in.readLine().split(" ");
Node root = new Node(Integer.parseInt(str[0]));
//递归进行赋值
if (Integer.parseInt(str[1]) != 0) {
//左孩子,递归再调用
root.left = treeGenerate(in);
}
if (Integer.parseInt(str[2]) != 0) {
//右孩子,递归再调用
root.right = treeGenerate(in);
}
return root;
}
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
bf.readLine();
Node root = treeGenerate(bf);
printByLevel(root);
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
public class Main{
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
br.readLine();
TreeNode root = createTree(br);
layerPrint(root);
zigZag(root);
}
public static void zigZag(TreeNode root){
if(root==null) return;
Stack<TreeNode> s1 = new Stack<>();
Stack<TreeNode> s2 = new Stack<>();
s1.add(root);
int level = 1;
TreeNode node;
StringBuilder sb;
while(!s1.isEmpty()||!s2.isEmpty()){
if(!s1.isEmpty()){
sb = new StringBuilder();
sb.append("Level "+level+" from left to right: ");
while(!s1.isEmpty()){
node = s1.pop();
sb.append(node.val+" ");
if(node.left!=null){
s2.add(node.left);
}
if(node.right!=null){
s2.add(node.right);
}
}
level++;
System.out.println(sb.toString().trim());
}
if(!s2.isEmpty()){
sb = new StringBuilder();
sb.append("Level "+level+" from right to left: ");
while(!s2.isEmpty()){
node = s2.pop();
sb.append(node.val+" ");
if(node.right!=null){
s1.add(node.right);
}
if(node.left!=null){
s1.add(node.left);
}
}
level++;
System.out.println(sb.toString().trim());
}
}
}
public static void layerPrint(TreeNode root){
if(root==null) return;
Queue<TreeNode> q = new LinkedList<>();
q.add(root);
int presize = 1;
int size = 0;
int count = 1;
while(!q.isEmpty()){
StringBuilder sb = new StringBuilder();
sb.append("Level "+count+" : ");
while((presize--)>0){
TreeNode node = q.poll();
sb.append(node.val+" ");
if(node.left!=null){
size++;
q.add(node.left);
}
if(node.right!=null){
size++;
q.add(node.right);
}
}
presize = size;
size = 0;
count++;
System.out.println(sb.toString().trim());
}
}
//递归建树
public static TreeNode createTree(BufferedReader br){
try{
String[] ss = br.readLine().trim().split(" ");
int data = Integer.parseInt(ss[0]);
int left = Integer.parseInt(ss[1]);
int right = Integer.parseInt(ss[2]);
TreeNode root = new TreeNode(data);
if(left!=0){
root.left = createTree(br);
}
if(right!=0){
root.right = createTree(br);
}
return root;
}catch(Exception e){
return null;
}
}
}
class TreeNode{
int val;
TreeNode left;
TreeNode right;
public TreeNode(int val){
this.val = val;
}
}
七、按升序输出二叉树的两个错误节点的值。(每个节点的值各不相同)
这个题目要点是考虑到是二叉搜索树,所以应该是按中序进行遍历, 从小到大的顺序进行输出,第一个错误点是出现前者大于后者的前者节点,第二个错误是前者大于后者的后者节点。
注意看看左神改写的中序遍历真的很厉害。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
public class Tree7 {
public static class Node {
//建立一棵树
public int value;
public Node left;
public Node right;
public Node(int data) {
this.value = data;
}
}
public static Node[] getTwoErNodes(Node head) {
Node[] errs = new Node[2];
if (head == null) return errs;
Stack<Node> stack = new Stack<>();
Node pre = null;
while (!stack.isEmpty() || head != null) {
if (head != null) {
stack.push(head);
head = head.left;
} else {
head = stack.pop();
if (pre != null && pre.value > head.value) {
errs[0] = errs[0] == null ? pre : errs[0];
errs[1] = head;
}
pre = head;
head = head.right;
}
}
return errs;
}
public static Node treeGenerate(BufferedReader in) throws IOException {
String[] str = in.readLine().split(" ");
Node root = new Node(Integer.parseInt(str[0]));
//递归进行赋值
if (Integer.parseInt(str[1]) != 0) {
//左孩子,递归调用再读一行root即为左孩子
root.left = treeGenerate(in);
}
if (Integer.parseInt(str[2]) != 0) {
//右孩子,递归调用再读一行root即为左孩子
root.right = treeGenerate(in);
}
return root;
}
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String[] str1 = bf.readLine().split(" ");
Node root = treeGenerate(bf);
Node[] errs=getTwoErNodes(root);
if(errs[0].value>errs[1].value) System.out.println(errs[1].value+" "+errs[0].value);
else System.out.println(errs[0].value+" "+errs[1].value);
}
}
八、判断t1树是否右与t2树拓扑结构相同的子树
这个递归用的太好了,哎要多学习
public class Tree8 {
public static class Node {
public int value;
public Node left;
public Node right;
public Node(int data) {
this.value = data;
}
}
public static boolean contains(Node t1, Node t2) {
if (t2 == null) {
return true;
}
if (t1 == null) {
return false;
}
return check(t1, t2) || contains(t1.left, t2) || contains(t1.right, t2);
}
public static boolean check(Node h, Node t2) {
if (t2 == null) {
return true;
}
if (h == null || h.value != t2.value) {
return false;
}
return check(h.left, t2.left) && check(h.right, t2.right);
}
}
九、判断二叉树是否为平衡二叉树
public class Tree9 {
public static class Node {
public int value;
public Node left;
public Node right;
public Node(int data) {
this.value = data;
}
}
public static class ReturnType {
public boolean isBalanced;
public int height;
public ReturnType(boolean isBalanced, int height) {
this.isBalanced = isBalanced;
this.height = height;
}
}
public static ReturnType process(Node head) {
if (head == null) {
return new ReturnType(true, 0);
}
ReturnType leftData = process(head.left);
ReturnType rightData = process(head.right);
int height = Math.max(leftData.height, rightData.height) + 1;
boolean isBalanced = leftData.isBalanced && rightData.isBalanced && Math.abs(leftData.height - rightData.height) < 2;
return new ReturnType(isBalanced, height);
}
public static boolean isBalanced(Node head) {
return process(head).isBalanced;
}
}
十、根据后序数组重建搜索二叉树
less和more的关系很重要,两者相差了一位。
public class Tree10 {
public static class Node {
Node left;
Node right;
int value;
public Node(int data) {
this.value = data;
}
}
public static boolean isPostArray(int[] arr) {
if (arr == null || arr.length == 0) {
return false;
}
return isPost(arr, 0, arr.length - 1);
}
public static boolean isPost(int[] arr, int start, int end) {
//more记录搜索二叉树的右子树的第一个值
//less记录搜索二叉树的左子树的最后一个值
if (start == end) {
return true;
}
int less = -1;
int more = end;
for (int i = start; i < end; i++) {
if (arr[end] > arr[i]) {
less = i;
} else {
more = more == end ? i : more;
}
}
if (less == -1 || more == end) {
return isPost(arr, start, end - 1);
}
if (less != more - 1) {
return false;
}
return isPost(arr, start, less) && isPost(arr, more, end - 1);
}
}
十一、判断一棵二叉树是否为搜索二叉树和完全二叉树
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
public class Tree11 {
public static class Node {
Node left;
Node right;
int value;
Node(int data) {
this.value = data;
}
}
public static ArrayList<Integer> arrayList = new ArrayList<>();
//中序遍历的搜索二叉树必定为单调递增序列
public static void inOrderRecur(Node head) {
if (head == null) return;
inOrderRecur(head.left);
arrayList.add(head.value);
inOrderRecur(head.right);
}
public static boolean layerOrder(Node head) {
int flag = 0;
if (head == null) return true;
Queue<Node> queue = new LinkedList<>();
queue.add(head);
while (!queue.isEmpty()) {
head = queue.poll();
if (head.left == null && head.right != null) return false;
if (head.left != null && head.right != null) {
queue.add(head.left);
queue.add(head.right);
}
if (flag == 1 && (head.left != null || head.right != null)) return false;
if (head.left == null && head.right == null) {
flag = 1;
}
}
return true;
}
public static Node treeGenerate(BufferedReader in) throws IOException {
String[] str = in.readLine().split(" ");
Node root = new Node(Integer.parseInt(str[0]));
//递归进行赋值
if (Integer.parseInt(str[1]) != 0) {
//左孩子,递归调用再读一行root即为左孩子
root.left = treeGenerate(in);
}
if (Integer.parseInt(str[2]) != 0) {
//右孩子,递归调用再读一行root即为左孩子
root.right = treeGenerate(in);
}
return root;
}
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
bf.readLine();
Node root = treeGenerate(bf);
//搜索二叉树判断
inOrderRecur(root);
boolean flag = true;
for (int i = 0; i + 1 < arrayList.size(); i++) {
if (arrayList.get(i) > arrayList.get(i + 1)) flag = false;
}
System.out.println(flag);
System.out.println(layerOrder(root));
}
}
十二、在一棵二叉树中找后继节点,也就是中序的下一个节点
这个题目的输入有问题坑哭了,就是中序然后遍历找后面一个节点。
做题半小时。调试1小时,最后发现给的数据错了,球球牛客网长点心吧。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
public class Tree12 {
public static class Node {
Node left;
Node right;
int value;
Node(int data) {
this.value = data;
}
}
public static ArrayList<Integer> arrayList = new ArrayList<>();
public static void mid_order(Node head) {
if (head == null) return;
mid_order(head.left);
arrayList.add(head.value);
mid_order(head.right);
}
public static Node treeGenerate(BufferedReader in) throws IOException {
String[] str = in.readLine().split(" ");
Node root = new Node(Integer.parseInt(str[0]));
//递归进行赋值
if (Integer.parseInt(str[1]) != 0) {
//左孩子,递归调用再读一行root即为左孩子
root.left = treeGenerate(in);
}
if (Integer.parseInt(str[2]) != 0) {
//右孩子,递归调用再读一行root即为左孩子
root.right = treeGenerate(in);
}
return root;
}
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
bf.readLine();
Node root = treeGenerate(bf);
mid_order(root);
String str = bf.readLine();
int value=Integer.parseInt(str);
// System.out.println(value);
// System.out.println(arrayList);
if(value==arrayList.get(arrayList.size()-1)) System.out.println(0);
for (int i = 0; i < arrayList.size()-1; i++) {
if(arrayList.get(i)==value) System.out.println(arrayList.get(i+1));
}
}
}
十三、在二叉树中找到俩个节点的最近公共祖先
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static class Node {
Node left;
Node right;
int value;
Node(int data) {
this.value = data;
}
}
public static Node lowestAncestor(Node head, Node o1, Node o2) {
if (head == null || head.value == o1.value || head.value == o2.value) {
return head;
}
Node left = lowestAncestor(head.left, o1, o2);
Node right = lowestAncestor(head.right, o1, o2);
if (left != null && right != null) {
return head;
}
//left和right一个为空一个不为空则直接返回不为空的那个
return left != null ? left : right;
}
public static Node treeGenerate(BufferedReader in) throws IOException {
String[] str = in.readLine().split(" ");
Node root = new Node(Integer.parseInt(str[0]));
//递归进行赋值
if (Integer.parseInt(str[1]) != 0) {
//左孩子,递归调用再读一行root即为左孩子
root.left = treeGenerate(in);
}
if (Integer.parseInt(str[2]) != 0) {
//右孩子,递归调用再读一行root即为左孩子
root.right = treeGenerate(in);
}
return root;
}
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
bf.readLine();
Node root = treeGenerate(bf);
String[] str = bf.readLine().split(" ");
Node o1 = new Node(Integer.parseInt(str[0]));
Node o2 = new Node(Integer.parseInt(str[1]));
Node result=lowestAncestor(root,o1,o2);
System.out.println(result.value);
}
}
十四、二叉树节点间的最大距离问题
用动态规划的思想来做,需要注意的是重视过程不重视结果
考虑俩个事情:
1、递归的条件 、递归条件
2、递归边界
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class Main {
private static class Node {
public int value;
public Node left;
public Node right;
public Node(int value) {
this.value = value;
}
}
private static class ReturnType {
/**
* 以该节点为头节点的二叉树节点间的最大距离
*/
public int maxLength;
/**
* 以该节点为头节点的二叉树的高度
*/
public int height;
public ReturnType(int maxLength, int height) {
this.maxLength = maxLength;
this.height = height;
}
}
private static int getMaxLength(Node head) {
if (head == null) {
return 0;
}
return process(head).maxLength;
}
private static ReturnType process(Node head) {
if (head == null) {
return new ReturnType(0, 0);
}
// 得到左子树与右子树的返回信息
ReturnType leftInfo = process(head.left);
ReturnType rightInfo = process(head.right);
// 最大距离为左子树中最大距离、右子树中最大距离、左子树高度+右子树高度+1 这三者中的最大值
int maxLength = Math.max(leftInfo.maxLength, rightInfo.maxLength);
maxLength = Math.max(leftInfo.height + rightInfo.height + 1, maxLength);
int height = Math.max(leftInfo.height, rightInfo.height) + 1;
return new ReturnType(maxLength, height);
}
private static Node createTree(BufferedReader reader) {
try {
String[] strs = reader.readLine().split(" ");
int[] arr = new int[strs.length];
for (int i = 0; i < arr.length; i++) {
arr[i] = Integer.valueOf(strs[i]);
}
Node head = new Node(arr[0]);
head.left = arr[1] == 0 ? null : createTree(reader);
head.right = arr[2] == 0 ? null : createTree(reader);
return head;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
Node head = null;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
reader.readLine();
head = createTree(reader);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(getMaxLength(head));
}
}