代码随想录算法训练营第十二天 | 二叉树系列3

二叉树系列3

  • 二叉树 看到二叉树就想到递归
  • 404 左叶子之和
    • 重点
    • 代码随想录的代码
    • 我的代码(当日晚上自己理解后写)
  • 513 找树左下角的值
    • 重点
    • 代码随想录的代码
    • 我的代码(当日晚上自己理解后写)
    • 我去,我怎么能写出这样的代码,没有return的递归,大错特错!
    • 修正
  • 112 路径总和
    • 未看讲解,自己编写的青春稚嫩版
    • 重点
    • 代码随想录的代码
    • 我的代码(当日晚上自己理解后写)
  • 113 路径总和2
    • 未看解答前自己编写
    • 重点
    • 代码随想录的代码
    • 我的代码(当日晚上自己理解后写)
  • 106 从中序与后序遍历序列构造二叉树
    • 重点
    • 代码随想录的代码
    • 我的代码(当日晚上自己理解后写)
  • 105 从前序与中序遍历序列构造二叉树
    • 重点
    • 代码随想录的代码
    • 我的代码(当日晚上自己理解后写)
  • 654 最大二叉树
    • 重点
    • 代码随想录的代码
    • 我的代码(当日晚上自己理解后写)
  • 二叉树系列3总结

二叉树 看到二叉树就想到递归

404 左叶子之和

不会,单次递归中的处理逻辑没想清楚。

重点

首先要理清左叶子节点的定义,即当前节点是其父节点的左孩子,并且当前节点的左右孩子均为None。

其次在理清递归逻辑时注意,在我们的定义中,每个节点收集的是其左右子树的左叶子之和,所以当遍历至叶子节点时,return 0

遍历顺序:使用后序遍历,同样是从底向上收集信息的,后序遍历写的代码较为简洁。

左递归后的,if 条件判断赋值,是整个代码的关键,画个图就能理解,意义为:子树为[9 6 7],那么对于9这个节点,左叶子之和就为6 。这里的内容是:确定单层递归逻辑里。

解二叉树的题目时,已经习惯了通过节点的左右孩子判断本节点的属性,而本题我们要通过节点的父节点判断本节点的属性。

代码随想录的代码

递归法:

class Solution:def sumOfLeftLeaves(self, root):if root is None:return 0if root.left is None and root.right is None:return 0leftValue = self.sumOfLeftLeaves(root.left)  # 左if root.left and not root.left.left and not root.left.right:  # 左子树是左叶子的情况leftValue = root.left.valrightValue = self.sumOfLeftLeaves(root.right)  # 右sum_val = leftValue + rightValue  # 中return sum_val

迭代法(前序遍历,中左右,思路上很直接,按照定义,统计所有的左孩子即可)

class Solution:def sumOfLeftLeaves(self, root):if root is None:return 0st = [root]result = 0while st:node = st.pop()if node.left and node.left.left is None and node.left.right is None:result += node.left.valif node.right:st.append(node.right)if node.left:st.append(node.left)return result

我的代码(当日晚上自己理解后写)

class Solution:def sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:if root == None :return 0leftsum = self.sumOfLeftLeaves(root.left)rightsum = self.sumOfLeftLeaves(root.right)if root.left == None :return rightsumif root.left.left == None and root.left.right == None :return leftsum+rightsum+root.left.valelse :return leftsum+rightsum

迭代法,二刷再写。

513 找树左下角的值

不会,用层序遍历很简单啊,为什么没想到,用层序遍历!!!

同样,递归法也要学习,这里的递归也要用回溯。

重点

首先是遍历顺序,只要保证,先遍历左节点就可以了,前中后序(中左右,左中右,左右中,左均在右前,所以什么顺序都可以),所以在递归中,用前序遍历。

代码随想录的代码

递归+回溯

