已知二叉树的根结点指针TreeNode* root以及链表上结点的深度,请设计算法返回一个链表ListNode,该链表代表该深度上所有结点的值,并按树上从左往右的顺序链接,深度不能超过树的高度,且树上结点的值为不大于100000的非负整数。
import java.util.*;
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}*/
public class TreeLevel {
public ListNode getTreeLevel(TreeNode root, int dep) {
if(root==null||dep<=0){
return null;
}
// write code here
LinkedList<TreeNode> list = new LinkedList();
//Stack<ListNode> depNodeCache = new Stack();
list.add(root);
int countDep = 1;
int count = 0;
//按层遍历
while(!list.isEmpty()&&countDep<dep){
count = list.size();
//遍历下一层的所有子叶
while(count>0){
TreeNode node = list.removeFirst();
if(node.left!=null){
list.add(node.left);
}
if(node.right!=null){
list.add(node.right);
}
count--;
}
countDep++;
}
return toListNode(list);
}
public static ListNode toListNode(LinkedList<TreeNode> list){
ListNode curNode = null;
ListNode pre = null;
while(!list.isEmpty()){
TreeNode node = list.removeLast();
curNode = new ListNode(node.val);
curNode.next = pre;
pre = curNode;
}
return curNode;
}
}
import java.util.*;
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}*/
public class TreeLevel {
ListNode result = new ListNode(-1);
ListNode cur = result;
public ListNode getTreeLevel(TreeNode root, int dep) {
// write code here
if (root == null || dep < 1) {
return null;
}
if (dep == 1) {
cur.next = new ListNode(root.val);
cur = cur.next;
}
getTreeLevel(root.left, dep - 1);
getTreeLevel(root.right, dep - 1);
return result.next;
}
}
//好像是剑指offer里面的一题,跟着差不多,双队列,有个小坑,见注释
//方法一
public ListNode getTreeLevel(TreeNode root, int dep) {
if(root==null||dep<=0) return null;
Queue<TreeNode> queueFather=new LinkedList<TreeNode>();
Queue<TreeNode> queueSon=new LinkedList<TreeNode>();
queueFather.offer(root);
int index=1;
if(index==dep) return new ListNode(root.val);
while(!queueFather.isEmpty()){
TreeNode temp=queueFather.poll();
if(temp.left!=null) queueSon.offer(temp.left);
if(temp.right!=null)queueSon.offer(temp.right);
if(queueFather.isEmpty()){
index++;
if(index==dep){
ListNode result=queueSon.isEmpty()?null:new ListNode(queueSon.poll().val);
ListNode cur=result;
while(!queueSon.isEmpty()) {
cur.next=new ListNode(queueSon.poll().val);
cur=cur.next;
}
return result;
}
queueFather=queueSon;
queueSon=new LinkedList<TreeNode>();//此处有个坑,其实很简单,可能一开始没注意到,这里不能用clear方法,因为此时queueFather和queueSon指向同一个对象
//clear就全清了,如果想用clear就把上一句改成 queueFather=queueSon.clone(),那最开始的多台就不能用了,因为queue没有clonde方法
}
}
return null;
}
//方法二:递归
ListNode result=new ListNode(0);
ListNode cur=result;
public ListNode getTreeLevel(TreeNode root, int dep) {
if(root==null||dep<1) return null;
if(--dep==0) {
cur.next=new ListNode(root.val);
cur=cur.next;
}
if(root.left!=null) getTreeLevel(root.left,dep);
if(root.right!=null)getTreeLevel(root.right,dep);
return result.next;
}
1、定义队列a,b 2、首先头节点入a 3、依次取出a队列中的每个元素e,并打印。然后把e的左右节点入b队列,直到a取空 4、a,b互换,打印回车 5、重复3/4步,直到a为空,b也为空 6、打印结果即为按层遍历结果
// 因无需出队列,故此题以ArrayList代替队列
public ListNode getTreeLevel(TreeNode root, int dep) {
if(root == null) return null;
ArrayList<TreeNode> arr = new ArrayList<>();
arr.add(root);
return foo(arr,dep-1);
}
public ListNode foo(ArrayList<TreeNode> arr,int dep){
if(dep == 0){
ListNode head = new ListNode(arr.get(0).val);
ListNode cur = head;
for(int i = 1;i < arr.size();i++){
cur.next = new ListNode(arr.get(i).val);
cur = cur.next;
}
return head;
}
ArrayList<TreeNode> narr = new ArrayList<TreeNode>();
for(int i = 0;i < arr.size();i++){
if(arr.get(i).left != null)
narr.add(arr.get(i).left);
if(arr.get(i).right != null)
narr.add(arr.get(i).right);
}
return foo(narr,dep-1);
}
public ListNode getTreeLevel(TreeNode root, int dep) {
// write code here
//如果需要第一层,那么把第一层返回
if(dep==1){
return new ListNode(root.val);
}
//采用两个队列来控制层次遍历
Queue<TreeNode> qu1=new LinkedList<TreeNode>();
Queue<TreeNode> qu2=new LinkedList<TreeNode>();
//记录目前的层数
int nowDep=1;
//首先设置一个表头和一个操作指针
ListNode head=new ListNode(0);
ListNode p=head;
//首先往qu1中加入根节点
qu1.add(root);
while(root!=null){
System.out.println("刚刚进入while");
//首先判断当前层是否为需要的层
if(nowDep==dep){
while(!qu1.isEmpty()){
// System.out.println("返回层的值:"+qu1.peek().val);
ListNode newNode=new ListNode(qu1.poll().val);
p.next=newNode;
p=newNode;
}
return head.next;
}
/*若qu1内元素所在的层并不是指定输出的层,则进行下一层的装入,首先是把
下一层的元素全部装入qu2,然后再把qu2内的元素全部装入qu1
*/
System.out.println("进入内部第一个while前");
while(!qu1.isEmpty()){
TreeNode nowNode=qu1.poll();
System.out.println("qu1出队"+nowNode);
qu2.add(nowNode.left);
qu2.add(nowNode.right);
}
while(!qu2.isEmpty()){
qu1.add(qu2.poll());
}
//此层后,进行层数加1
nowDep++;
}
return new ListNode(root.val);
}
//用null 分辨层
public class TreeLevel {
public ListNode getTreeLevel(TreeNode root, int dep) {
Queue<TreeNode> q=new LinkedList<TreeNode>();
TreeNode t=null;
ListNode head=new ListNode(0);
ListNode cur=head;
ListNode tmp=null;
int k=0;
q.add(null);
q.add(root);
while(!q.isEmpty()){
t=q.poll();
if(t==null){
k++;
if(k==dep)
break;
q.add(null);
}
else{
if(t.left!=null)
q.add(t.left);
if(t.right!=null)
q.add(t.right);
}
}
while(!q.isEmpty()){
tmp=new ListNode(q.poll().val);
cur.next=tmp;
cur=cur.next;
}
return head.next;
}
}
只要在先序遍历函数上加上两个参数即可:
目标深度 若当前深度和目标深度一致时,将当前节点输出,并直接return回溯,无需再往下递归了!节约一定的开销!
private ListNode node = new ListNode(-1);
private ListNode first = node;
public ListNode getTreeLevel(TreeNode root, int dep) {
if ( root==null || dep<=0 ) return null;
preOrder( root, 1, dep );
return first.next;
}
private void preOrder( TreeNode root, int level, int dep ){
if ( root==null ) return;
if ( level==dep ) {
node.next = new ListNode(root.val);
node = node.next;
return;
}
preOrder(root.left, level+1, dep);
preOrder(root.right, level+1, dep);
}
public class TreeLevel {
MyListNode list = new MyListNode();
public ListNode getTreeLevel(TreeNode root, int dep) {
// write code here
vistTree(root,1,dep);
return list.getHead();
}
// 因为要求的函数没有带有深度记录参数 为了方便 自己重写了一个可以记录深度的函数
private void vistTree(TreeNode root,int depth,int goal){
if(depth == goal){
list.addToList(root.val);
return ;
}else{
if(root.left != null){
vistTree(root.left,depth+1,goal);
}
if(root.right != null){
vistTree(root.right,depth+1,goal);
}
}
}
/**
* 自己定义的一个内部类 主要用来保存访问时候的数据
*/
class MyListNode{
private ListNode head;
private ListNode last;
public ListNode getHead(){
return head;
}
public void addToList(int val){
if(head == null){
head = new ListNode(val);
last = head;
}else{
last.next = new ListNode(val);
last = last.next;
}
}
}
}