微软100题第16题(输入一颗二元树,从上往下按层打印树的每个结点,同一层中按照从左往右的顺序打印)

本教程提供了一系列关于Kubernetes(K8s)的部署方法及资源管理配置的视频课程链接,涵盖minikube、kubeadm等多种部署方式,并详细介绍了K8s核心资源如Pod、Service、Deployment等的使用。

发布一个k8s部署视频:https://edu.youkuaiyun.com/course/detail/26967

课程内容:各种k8s部署方式。包括minikube部署,kubeadm部署,kubeasz部署,rancher部署,k3s部署。包括开发测试环境部署k8s,和生产环境部署k8s。

腾讯课堂连接地址https://ke.qq.com/course/478827?taid=4373109931462251&tuin=ba64518

第二个视频发布  https://edu.youkuaiyun.com/course/detail/27109

腾讯课堂连接地址https://ke.qq.com/course/484107?tuin=ba64518

介绍主要的k8s资源的使用配置和命令。包括configmap,pod,service,replicaset,namespace,deployment,daemonset,ingress,pv,pvc,sc,role,rolebinding,clusterrole,clusterrolebinding,secret,serviceaccount,statefulset,job,cronjob,podDisruptionbudget,podSecurityPolicy,networkPolicy,resourceQuota,limitrange,endpoint,event,conponentstatus,node,apiservice,controllerRevision等。

第三个视频发布:https://edu.youkuaiyun.com/course/detail/27574

详细介绍helm命令,学习helm chart语法,编写helm chart。深入分析各项目源码,学习编写helm插件


————————————————------------------------------------------------------------------------------------------------------------------

1python版本

'''
Created on 2017-1-18

@author: admin
第16题(树):
题目(微软):
输入一颗二元树,从上往下按层打印树的每个结点,同一层中按照从左往右的顺序打印。  
例如输入8
  / /
 6 10
/ / / /
5 7 9 11
输出8 6 10 5 7 9 11。
'''
from _overlapped import NULL
class BinaryTree:
    def __init__(self):
        self.root=self.Node(0)
        self.root.left=self.Node(1)
        self.root.right=self.Node(2)
        self.root.left.left=self.Node(3)
        self.root.left.right=self.Node(4)
        self.root.right.left=self.Node(5)
        self.root.right.right=self.Node(6)
    
    def levelWalk(self):
        nodes=[]
        nodes.append(self.root)
        while len(nodes)>0:
            print(nodes[0].value,end=",")
            if nodes[0].left!=NULL:
                nodes.append(nodes[0].left)
            if nodes[0].right!=NULL:
                nodes.append(nodes[0].right)
            nodes=nodes[1:]

    class Node:
        def __init__(self,value):
            self.value=value
            self.left=NULL
            self.right=NULL
        
if __name__ == '__main__':
    tree=BinaryTree()
    tree.levelWalk()

2java版本

 

3scala版本

package ms

import scala.collection.mutable.ListBuffer
/**
 * 第16题(树): 
题目(微软): 
输入一颗二元树,从上往下按层打印树的每个结点,同一层中按照从左往右的顺序打印。   
例如输入
   8 
  / / 
 6 10 
/ / / / 
5 7 9 11 
输出8 6 10 5 7 9 11。
 */
class LeverTree{
  var root:Node=null
  def this(default:Int=1){
    this()
    root=Node(0)
    root.left=Node(1)
    root.right=Node(2)
    root.left.left=Node(3)
    root.left.right=Node(4)
    root.right.left=Node(5)
    root.right.right=Node(6)
  }
  
  def levelWalk(){
    val listBuffer=ListBuffer[Node]()
    listBuffer+=root;
    while(listBuffer.size>0){
      print(listBuffer(0).value+",")
      if(listBuffer(0).left!=null){
        listBuffer+=listBuffer(0).left
      }
      if(listBuffer(0).right!=null){
        listBuffer+=listBuffer(0).right
      }
      listBuffer.remove(0)
    }
  }
  