class Solution:def findBottomLeftValue(self, root: TreeNode) -> int:self.max_depth = float('-inf')self.result = Noneself.traversal(root, 0)return self.resultdef traversal(self, node, depth):if not node.left and not node.right:if depth > self.max_depth:self.max_depth = depthself.result = node.valreturnif node.left:depth += 1self.traversal(node.left, depth)depth -= 1if node.right:depth += 1self.traversal(node.right, depth)depth -= 1

递归+隐式回溯

class Solution:def findBottomLeftValue(self, root: TreeNode) -> int:self.max_depth = float('-inf')self.result = Noneself.traversal(root, 0)return self.resultdef traversal(self, node, depth):if not node.left and not node.right:if depth > self.max_depth:self.max_depth = depthself.result = node.valreturnif node.left:self.traversal(node.left, depth+1)if node.right:self.traversal(node.right, depth+1)

层序遍历:

from collections import deque
class Solution:def findBottomLeftValue(self, root):if root is None:return 0queue = deque()queue.append(root)result = 0while queue:size = len(queue)for i in range(size):node = queue.popleft()if i == 0:result = node.valif node.left:queue.append(node.left)if node.right:queue.append(node.right)return result

我的代码(当日晚上自己理解后写)

自己编写时,第一时间依旧写不出来,原因是:不知道如何在递归中去判断,当前是否是最后一层。学习解答中的思路,用一个全局变量去判断当前是否为 max.depth。

迭代法,二刷再写。

我去,我怎么能写出这样的代码,没有return的递归,大错特错!

class Solution:def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:if root.left == None and root.right == None :return root.valself.maxdepth = -1self.rleft = 0self.digui(root,0)return self.rleftdef digui(self,root,depth):if self.maxdepth < depth :self.maxdepth = depthself.rleft = root.valif root.left :self.digui(root.left,depth+1)if root.right :self.digui(root.right,depth+1)

上述代码也能通过的原因:在Python中,不写return,会默认在程序结束后,return None

修正

class Solution:def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:if root.left == None and root.right == None :return root.valself.maxdepth = -1self.rleft = 0self.digui(root,0)return self.rleftdef digui(self,root,depth):if root.left == None and root.right ==None :if self.maxdepth < depth :self.maxdepth = depthself.rleft = root.valreturnif root.left :self.digui(root.left,depth+1)if root.right :self.digui(root.right,depth+1)

112 路径总和

未看讲解,自己编写的青春稚嫩版

class Solution:def __init__(self):self.bool = Falsedef hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:res = 0if root == None:return Falseself.digui(root,targetSum,res)return self.booldef digui(self,root,target,res):if not self.bool :if root.left == None and root.right == None :res += root.valif res == target :self.bool = Truereturnelse :returnif root.left :res += root.valleftbool = self.digui(root.left,target,res)res -= root.valif root.right :res += root.valrightbool = self.digui(root.right,target,res)res -= root.val returnelse :return 

重点

借助本题,要学习,递归算法,什么时候需要返回值,什么时候不需要返回值?

本题同样不需要对中间节点进行处理逻辑,所以前中后序遍历均可。

在这里插入图片描述

本题是需要返回值的,还是要学习代码随想录的代码,及时返回,避免无效递归,比如在 if root.left 后,不仅要进一步递归,还要判断一下,是否return True 。

本题还有另一种方法,迭代法,要学习,用栈模拟需要回溯的递归过程。

代码随想录的代码

递归

class Solution:def traversal(self, cur: TreeNode, count: int) -> bool:if not cur.left and not cur.right and count == 0: # 遇到叶子节点,并且计数为0return Trueif not cur.left and not cur.right: # 遇到叶子节点直接返回return Falseif cur.left: # 左count -= cur.left.valif self.traversal(cur.left, count): # 递归,处理节点return Truecount += cur.left.val # 回溯,撤销处理结果if cur.right: # 右count -= cur.right.valif self.traversal(cur.right, count): # 递归,处理节点return Truecount += cur.right.val # 回溯,撤销处理结果return Falsedef hasPathSum(self, root: TreeNode, sum: int) -> bool:if root is None:return Falsereturn self.traversal(root, sum - root.val) 

递归+精简

