面试题61 序列化二叉树
题目要求实现两个函数,分别完成一棵二叉树的序列化和反序列化。
序列化是指使用前序遍历,将二叉树的值转化为一字符序列。反序列化是指根据此字符重新构造一棵二叉树。
在序列化过程中,在每次二叉树节点不为空时,在转化val所得的字符之后添加一个","作为分隔;对于空节点则以"#,"代替
在反序列化过程中,对字符串按照","进行分割插入到队列中,然后依次从队列中取出字符建立节点,创建一棵二叉树。
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
/*序列化意即使用前序遍历,将二叉树的值转化为一字符序列,反序列化即根据此字符序列重新构造一棵二叉树*/
import java.util.Queue;
import java.util.LinkedList;
public class Solution {
//递归形式的前序遍历
String Serialize(TreeNode root) {
if(root==null){
return "#,";
}
StringBuffer sb=new StringBuffer(root.val+",");
sb.append(Serialize(root.left));
sb.append(Serialize(root.right));
return sb.toString();
}
TreeNode Deserialize(String str) {
String[] res=str.split(",");
Queue<String> queue=new LinkedList<String>();
for(int i=0;i<res.length;i++){
queue.offer(res[i]);
}
return pre(queue);
}
//递归形式重建二叉树
TreeNode pre(Queue<String> queue){
String val=queue.poll();
if(val.equals("#"))
return null;
TreeNode node=new TreeNode(Integer.valueOf(val));
node.left=pre(queue);
node.right=pre(queue);
return node;
}
}
面试题62 二叉搜索树的第k个节点
题目要求找出二叉搜索树的第k小的节点,那就要对这个二叉树进行遍历并排序。二叉搜索树的中序遍历就是一个升序的序列,还有再去找他第k个节点即可。
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
/*二叉搜索树按照中序遍历,就是从小到大排列的一组数*/
import java.util.ArrayList;
public class Solution {
TreeNode KthNode(TreeNode pRoot, int k)
{
ArrayList<TreeNode> inlist=new ArrayList<TreeNode>();
if(pRoot==null || k<1){
return null;
}
in(pRoot,inlist);
if(k<=inlist.size())
return inlist.get(k-1);
return null;
}
void in(TreeNode node,ArrayList<TreeNode> inlist){
if(node==null)
return;
in(node.left,inlist);
inlist.add(node);
in(node.right,inlist);
}
/*中序遍历的另一种写法 因为是void,所以在if不满足时不需要显式写递归出口,返回任何值
void in(TreeNode node,ArrayList<TreeNode> inlist){
if(node!=null){
in(node.left,inlist);
inlist.add(node);
in(node.right,inlist);
}
}*/
}
面试题63 数据流的中位数
/*Java的PriorityQueue 是从JDK1.5开始提供的新的数据结构接口,
默认内部是自然排序,结果为小顶堆,也可以自定义排序器,比如下面反转比较,完成大顶堆。
链接:https://www.nowcoder.com/questionTerminal/9be0172896bd43948f8a32fb954e1be1
来源:牛客网
插入思路
奇数个数插入到大堆中,偶数个数插入到小堆中,
* 但是 奇数个数时可能会出现当前待插入的数比小堆堆顶元素大,此时需要将元素先插入到小堆,然后将小堆堆顶元素弹出并插入到大堆中
* 对于偶数时插入小堆的情况,一样的道理。why?
* 因为要保证最大堆的元素要比最小堆的元素都要小。*/
import java.util.Comparator;
import java.util.PriorityQueue;
public class Solution {
int count=0;
//priorityqueue默认是小根堆 默认初始容量是15
PriorityQueue<Integer> minHeap=new PriorityQueue<Integer>();
PriorityQueue<Integer> maxHeap=new PriorityQueue<Integer>(15,new Comparator<Integer>(){
//此处的匿名内部类可以改写成lambda表达式,更简单,但更耗时耗空间
public int compare(Integer o1,Integer o2){
//PriorityQueue默认是小顶堆,实现大顶堆,需要反转默认排序器
return o2.compareTo(o1);//o2-o1也可以
}
});
public void Insert(Integer num) {
if((count&1)==0)//count为偶数的高效写法
{/*偶数放入小顶堆,但也不是直接放入,因为可能插入的数小于大顶堆的堆顶值,所以要先将数插入
大顶堆,再将大顶堆的堆顶值(其最大值)插入小顶堆*/
//1.新加入的数先放入大顶堆,从大顶堆中筛选出最大值(堆顶值)
maxHeap.offer(num);
int temp=maxHeap.poll();
//2.将大顶堆筛选出的最大值放入小顶堆
minHeap.offer(temp);
}else{
/*奇数放入大顶堆,但也不是直接放入,因为可能插入的数大于小顶堆的堆顶值,所以要先将数插入
小顶堆,再将小顶堆的堆顶值(其最小值)插入大顶堆*/
//1.新加入的数先放入小顶堆,从小顶堆中筛选出最小值(堆顶值)
minHeap.offer(num);
int temp=minHeap.poll();
//2.将小顶堆筛选出的最小值放入大顶堆
maxHeap.offer(temp);
}
count++;//注意这个,是标明插入第几个数的依据。从0开始
}
public Double GetMedian() {
if((count&1)!=0){
return new Double(maxHeap.peek());
}else{
return new Double(maxHeap.peek()+minHeap.peek())/2;
}
}
}