树
重建二叉树
题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
解法一:
使用递归:
- 递归出口就是数组中只有一个元素就是叶子节点
- 递归条件是根据先序遍历找到根元素,然后根据中序遍历找到左右子树。
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
import java.util.Arrays;
public class Solution {
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
if(pre.length == 0){
return null;
}
//定义根节点
int rootval = pre[0];
if(pre.length == 1){
return new TreeNode(rootval);
}
int rootIndex = 0;
TreeNode root = new TreeNode(rootval);
for(int i=0;i< in.length;i++){
if(in[i] == rootval){
rootIndex = i;
}
}
root.left = reConstructBinaryTree(Arrays.copyOfRange(pre, 1, rootIndex + 1), Arrays.copyOfRange(in, 0, rootIndex));
root.right = reConstructBinaryTree(Arrays.copyOfRange(pre, rootIndex + 1, pre.length), Arrays.copyOfRange(in, rootIndex + 1, in.length));
return root;
}
}
二叉树的下一个结点
题目描述
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
解法一:
- 该节点如果有右子树,那么找这个节点的右子树的最左子树
- 没有右子树的话
- 如果该节点是其父节点的左节点,那么其父节点就是下一个节点
- 如果该节点是其父节点的右节点,那么找某个节点是其父节点的左节点,那么该某个节点的父节点就是下一个节点
public TreeLinkNode GetNext(TreeLinkNode pNode)
{
TreeLinkNode cur = null;
if(pNode == null){
return cur;
}
cur = pNode;
if(cur.right != null){
TreeLinkNode tem = pNode.right;
while(tem.left != null){
tem = tem.left;
}
return tem;
}else{
if(cur.next != null && cur.next.left == cur){
return cur.next;
}
else{
if(cur.next != null && cur.next.right == cur){
while(cur.next != null){
if(cur.next.left == cur){
return cur.next;
}
cur = cur.next;
}
}
}
return null;
}
}
对称的二叉树
题目描述
请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
解法一:
- 就是求其镜像二叉树
- 肯定是使用递归啦
- 比较left.right == right.left
public class Solution {
boolean isSymmetrical(TreeNode pRoot)
{
if(pRoot == null){
return true;
}
return help(pRoot.left, pRoot.right);
}
public boolean help(TreeNode t1, TreeNode t2){
if(t1 == null && t2 == null){
return true;
}
if(t1 == null || t2 == null){
return false;
}
return t1.val == t2.val && help(t1.left, t2.right);
}
}
按之字形顺序打印二叉树
题目描述
请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
解法一:
- 使用两个栈解决,一个负责奇数层数,一个负责偶数层数
public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> res = new ArrayList();
if(pRoot == null){
return res;
}
//奇数
Stack<TreeNode> s1 = new Stack();
//偶数
Stack<TreeNode> s2 = new Stack();
boolean flag = true;
s1.push(pRoot);
while(!s1.isEmpty() || !s2.isEmpty()){
if(flag){
//开始走s1
ArrayList<Integer> list = new ArrayList();
while(!s1.isEmpty()){
TreeNode cur = s1.pop();
list.add(cur.val);
if(cur.left != null){
s2.push(cur.left);
}
if(cur.right != null){
s2.push(cur.right);
}
}
res.add(list);
flag = !flag;
}else{
//开始走s2
ArrayList<Integer> list = new ArrayList();
while(!s2.isEmpty()){
TreeNode cur = s2.pop();
list.add(cur.val);
if(cur.right != null){
s1.push(cur.right);
}
if(cur.left != null){
s1.push(cur.left);
}
}
res.add(list);
flag = !flag;
}
}
return res;
}
解法二:
- 用两个list 一个放每层的元素,一个放值。
- 偶数层用
Collections.reverse( new ArrayList<Integer>() );
方法反转一下。 - 在数据量比较大的效率比较慢
public ArrayList<ArrayList<Integer>> Print_01(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> res = new ArrayList();
ArrayList<TreeNode> list = new ArrayList();
if(pRoot == null){
return res;
}
list.add(pRoot);
boolean flag = true;
while(!list.isEmpty()){
ArrayList<TreeNode> nextNode = new ArrayList();
ArrayList<Integer> cur = new ArrayList();
for(TreeNode a : list){
cur.add(a.val);
if(a.left != null){
nextNode.add(a.left);
}
if(a.right != null){
nextNode.add(a.right);
}
}
if(!flag){
Collections.reverse(cur);
}
res.add(cur);
flag = !flag;
list = nextNode;
}
return res;
}
把二叉树打印成多行
题目描述
从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。
解法一:
- 二叉树的层次遍历。使用两个list 一个存储值 一个存储下一层的所有的节点,
public class Solution {
ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> res = new ArrayList();
ArrayList<TreeNode> list = new ArrayList();
if(pRoot == null){
return res;
}
list.add(pRoot);
while(!list.isEmpty()){
ArrayList<Integer> cur = new ArrayList();
ArrayList<TreeNode> next = new ArrayList();
for(TreeNode n : list){
cur.add(n.val);
if(n.left != null){
next.add(n.left);
}
if(n.right != null){
next.add(n.right);
}
}
list = next;
res.add(cur);
}
return res;
}
}
序列化二叉树
题目描述
请实现两个函数,分别用来序列化和反序列化二叉树
二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过 某种符号表示空节点(#),以 ! 表示一个结点值的结束(value!)。
二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。
解法一:
- 都用的是递归操作
- 用一个队列 保存着所有的String 值
String Serialize(TreeNode root) {
if(root == null){
return "#!";
}
String s = root.val + "!";
s += Serialize(root.left);
s += Serialize(root.right);
return s;
}
TreeNode Deserialize(String str) {
String[] aa = str.split("!");
Queue<String> queue = new LinkedList();
for(int i = 0; i < aa.length; i++){
queue.add(aa[i]);
}
return generate(queue);
}
public TreeNode generate(Queue<String> queue){
String a = queue.poll();
if(a.equals("#")){
return null;
}
TreeNode cur = new TreeNode(Integer.valueOf(a));
cur.left = generate(queue);
cur.right = generate(queue);
return cur;
}
二叉搜索树的第k个结点
题目描述
给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4。
解法一:
- 其实考的就是中序遍历 返回中序遍历的第k个的值就好了。
public class Solution {
TreeNode KthNode(TreeNode pRoot, int k)
{
if(pRoot == null || k <= 0){
return null;
}
Stack<TreeNode> stack = new Stack();
ArrayList<TreeNode> res = new ArrayList();
TreeNode cur = pRoot;
while(!stack.isEmpty() || cur != null){
if(cur != null){
stack.push(cur);
cur = cur.left;
}else{
cur = stack.pop();
res.add(cur);
cur = cur.right;
}
}
if(k > res.size()){
return null;
}
TreeNode tem = res.get(k - 1);
return tem;
}
}
数据流中的中位数
题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
解法一:
- 选择两个优先级队列 一个大顶堆一个小顶堆,
- 数量为偶数的时候放入大顶堆中,然后把堆顶元素弹出给小顶堆,
- 数量为奇数的时候放入小顶堆中,然后把堆顶元素弹出给大顶堆
- 这样保证大顶堆的元素最大的都比小顶堆的元素最小的小,也就是小的放入大顶堆中,大的当如小顶堆中。
public class Solution {
//小顶堆
private PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>();
//大顶堆
private PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(15, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
int count = 0;
public void Insert(Integer num) {
if((count & 1) == 0){
maxHeap.offer(num);
int cur = maxHeap.poll();
minHeap.offer(cur);
}else{
minHeap.offer(num);
int cur = minHeap.poll();
maxHeap.offer(cur);
}
count++;
}
public Double GetMedian() {
if((count & 1) == 0){
return new Double(minHeap.peek()+maxHeap.peek())/2;
}else{
return new Double(minHeap.peek());
}
}
}