class Solution:def hasPathSum(self, root: TreeNode, sum: int) -> bool:if not root:return Falseif not root.left and not root.right and sum == root.val:return Truereturn self.hasPathSum(root.left, sum - root.val) or self.hasPathSum(root.right, sum - root.val)

迭代法

class Solution:def hasPathSum(self, root: TreeNode, sum: int) -> bool:if not root:return False# 此时栈里要放的是pair<节点指针,路径数值>st = [(root, root.val)]while st:node, path_sum = st.pop()# 如果该节点是叶子节点了,同时该节点的路径数值等于sum,那么就返回trueif not node.left and not node.right and path_sum == sum:return True# 右节点,压进去一个节点的时候,将该节点的路径数值也记录下来if node.right:st.append((node.right, path_sum + node.right.val))# 左节点,压进去一个节点的时候,将该节点的路径数值也记录下来if node.left:st.append((node.left, path_sum + node.left.val))return False

我的代码(当日晚上自己理解后写)

class Solution:def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:if root == None :return Falseif targetSum - root.val == 0 and root.left == None and root.right == None:return Trueif self.hasPathSum(root.left,targetSum-root.val):return Trueif self.hasPathSum(root.right,targetSum-root.val):return Truereturn False

迭代法,二刷再写。

113 路径总和2

未看解答前自己编写

Debug心得 :主要有两点

1:在获得正确路径后,res要进行一步pop,回溯,因为前面有append操作.

2:Python中,res被append进到level后,如果对res操作,level的值也会改变!离谱!
例如: res = [1,2] r = [] r.append(res) res.pop() 此时,r 中为 [ [ 1 ] ] ,所以要 r.append(res.copy())

class Solution:def __init__(self):self.level = []def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:if root == None :return []res = []self.digui(root,targetSum,res,self.level)return self.leveldef digui(self,root,target,res,level):if root.left == None and root.right == None :target -= root.valif target == 0 :res.append(root.val)self.level.append(res.copy())res.pop()return if root.left :target -= root.valres.append(root.val)self.digui(root.left,target,res,self.level)target += root.valres.pop()if root.right :target -= root.valres.append(root.val)self.digui(root.right,target,res,self.level)target += root.valres.pop()return

此题不需要引入全局变量

class Solution:def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:if root == None :return []level = []res = []self.digui(root,targetSum,res,level)return leveldef digui(self,root,target,res,level):if root.left == None and root.right == None :target -= root.valif target == 0 :res.append(root.val)level.append(res.copy())res.pop()return if root.left :target -= root.valres.append(root.val)self.digui(root.left,target,res,level)target += root.valres.pop()if root.right :target -= root.valres.append(root.val)self.digui(root.right,target,res,level)target += root.valres.pop()return

重点

此题与上一题的不同之处在于:对于返回值的处理上,不需要返回值,设置一个变量,保存所有正确的路径。

代码随想录的代码

递归

class Solution:def __init__(self):self.result = []self.path = []def traversal(self, cur, count):if not cur.left and not cur.right and count == 0: # 遇到了叶子节点且找到了和为sum的路径self.result.append(self.path[:])returnif not cur.left and not cur.right: # 遇到叶子节点而没有找到合适的边,直接返回returnif cur.left: # 左 (空节点不遍历)self.path.append(cur.left.val)count -= cur.left.valself.traversal(cur.left, count) # 递归count += cur.left.val # 回溯self.path.pop() # 回溯if cur.right: #  右 (空节点不遍历)self.path.append(cur.right.val) count -= cur.right.valself.traversal(cur.right, count) # 递归count += cur.right.val # 回溯self.path.pop() # 回溯returndef pathSum(self, root: TreeNode, sum: int) -> List[List[int]]:self.result.clear()self.path.clear()if not root:return self.resultself.path.append(root.val) # 把根节点放进路径self.traversal(root, sum - root.val)return self.result 

递归+精简