  case class Node(var value:Int,var left:Node=null,var right:Node=null)
}
object MicroSoft016 {
  def main(args: Array[String]): Unit = {
    val tree=new LeverTree(1)
    tree.levelWalk()
  }
  
}

 
<think>好的,用户想要实现一个按打印二叉节点,并且同一的节点从右到左输出的算法。首先,我需要回忆一下常见的二叉遍历方法。通常,序遍历(广度优先搜索,BFS)是用队列实现的,按从左到右访问节点。但用户的需求是同一从右到左,这显然和标准序遍历的顺序相反。 那如何调整呢?首先想到的是,在标准序遍历的基础上,对每一的节点进行逆序处理。也就是说,先按正常的序遍历收集每一的节点,然后将该的节点顺序反转,再添加到结果中。这种方法虽然可行,但可能效率稍低,因为需要额外的反转操作。不过实现起来比较简单,适合快速解决问。 另一种方法是修改节点入队的顺序。通常,我们先将左子节点入队,再入队右子节点,这样出队顺序是左到右。如果反过来,先入队右子节点,再入队左子节点,那么出队顺序就会变成右到左。这可能更高效,因为不需要额外的反转步骤。不过需要测试这种方法是否正确。 然后,我需要考虑代码的结构。无论是Python还是C++,实现思路应该类似。以Python为例,用户提供的引用中的代码使用了队列,每次处理一节点。可能需要维护一个队列,记录当前的所有节点,然后将它们的子节点按右到左的顺序入队。 另外,用户提供的引用[3]中提到了使用栈和队列结合的方法来实现自下而上、从右到左的遍历,但用户的需求是按从上到下,每内从右到左。所以可能不需要栈,只需要调整入队顺序或者反转每的结果。 接下来,我需要验证这两种方法的正确性。第一种方法:正常序遍历后反转每的结果。例如,对于二叉: 1 / \ 2 3 / \ / \ 4 5 6 7 标准序遍历得到的结构是[[1], [2,3], [4,5,6,7]],反转每后变成[[1], [3,2], [7,6,5,4]],这正是用户需要的输出。 第二种方法:修改入队顺序,先右后左。在处理每一时,将右子节点先入队,左子节点后入队。这样,队列中的节点顺序会是右到左,从而在出队时自然形成从右到左的顺序。例如,根节点1入队后,处理根节点时,先入队3,再入队2。下一处理时,队列里是3、2,处理3时,入队7、6;处理2时,入队5、4。这样下一的节点顺序是7、6、5、4,即从右到左。这样得到的结构是[[1], [3,2], [7,6,5,4]],符合要求。 这两种方法哪种更好呢?第一种方法可能需要额外的反转操作,时间复杂度是O(n),因为每都要反转,但空间复杂度可能稍高。第二种方法通过调整入队顺序,无需反转,直接在访问时得到正确顺序,可能更高效。 然后,需要考虑代码的具体实现。在Python中,可以使用队列,每次处理一,记录当前的节点数,循环处理每个节点,并将其子节点按右到左的顺序加入队列。例如,使用一个队列,每次处理一时,记录当前的长度,然后循环该次数,将节点值收集到当前的结果列表中,同时将子节点按右到左入队。这样,每一的节点都会被正确收集。 用户提供的引用中的Python代码使用了队列,每次弹出队首元素,并将左、右子节点入队。如果要调整为从右到左,可能需要改变入队顺序,先右后左,这样下一的处理顺序就会是右到左。但这样在下一处理时,队列中的顺序已经是右到左了,所以处理当前的时候,每个节点的左右子节点需要反过来入队吗?或者,每次处理一的时候,先右子节点入队,再左子节点入队,这样下一顺序就是右到左,但当前顺序是从右到左吗? 可能需要更仔细的分析。例如,根节点入队后,处理根节点时,将右子节点入队,再左子节点入队。这样,队列中的顺序是右、左。处理下一时,先处理右子节点,然后将它的右子节点和左子节点入队,接着处理左子节点,同样先右后左。这样,每一的处理顺序都是从右到左,而下一的入队顺序也是右到左,从而保证次正确。 不过,这样可能会导致下一顺序不正确。例如,假设第三有四个节点:原顺序是4、5、6、7,在第二处理右节点3时,先入队7,再6;处理左节点2时,先入队5,再4。这样队列中的顺序是7、6、5、4,处理第三时,顺序是7、6、5、4,即从右到左,符合要求。所以这种方法可以实现每从右到左的顺序,无需反转。 因此,正确的做法是在处理每个节点时,先将其右子节点入队,再左子节点入队。这样,队列中的顺序就是按从右到左排列的。不过,这样处理的话,每的节点会被正确地按从右到左的顺序处理,而无需反转。 但这样会不会导致下一顺序混乱?比如,在处理第三的节点时,每个节点的右子节点先入队,左子节点后入队,这样队列中的顺序是右、左,从而在处理下一时,同样按右到左的顺序。但用户的需求是按输出,每内部从右到左,而每顺序还是从上到下的。例如,对于深度为3的,输出应该是[[1], [3,2], [7,6,5,4]]。如果按照上述方法,队列中的处理顺序会是: 初始队列:[1] 处理1:弹出1,入队3,再入队2。队列变为[3,2]。收集1的结果[1]。 处理2:弹出3,入队7,6;弹出2,入队5,4。队列变为[7,6,5,4]。收集2的结果[3,2]。 处理3:依次弹出7、6、5、4,如果它们没有子节点,队列为空。收集3的结果[7,6,5,4]。 这样得到的顺序是正确的,每内部从右到左。所以这种方法可行,无需反转每的结果。 但这样是否正确呢?因为通常的序遍历是按处理的,每次处理一的时候,记录当前队列的长度,然后处理该长度的次数,从而将同一的节点处理完。如果入队的顺序是右到左,那么在同一的处理中,节点是按右到左的顺序被处理的,所以收集的顺序也是右到左的。因此,这种方法可以正确实现每从右到左的输出,而无需反转。 因此,代码实现的关键在于修改子节点的入队顺序:先右子节点,再左子节点。这样,在队列中同一的节点会被按右到左的顺序处理,从而收集到正确的结果。 现在,参考用户提供的Python代码示例,可以进行调整。原代码中,处理当前节点时,先入队左子节点,再右子节点。现在需要反过来,先入队右子节点,再左子节点。 例如,原代码中的部分: if t.left: q.append(t.left) if t.right: q.append(t.right) 现在需要改为: if t.right: q.append(t.right) if t.left: q.append(t.left) 这样,队列中的顺序就是右子节点在前,左子节点在后。这样处理每一的时候,节点的顺序就是从右到左了。 不过,需要注意之间的分隔。在标准的序遍历中,我们通常会在每一开始前记录队列的长度,然后处理该长度的节点,这样就能区分每一。例如: 在Python中,可以通过循环队列的长度来实现分。例如: while q: level_size = len(q) current_level = [] for _ in range(level_size): node = q.pop(0) current_level.append(node.val) if node.right: q.append(node.right) if node.left: q.append(node.left) result.append(current_level) 这样,每次处理一的时候,先处理该的所有节点(level_size次),并将他们的右子节点和左子节点入队(顺序为右到左),这样下一的处理顺序也会是右到左。但这样会导致下一顺序也是右到左,而我们需要的是每一顺序都是右到左,但之间从上到下。例如: 对于根节点1,处理时入队3、2。下一的处理顺序是3、2,收集到当前的结果是[3,2]。然后处理3的子节点,入队7、6;处理2的子节点,入队5、4。队列变为[7,6,5,4]。下一处理时,依次处理7、6、5、4,收集为[7,6,5,4]。这正是用户需要的输出。 因此,这样的代码结构可以实现按从右到左打印节点的需求。因此,修改后的Python代码应该使用分处理,并在处理每个节点时,先右后左入队。 总结来说,正确的实现步骤是: 1. 初始化队列,将根节点入队(如果根非空)。 2. 进入循环,直到队列为空。 3. 在每次循环开始时,记录当前的节点数(队列的长度)。 4. 创建一个临时列表存储当前的节点值。 5. 循环处理当前每个节点: a. 出队节点。 b. 将节点值加入当前列表。 c. 先入队右子节点(如果存在)。 d. 再入队左子节点(如果存在)。 6. 将当前列表加入结果列表。 7. 循环结束后,返回结果列表。 这样,每的节点都会被按从右到左的顺序收集,而子节点的入队顺序保证下一的处理顺序正确。 用户提供的引用中的代码是单的处理,没有显式分,所以可能需要调整结构。例如,原Python代码: def PrintFromTopToBottom(self, root): Tree_list=[] if not root: return [] q=[root] while len(q): t=q.pop(0) Tree_list.append(t.val) if t.left: q.append(t.left) if t.right: q.append(t.right) return Tree_list 这个代码将所有的节点按顺序放入Tree_list,但无法区分次。如果要按输出,并且每从右到左,需要分处理,如前面的分析,使用分循环,并在每处理时先右后左入队。 因此,最终的Python代码可能如下: def right_to_left_level_order(root): result = [] if not root: return result queue = [root] while queue: level_size = len(queue) current_level = [] for _ in range(level_size): node = queue.pop(0) current_level.append(node.val) if node.right: queue.append(node.right) if node.left: queue.append(node.left) result.append(current_level) return result 这样,返回的result是一个二维列表,每个子列表代表一,按从右到左的顺序排列。 验证这个代码是否正确。例如,对于二叉: 1 / \ 2 3 / \ / \ 4 5 6 7 根节点1入队。队列长度为1,处理该: current_level初始化为空。处理节点1,加入current_level。然后检查右子节点3,入队;左子节点2,入队。此时队列是[3,2]。current_level是[1],加入result。 下一轮循环,队列长度是2。处理第一个节点3,加入current_level。检查右子节点7,入队;左子节点6,入队。队列变为[2,7,6]。然后处理第二个节点2,加入current_level。检查右子节点5,入队;左子节点4,入队。队列变为[7,6,5,4]。current_level是[3,2],加入result。 下一轮循环,队列长度是4。依次处理7、6、5、4。每个节点没有子节点,所以队列在每次处理后变为[6,5,4]、[5,4]、[4]、[]。current_level收集为[7,6,5,4],加入result。最终result是[[1], [3,2], [7,6,5,4]],符合要求。 因此,这段代码是正确的。 用户可能还想了解其他语言的实现,比如C++。根据引用中的C++代码,同样可以进行调整,将入队顺序改为先右后左,并在分处理时收集每的节点。例如: vector<vector<int>> levelOrder(TreeNode* root) { vector<vector<int>> result; if (!root) return result; queue<TreeNode*> q; q.push(root); while (!q.empty()) { int level_size = q.size(); vector<int> current_level; for (int i = 0; i < level_size; ++i) { TreeNode* node = q.front(); q.pop(); current_level.push_back(node->val); if (node->right) q.push(node->right); if (node->left) q.push(node->left); } result.push_back(current_level); } return result; } 这样,C++的实现也是类似的逻辑。 总结,用户的问可以通过修改序遍历的子节点入队顺序,先右后左,并分处理来实现按从右到左打印二叉节点。这种方法的时间复杂度是O(n),空间复杂度也是O(n),与标准序遍历相同,是高效的实现方式。</think>### 逐步解答 要实现二叉从右往左打印节点,需在标准序遍历(BFS)基础上调整节点处理顺序。以下是实现思路和代码示例: --- #### 核心思路 1. **队列结构调整**:将子节点入队顺序改为**先右后左**,确保每节点处理顺序自然形成从右往左的序列 2. **分处理机制**:通过记录每节点数量,保证结果分存储 --- #### Python实现代码 ```python class TreeNode: def __init__(self, x): self.val = x self.left = None self.right = None def right_to_left_level_order(root): result = [] if not root: return result queue = [root] while queue: level_size = len(queue) current_level = [] for _ in range(level_size): node = queue.pop(0) # 从队列头部取出节点 current_level.append(node.val) # 关键调整:先右子节点入队 if node.right: queue.append(node.right) if node.left: queue.append(node.left) result.append(current_level) return result ``` --- #### 执行过程示例 以二叉: ``` 1 / \ 2 3 / \ / \ 4 5 6 7 ``` **处理流程**: 1. 根节点`1`入队 → 队列:`[1]` 2. 处理第一: - 取出`1` → 当前结果:`[1]` - 先右子节点`3`入队 → 队列:`[3]` - 再左子节点`2`入队 → 队列:`[3,2]` 3. 处理第二: - 取出`3` → 当前结果:`[3]` - 右子`7`入队 → 队列:`[2,7]` - 左子`6`入队 → 队列:`[2,7,6]` - 取出`2` → 当前结果:`[3,2]` - 右子`5`入队 → 队列:`[7,6,5]` - 左子`4`入队 → 队列:`[7,6,5,4]` 4. 处理第三: - 依次取出`7,6,5,4` → 当前结果:`[7,6,5,4]` **最终输出**: $$ [[1],[3,2],[7,6,5,4]] $$ --- #### 关键点解析 1. **入队顺序调整**:通过先处理右子节点实现自然逆序 ```python if node.right: queue.append(node.right) # 先右 if node.left: queue.append(node.left) # 后左 ``` 2. **时间复杂度**:$O(n)$,每个节点恰好访问一次 3. **空间复杂度**:$O(n)$,队列最大存储最后一节点数 --- #### 扩展验证 可用以下二叉验证代码: ```python # 构造测试 root = TreeNode(1) root.left = TreeNode(2) root.right = TreeNode(3) root.left.left = TreeNode(4) root.left.right = TreeNode(5) root.right.left = TreeNode(6) root.right.right = TreeNode(7) print(right_to_left_level_order(root)) # 输出:[[1], [3, 2], [7, 6, 5, 4]] ``` --- ### 相关问 1. 如何实现自下而上的序遍历? 2. 怎样在每遍历时同时记录级深度? 3. 能否用深度优先搜索(DFS)实现序遍历?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hxpjava1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值