已知二叉树的根结点指针TreeNode* root以及链表上结点的深度,请设计算法返回一个链表ListNode,该链表代表该深度上所有结点的值,并按树上从左往右的顺序链接,深度不能超过树的高度,且树上结点的值为不大于100000的非负整数。
public class TreeLevel {
ListNode ln = new ListNode(-1);
ListNode p = ln;
public ListNode getTreeLevel(TreeNode root, int dep) {
// write code here
if (root == null || dep <= 0)
return null;
if (dep == 1) {
p.next = new ListNode(root.val);
p = p.next;
} else {
getTreeLevel(root.left, dep - 1);
getTreeLevel(root.right, dep - 1);
}
return ln.next;
}
}
这个题目的意思就是输出二叉树的某一层的所有元素,这个首先想到的是层次遍历,层次遍历最简单的方法就是用队列实现,我们传统的层次遍历方法是可以输出所有元素,那么如何区分相邻两层之间的元素呢?
其实我们可以用两个整数变量line1,line2来记录相邻两层的元素个数,其中line1代表出栈那一层留下的元素个数,line2代表下一层进栈元素的个数,每当line1为0的时候,说明上一层已经全部出栈,下一层已经全部入栈,那么层次遍历层数就加一,这个时候将line2的值复制给line1,line2=0,当遍历到第dep层的时候,便把那一层的所有元素输出,停止遍历。
class TreeLevel {
public:
ListNode* getTreeLevel(TreeNode* root, int dep) {
// write code here
if(dep<=0||root==NULL)
return NULL;
ListNode* list=new ListNode(-1);
ListNode* listHead=list;
queue<TreeNode*> qu;
qu.push(root);
int lines1=1,lines2=0,num=1;
while(!qu.empty())
{
if(num==dep)
{
for(int i=0;i<lines1;i++)
{
TreeNode* root1=qu.front();
list->next=new ListNode(root1->val);
list=list->next;
qu.pop();
}
return listHead->next;
}
TreeNode* root1=qu.front();
if(root1->left)
{
qu.push(root1->left);
lines2++;
}
if(root1->right)
{
qu.push(root1->right);
lines2++;
}
qu.pop();
if(--lines1==0)
{
lines1=lines2;
lines2=0;
num++;
}
}
return listHead->next;
}
};
<方法2>:递归遍历
其实也可以用递归遍历实现,刚开始为深度为dep,每往下递归一层,则深度减一(dep=dep-1),当dep==1的时候,便输出那个元素,如果先递归左子树,那么则实现从左到右打印,如果先递归右子树,则实现从右往左打印。
class TreeLevel {
public:
ListNode* getTreeLevel(TreeNode* root, int dep) {
// write code here
ListNode* list=new ListNode(-1);
ListNode* listHead=list;
get1(root,list,dep);
return listHead->next;
}
void get1(TreeNode* root,ListNode* &list,int dep)
{
if(dep<=0||root==NULL)
return;
if(dep==1)
{
ListNode* listnext=new ListNode(root->val);
list->next=listnext;
list=list->next;
return ;
}
get1(root->left,list,dep-1);
get1(root->right,list,dep-1);
}
};
有点诡异 用递归
class TreeLevel {
public:
ListNode* getTreeLevel(TreeNode* root, int dep) {
// write code here
if(root == NULL || dep <= 0) return NULL;
p = new ListNode(-1);
ListNode* head = p;
InOrder(root, dep);
return head->next;
}
void InOrder(TreeNode* root, int dep)
{
if(root == NULL) return;
if(dep == 1)
{
p->next = new ListNode(root->val);
p = p->next;
return;
}
InOrder(root->left, dep - 1);
InOrder(root->right, dep - 1);
}
private:
ListNode *p;
};
//看没有用Java做的,,分享一个Java的吧
//思路是使用层次遍历,当遍历到该层时,dep--,此时,队列中的即是dep层的节点
import java.util.*;
public class TreeLevel {
public ListNode getTreeLevel(TreeNode root, int dep) {
// write code here
if(root==null) return null;
Queue<TreeNode> que=new LinkedList<TreeNode>();
int len=0,i;
que.add(root);
while(dep>1&&!que.isEmpty()){
len=que.size();
for(i=0;i<len;i++){
TreeNode p=que.poll();
if(p.left != null)
que.add(p.left);
if(p.right != null)
que.add(p.right);
}
dep--;
}
ListNode res=new ListNode(que.poll().val);
ListNode tem=res;
while(!que.isEmpty()){
tem.next=new ListNode(que.poll().val);
tem=tem.next;
}
return res;
}
}
只要在先序遍历函数上加上两个参数即可:
目标深度 若当前深度和目标深度一致时,将当前节点输出,并直接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);
}
//层序遍历找到深度指向的层数,将其val存入链表
class TreeLevel {
public:
ListNode* getTreeLevel(TreeNode* root, int dep) {
// write code here
ListNode *pRoot = new ListNode(-1);
ListNode *pNode = pRoot;
if (root == NULL)
return pRoot;
queue<TreeNode*> Node;
Node.push(root);
int count = 1;
vector<int> Data;
while (!Node.empty())
{
int Index = 0;
int len = Node.size();
vector<int> data;
while (Index++ < len)
{
TreeNode *pNode = Node.front();
Node.pop();
data.push_back(pNode->val);
if (pNode->left != NULL)
Node.push(pNode->left);
if (pNode->right != NULL)
Node.push(pNode->right);
}
if (count == dep)
{
Data = data;
break;
}
count++;
}
for (int i = 0; i < Data.size(); i++)
{
ListNode *p = new ListNode(Data[i]);
pNode->next = p;
pNode = pNode->next;
}
return pRoot->next;
}
};
public class TreeLevel {
public ListNode getTreeLevel(TreeNode root, int dep) {
if (root == null) {
return null;
}
ListNode head = new ListNode(0);
ListNode p = head;
LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root);
int d = 0;
while (!queue.isEmpty()) {
d++;
int size = queue.size();
for (int i = 0; i < size; i++) {
TreeNode node = queue.remove();
if (d == dep) {
p.next = new ListNode(node.val);
p = p.next;
}
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
}
if (d == dep) {
break;
}
}
return head.next;
}
}
一个队列广搜,到达第dep层后队列所存即为该层结点。
class TreeLevel {
public:
ListNode* getTreeLevel(TreeNode* root, int dep) {
// write code here
queue<TreeNode *> q;
q.push(root);
int current_wid = 1, next_wid = 0, d = 1;
while(!q.empty())
{
if(current_wid == 0)
{
d++;
current_wid = next_wid;
next_wid = 0;
}
if(d == dep)
break;
TreeNode *temp = q.front();
q.pop();
current_wid--;
if(temp->left != NULL)
{
q.push(temp->left);
next_wid++;
}
if(temp->right != NULL)
{
q.push(temp->right);
next_wid++;
}
}
if(q.empty())
return new ListNode(-1);
int value = q.front()->val;
q.pop();
ListNode *head = new ListNode(value), * node;
node = head;
while(!q.empty())
{
node->next = new ListNode(q.front()->val);
q.pop();
node = node->next;
}
return head;
}
};
class TreeLevel {
public:
ListNode* getTreeLevel(TreeNode* root, int dep) {
if(root == nullptr || dep <= 0){
return nullptr;
}//if
// 头结点
ListNode *head = new ListNode(-1);
ListNode *p = head;
// 队列 层次遍历
queue<TreeNode*> curQueue;
curQueue.push(root);
queue<TreeNode*> nextQueue;
int level = 1;
while(!curQueue.empty()){
while(!curQueue.empty()){
TreeNode *node = curQueue.front();
curQueue.pop();
// 某一深度上所有结点的链表
if(level == dep){
p->next = new ListNode(node->val);
p = p->next;
}//if
if(node->left){
nextQueue.push(node->left);
}//if
if(node->right){
nextQueue.push(node->right);
}//if
}//while
swap(curQueue,nextQueue);
if(level == dep){
return head->next;
}//if
++level;
}//while
return nullptr;
}
};
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
class TreeLevel {
public:
ListNode* getTreeLevel(TreeNode* root, int dep) {
// corner case
if (!root) return nullptr;
deque<TreeNode*> q{{root}};
ListNode dummy(-1), *tail = &dummy;
int level = 1;
while (not q.empty() && level <= dep) {
size_t s = q.size();
while (s--) {
auto curr = q.front(); q.pop_front();
if (level == dep) {
tail = tail->next = new ListNode(curr->val);
continue;
}
if (curr->left) q.push_back(curr->left);
if (curr->right) q.push_back(curr->right);
}
++level;
}
return dummy.next;
}
}; ListNode head = new ListNode(0);
ListNode tmp = head;
public ListNode getTreeLevel(TreeNode root, int dep) {
// write code here
get(root, 1, dep);
return head.next;
}
public void get(TreeNode root, int curDep, int dep){
if(curDep == dep){
tmp.next = new ListNode(root.val);
tmp = tmp.next;
return;
}
if(root.left != null){
get(root.left, curDep +1, dep);
}
if(root.right != null){
get(root.right, curDep +1, dep);
}
} //可以采用前序遍历,到达一定深度就开始存储节点值
class TreeLevel {
public:
ListNode* getTreeLevel(TreeNode* root, int dep) {
if(root==nullptr) return nullptr;
ListNode *head=new ListNode(-1);
ListNode *p=head;
int count=1;
seek(root,p,count,dep);
return head->next;
}
private:
void seek(TreeNode *root,ListNode *&ptr,int cnt,int dep)
{
if(cnt>dep||root==nullptr) return ;
if(cnt==dep)
{
ListNode *temp=new ListNode(root->val);
ptr->next=temp;
ptr=temp;
return ;
}
seek(root->left,ptr,cnt+1,dep);
seek(root->right,ptr,cnt+1,dep);
return ;
}
};
//PS:也可以采用层次遍历
class TreeLevel {
public:
ListNode* getTreeLevel(TreeNode* root, int dep) {
// write code here
if(root==nullptr||dep==0) return nullptr;
ListNode *head=new ListNode(-1);
ListNode *p=head;
queue<TreeNode*>q;
q.push(root);
int cnt=0;
while(!q.empty())
{
int size=q.size();
++cnt;
if(cnt>dep) break;
for(int i=0;i<size;++i)
{
TreeNode *front=q.front();
q.pop();
if(cnt==dep)
{
ListNode *temp=new ListNode(front->val);
p->next=temp;
p=temp;
}
if(front->left!=nullptr)
q.push(front->left);
if(front->right!=nullptr)
q.push(front->right);
}
}
return head->next;
}
};
class TreeLevel {
public:
ListNode* getTreeLevel(TreeNode* root, int dep) {
if (!root) { return nullptr; }
queue<TreeNode*> Q;
ListNode* p = new ListNode(0);
ListNode* res = p;
Q.push(root);
int h = 0;
while (!Q.empty()) {
int n = Q.size();
++h;
if (h > dep) { break; }
while (n) {
TreeNode* node = Q.front();
Q.pop();
if (dep == h) {
p->next = (ListNode*)node;
p = p->next;
}
if (node->left) {
Q.push(node->left);
}
if (node->right) {
Q.push(node->right);
}
--n;
}
}
p->next = nullptr;
res = res->next;
return res;
}
};
运行时间:4ms
占用内存:592k
class TreeLevel:
def getTreeLevel(self, root, dep):
if not root: return
nodeStack = [root]
res = []
while nodeStack:
res.append([i.val for i in nodeStack])
nodeStack = [i for node in nodeStack for i in (node.left, node.right) if i]
dummy = ListNode(0)
pre = dummy
for i in res[dep - 1]:
node = ListNode(i)
pre.next = node
pre = pre.next
return dummy.next
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;
}
}
// 头铁的方法
public class TreeLevel {
public ListNode getTreeLevel(TreeNode root, int dep) {
// write code here
ListNode head = null;
if(root == null || dep < 0){
return head;
}
Queue<TreeNode> queue = new LinkedList<TreeNode>();
int depth = 1;
int count = 0;
int children = 1;
queue.offer(root);
while(!queue.isEmpty()){
TreeNode temp = queue.poll();
if(depth == dep){
ListNode cur = new ListNode(temp.val);
if(head == null){
head = cur;
}else{
cur.next = head;
head = cur;
}
}
if(depth == dep + 1){
break;
}
count++;
//需要head为最左边元素就从右往左添加队列。
if(temp.right != null){
queue.offer(temp.right);
}
if(temp.left != null){
queue.offer(temp.left);
}
if(count == children){
children = queue.size();
count = 0;
depth++;
}
}
return head;
}
} // BFS public ListNode getTreeLevel(TreeNode root, int dep) { if(root!=null&&dep==1) return new ListNode(root.val); if(root==null||dep<=0) return null; ListNode head = null; ListNode last = null; Queue<NodeAndHeight> queue = new LinkedList<>(); queue.offer(new NodeAndHeight(root,1)); // 根节点入队 while(!queue.isEmpty()){ NodeAndHeight nah = queue.poll(); if(nah.height==dep){ if(head==null){ head = new ListNode(nah.node.val); last = head; }else{ last.next = new ListNode(nah.node.val); last = last.next; } } if(nah.node.left!=null&&nah.height<dep){ queue.offer(new NodeAndHeight(nah.node.left,nah.height+1)); } if(nah.node.right!=null&&nah.height<dep){ queue.offer(new NodeAndHeight(nah.node.right,nah.height+1)); } } return head; } class NodeAndHeight{ TreeNode node; int height; NodeAndHeight(TreeNode node,int height){ this.node = node; this.height = height; } }
public static ListNode getTreeLevel(TreeNode root, int dep) {
LinkedList<TreeNode> link = new LinkedList<TreeNode>();
ListNode p = null;
ListNode list = new ListNode(-1); //list指向头节点
p = list;
link.addLast(root);
link.addLast(null); //用null来表示每一层的分隔
while (!link.isEmpty()){
root = link.removeFirst();
if (root == null){
dep--; //下降一层
if (!link.isEmpty())
link.addLast(null);
continue;
}
if (dep == 1){
if (root != null){
p.next = new ListNode(root.val);
p = p.next;
}
}
if (root.left != null){
link.addLast(root.left);
}
if (root.right != null){
link.addLast(root.right);
}
}
return list.next;
} 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;
}
}
//深度遍历,不需要使用队列,递归的顺序即为从左至右
public class TreeLevel {
ListNode head = new ListNode(-1);
ListNode p = head;
public ListNode getTreeLevel(TreeNode root, int dep) {
// write code here
traversal(root, dep);
return head.next;
}
private void traversal(TreeNode root, int dep){
if(root != null) {
if(dep == 1) {
p.next = new ListNode(root.val);
p = p.next;
}
traversal(root.left, dep - 1);
traversal(root.right, dep - 1);
}
}
}