class Solution:def pathSum(self, root: TreeNode, targetSum: int) -> List[List[int]]:result = []self.traversal(root, targetSum, [], result)return resultdef traversal(self,node, count, path, result):if not node:returnpath.append(node.val)count -= node.valif not node.left and not node.right and count == 0:result.append(list(path))self.traversal(node.left, count, path, result)self.traversal(node.right, count, path, result)path.pop()

迭代:

class Solution:def pathSum(self, root: TreeNode, targetSum: int) -> List[List[int]]:if not root:return []stack = [(root, [root.val])]res = []while stack:node, path = stack.pop()if not node.left and not node.right and sum(path) == targetSum:res.append(path)if node.right:stack.append((node.right, path + [node.right.val]))if node.left:stack.append((node.left, path + [node.left.val]))return res

我的代码(当日晚上自己理解后写)

class Solution:def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:level = []res = []self.digui(root,targetSum,level,res)return resdef digui(self,root,targetSum,level,res):if root == None :return if targetSum - root.val == 0 and root.left == None and root.right == None:level.append(root.val)res.append(level.copy())level.pop()returnif root.left:level.append(root.val)self.digui(root.left,targetSum-root.val,level,res)level.pop()if root.right:level.append(root.val)self.digui(root.right,targetSum-root.val,level,res)level.pop()return

一个改进版,写递归一定要注意的点:return 的编写,什么时候return ,return 之前是否需要回溯等。

106 从中序与后序遍历序列构造二叉树

中序和后序、中序和前序,可以唯一的确定一颗二叉树的前提是:中序和后序(前序),序列里面的值是不重复的,有重复不可能切割。

前序和后序无法确定,因为不知道中间节点。

利用递归构建,利用后序的最后一个节点,来确定根节点,根据根节点来切中序,根据切出的左子树的长度N,取后序中的前N个,即可成功切割后序数组,中序和后序均切割完后,递归构建即可。

本题在切割区间时,要始终注意不变量,采取全部左闭右开。

凡是构造二叉树的题目,采用的遍历顺序均为前序遍历。

重点

涉及非常多的细节!

代码随想录的代码

class Solution:def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode:# 第一步: 特殊情况讨论: 树为空. (递归终止条件)if not postorder:return None# 第二步: 后序遍历的最后一个就是当前的中间节点.root_val = postorder[-1]root = TreeNode(root_val)# 第三步: 找切割点.separator_idx = inorder.index(root_val)# 第四步: 切割inorder数组. 得到inorder数组的左,右半边.inorder_left = inorder[:separator_idx]inorder_right = inorder[separator_idx + 1:]# 第五步: 切割postorder数组. 得到postorder数组的左,右半边.# ⭐️ 重点1: 中序数组大小一定跟后序数组大小是相同的.postorder_left = postorder[:len(inorder_left)]postorder_right = postorder[len(inorder_left): len(postorder) - 1]# 第六步: 递归root.left = self.buildTree(inorder_left, postorder_left)root.right = self.buildTree(inorder_right, postorder_right)# 第七步: 返回答案return root

我的代码(当日晚上自己理解后写)

class Solution:def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:if postorder == [] :return Nonemiddle = postorder[-1]node = TreeNode(middle)idx = inorder.index(middle)lefti = inorder[:idx]righti = inorder[idx+1:]leftp = postorder[:idx]rightp = postorder[idx:-1]node.left = self.buildTree(lefti,leftp)node.right = self.buildTree(righti,rightp)return node

105 从前序与中序遍历序列构造二叉树

同上一题,106. 凡是构造二叉树的题目,采用的遍历顺序均为前序遍历。

重点

细节!

代码随想录的代码

class Solution:def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:# 第一步: 特殊情况讨论: 树为空. 或者说是递归终止条件if not preorder:return None# 第二步: 前序遍历的第一个就是当前的中间节点.root_val = preorder[0]root = TreeNode(root_val)# 第三步: 找切割点.separator_idx = inorder.index(root_val)# 第四步: 切割inorder数组. 得到inorder数组的左,右半边.inorder_left = inorder[:separator_idx]inorder_right = inorder[separator_idx + 1:]# 第五步: 切割preorder数组. 得到preorder数组的左,右半边.# ⭐️ 重点1: 中序数组大小一定跟前序数组大小是相同的.preorder_left = preorder[1:1 + len(inorder_left)]preorder_right = preorder[1 + len(inorder_left):]# 第六步: 递归root.left = self.buildTree(preorder_left, inorder_left)root.right = self.buildTree(preorder_right, inorder_right)# 第七步: 返回答案return root

