一、分别按照二叉树先序,中序和后序打印所有的节点。

这道题就是书上的算法思想的实际使用,唯一需要特别注意到的是用递归的方式建树,还是比较巧妙的,因为一棵树的建立过程字符流是重复使用的,用递归的方式对根进行循环赋值。

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));
}
}

Java刷题-tree的更多相关文章

  1. 牛客网Java刷题知识点之Java 集合框架的构成、集合框架中的迭代器Iterator、集合框架中的集合接口Collection(List和Set)、集合框架中的Map集合

    不多说,直接上干货! 集合框架中包含了大量集合接口.这些接口的实现类和操作它们的算法. 集合容器因为内部的数据结构不同,有多种具体容器. 不断的向上抽取,就形成了集合框架. Map是一次添加一对元素. ...

  2. 牛客网Java刷题知识点之泛型概念的提出、什么是泛型、泛型在集合中的应用、泛型类、泛型方法、泛型接口、泛型限定上限、泛型限定下限、 什么时候使用上限?泛型限定通配符的体现

    不多说,直接上干货! 先来看个泛型概念提出的背景的例子. GenericDemo.java package zhouls.bigdata.DataFeatureSelection; import ja ...

  3. JS、JAVA刷题和C刷题的一个很重要的区别

    就是最近在做树方面的题时,发现JS和JAVA刷题和C刷题的一个很重要的区别就是传入null的区别 当遍历的时候,C传参数时可以传进去null的指针,因为递归进去,出来时,指针还是指着那个地方 但是JS ...

  4. 牛客网Java刷题知识点之为什么HashMap和HashSet区别

    不多说,直接上干货! HashMap  和  HashSet的区别是Java面试中最常被问到的问题.如果没有涉及到Collection框架以及多线程的面试,可以说是不完整.而Collection框架的 ...

  5. 牛客网Java刷题知识点之为什么HashMap不支持线程的同步,不是线程安全的?如何实现HashMap的同步?

    不多说,直接上干货! 这篇我是从整体出发去写的. 牛客网Java刷题知识点之Java 集合框架的构成.集合框架中的迭代器Iterator.集合框架中的集合接口Collection(List和Set). ...

  6. 牛客网Java刷题知识点之Map的两种取值方式keySet和entrySet、HashMap 、Hashtable、TreeMap、LinkedHashMap、ConcurrentHashMap 、WeakHashMap

    不多说,直接上干货! 这篇我是从整体出发去写的. 牛客网Java刷题知识点之Java 集合框架的构成.集合框架中的迭代器Iterator.集合框架中的集合接口Collection(List和Set). ...

  7. 牛客网Java刷题知识点之ArrayList 、LinkedList 、Vector 的底层实现和区别

    不多说,直接上干货! 这篇我是从整体出发去写的. 牛客网Java刷题知识点之Java 集合框架的构成.集合框架中的迭代器Iterator.集合框架中的集合接口Collection(List和Set). ...

  8. 牛客网Java刷题知识点之垃圾回收算法过程、哪些内存需要回收、被标记需要清除对象的自我救赎、对象将根据存活的时间被分为:年轻代、年老代(Old Generation)、永久代、垃圾回收器的分类

    不多说,直接上干货! 首先,大家要搞清楚,java里的内存是怎么分配的.详细见 牛客网Java刷题知识点之内存的划分(寄存器.本地方法区.方法区.栈内存和堆内存) 哪些内存需要回收 其实,一般是对堆内 ...

  9. 牛客网Java刷题知识点之HashMap的实现原理、HashMap的存储结构、HashMap在JDK1.6、JDK1.7、JDK1.8之间的差异以及带来的性能影响

    不多说,直接上干货! 福利 => 每天都推送 欢迎大家,关注微信扫码并加入我的4个微信公众号:   大数据躺过的坑      Java从入门到架构师      人工智能躺过的坑          ...

随机推荐

  1. 2021-02:Teams开发平台更新概述

    作为2021年工作计划的一部分,我会在每月的第三个星期五发布Teams开发平台的更新报告,给大家整理和讲解最新的平台功能,以及特色场景.这是第一篇文章,我会挑选截至到2月份一些重要的更新,以后每月的更 ...

  2. alpakka-kafka(1)-producer

    alpakka项目是一个基于akka-streams流处理编程工具的scala/java开源项目,通过提供connector连接各种数据源并在akka-streams里进行数据处理.alpakka-k ...

  3. django学习-20.python3中的特殊方法【__str__】的作用

    目录结构 1.前言 2.[__str__]特殊方法的具体使用 2.1.当使用print打印一个类被实例化后生成的对象的时候,若类里有定义了[__str__]特殊方法,是打印出这样的数据:[__str_ ...

  4. Java 优雅地退出程序

    本文转载自Java 优雅地退出程序 导语 很多情况下,我们的程序需要在操作系统 后台 一直运行,这在程序代码里的实现就是用死循环 ( while (true) ) 来实现的.但是,这样会出现一个问题, ...

  5. java: 程序包javax.servlet.http不存在

    下载好apache tomcat,将lib目录下的servlet-api.jar导入idea即可

  6. mtk相机冷启动拆解

    1 概述 冷启动大致可以分成以下几块内容: S0 (system) 主要是 Activity 的创建耗时(从 Touch up,即 ptr:up 开始) ptr:up S1 App 从 Activit ...

  7. 后端程序员之路 35、Index搜索引擎实现分析4-最终的正排索引与倒排索引

    # index_box 提供搜索功能的实现- 持有std::vector<ITEM> _buffer; 存储所有文章信息- 持有ForwardIndex _forward_index;  ...

  8. jquery通过live绑定toggle事件

    $("a[name=reply]").live("click",function(){ $(this).toggle( function () { var $c ...

  9. android上实现0.5px线条

    转: android上实现0.5px线条 由于安卓手机无法识别border: 0.5px,因此我们要用0.5px的话必须要借助css3中的-webkit-transform:scale缩放来实现. 原 ...

  10. MYSQL的replace into

    replace into t(id, update_time) values(1, now()); 或 replace into t(id, update_time) select 1, now(); ...