我的代码(当日晚上自己理解后写)

class Solution:def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:if preorder == [] :return Nonemiddle = preorder[0]idx = inorder.index(middle)node = TreeNode(middle)lefti = inorder[:idx]righti = inorder[idx+1:]leftp = preorder[1:idx+1]rightp = preorder[idx+1:]node.left = self.buildTree(leftp,lefti)node.right = self.buildTree(rightp,righti)return node

654 最大二叉树

凡是构造二叉树的题目,采用的遍历顺序均为前序遍历。

本题一眼看上去也是使用递归构建树的题。

重点

本题学习代码随想录解答文章中的优化版本,当 left > right 时,return None

代码随想录的代码

版本一(基础版)

class Solution:def constructMaximumBinaryTree(self, nums: List[int]) -> TreeNode:if len(nums) == 1:return TreeNode(nums[0])node = TreeNode(0)# 找到数组中最大的值和对应的下标maxValue = 0maxValueIndex = 0for i in range(len(nums)):if nums[i] > maxValue:maxValue = nums[i]maxValueIndex = inode.val = maxValue# 最大值所在的下标左区间 构造左子树if maxValueIndex > 0:new_list = nums[:maxValueIndex]node.left = self.constructMaximumBinaryTree(new_list)# 最大值所在的下标右区间 构造右子树if maxValueIndex < len(nums) - 1:new_list = nums[maxValueIndex+1:]node.right = self.constructMaximumBinaryTree(new_list)return node

版本二(使用下标)

class Solution:def traversal(self, nums: List[int], left: int, right: int) -> TreeNode:if left >= right:return NonemaxValueIndex = leftfor i in range(left + 1, right):if nums[i] > nums[maxValueIndex]:maxValueIndex = iroot = TreeNode(nums[maxValueIndex])root.left = self.traversal(nums, left, maxValueIndex)root.right = self.traversal(nums, maxValueIndex + 1, right)return rootdef constructMaximumBinaryTree(self, nums: List[int]) -> TreeNode:return self.traversal(nums, 0, len(nums))

版本三(使用切片)

class Solution:def constructMaximumBinaryTree(self, nums: List[int]) -> TreeNode:if not nums:return Nonemax_val = max(nums)max_index = nums.index(max_val)node = TreeNode(max_val)node.left = self.constructMaximumBinaryTree(nums[:max_index])node.right = self.constructMaximumBinaryTree(nums[max_index+1:])return node

我的代码(当日晚上自己理解后写)

还是切片方便呀。

class Solution:def constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:if nums == [] :return Nonemiddle = max(nums)idx = nums.index(middle)node = TreeNode(middle)lefti = nums[:idx]righti = nums[idx+1:]node.left = self.constructMaximumBinaryTree(lefti)node.right = self.constructMaximumBinaryTree(righti)return node

二叉树系列3总结

代码随想录的总结很不错,直接上链接。

二叉树系列3总结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/18459.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在Visual Studio Code里导出8266固件

1.编辑 .vscode目录下 arduion.json 添加 一个配置项output即输出目录.当然你不设置其它软固件一样会生成,只是就不知道你能不能找到了.我的配置如下 当然这个路径你想写什么 就是什么 . 2. 切换到 arduion的项目文件 xxxx.ino.点击vsc右上的验证 即可在上面设置的目录下找到…

Java面试题大全(2023牛客网最新版)大厂面试题附答案详解

很多 Java 工程师的技术不错&#xff0c;但是一面试就头疼&#xff0c;10 次面试 9 次都是被刷&#xff0c;过的那次还是去了家不知名的小公司。 问题就在于&#xff1a;面试有技巧&#xff0c;而你不会把自己的能力表达给面试官。 应届生&#xff1a;你该如何准备简历&#…

IntegrityError: FOREIGN KEY constraint failed解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

阿里云AliYun物联网平台使用-申请免费试用及完成初始配置

一、项目简介 本专栏文章将围绕阿里云物联网平台&#xff0c;实现其设备向云平台的数据上传&#xff0c;客户端获取云平台数据。设备通过NBIOT技术实现无线采集&#xff0c;定时上传。 二、阿里云平台申请 阿里云物联网平台试用申请地址 进入上述超链接网址&#xff1a; 由于是…

This application failed to start?

大家好&#xff0c;最近在搞一个定制的图像分割项目&#xff0c;其中需要自己构建数据集。 这里我用到了基于paddle开发高效智能的交互式分割标注软件 EISeg(Efficient Interactive Segmentation)。 它涵盖了通用、人像、遥感、医疗、视频等不同方向的高质量交互式分割模型。另…

Linux安装配置Oracle+plsql安装配置(详细)

如果觉得本文不够详细&#xff0c;没有效果图&#xff0c;可移步详细版&#xff1a; Linux安装配置Oracleplsql安装配置&#xff08;超详细&#xff09;_超爱慢的博客-CSDN博客 目录 1.安装虚拟机系统 1.安装虚拟机 2.配置虚拟机 1.设置机器名 2.修改域名映射 3.固定IP…

JavaEE——常见的锁策略、CAS、synchronized 原理(八股)

文章目录 一、常见的锁策略1.乐观锁 & 悲观锁2.轻量级锁 & 重量级锁3.自旋锁 & 挂起等待锁4.互斥锁 & 读写锁5. 公平锁 & 非公平锁 二、CAS1、什么是 CAS2. CAS 的应用场景2.实现自旋锁3. CAS 中的 ABA 问题 三、 Synchronized 原理 一、常见的锁策略 当前…

MySQL数据库基础

目录 为什么使用数据库&#xff1f; 主流数据库 数据库基本使用 连接服务器 服务器管理 理解服务器、数据库、表的关系 使用示例 MySQL架构 MySQL架构分层 MySQL架构的主要组件&#xff1a; SQL分类 存储引擎 为什么使用数据库&#xff1f; 我们平时存储数据常用各…

简要介绍 | 融合深度学习与符号逻辑:神经符号结合的探索

注1&#xff1a;本文系“简要介绍”系列之一&#xff0c;仅从概念上对神经符号结合进行非常简要的介绍&#xff0c;不适合用于深入和详细的了解。 融合深度学习与符号逻辑&#xff1a;神经符号结合的探索 Neuro-Symbolic AI 本文将探讨神经符号结合的概念、原理、研究现状、挑战…

电脑应用程序发生异常怎么办?

有时候我们打开电脑上面的某个软件时&#xff0c;会打不开&#xff0c;并且会弹出如下的错误提示“应用程序发生异常 未知的软件异常&#xff08;&#xff58;&#xff58;&#xff58;&#xff09;&#xff0c;位置为&#xff58;&#xff58;”。相信大多数的人在使用电脑的时…

ThreadLocal与InheritableThreadLocal及线程池的影响

在web开发中使用了ThreadLocal本地线程存储拦截器解析的用户信息&#xff0c;方便在下文代码中调用&#xff0c;但是在springboot中使用Async开启异步操作时&#xff0c;就会造成&#xff0c;子线程无法拿到父本地线程数据。拿到一些脏数据。 1.InheritableThreadLocal 在这个…

Linux 批量杀掉进程(包含某个关键字)

一、场景说明 现场环境有十多个包含 ”celery” 关键字的进程在运行&#xff0c;每次重启服务&#xff0c;需要将这些进行kill掉&#xff0c;然后重新启动。 可以用如下命令批量kill掉这些进程&#xff1a; kill -9 PID1 PID2 PID3 PID4.....其中&#xff0c;PID是查询到的进…