题目
题目链接:
https://www.nowcoder.com/practice/19bff16ca0d64d6da38ed24fd2903ce9
思路
考察点
总结一下这个题目的要点:
题目给定一个二叉搜索树,要求把它转换成累加树,即每个节点的值是原来的值加上所有大于它的值之和。
为了实现这个转换,我们需要按照节点值降序遍历所有节点,同时记录已经遍历过的节点值的和,
并把这个和加到当前节点的值中。
这种按照节点值降序遍历的方法被称为反序中序遍历,它可以利用二叉搜索树的性质,
即左子树的值小于根节点的值,右子树的值大于根节点的值。
反序中序遍历可以用递归,栈或者 Morris 遍历三种方法来实现,它们的思路都是先遍历右子树,
再遍历根节点,最后遍历左子树。
递归方法是通过调用栈来回溯之前的节点,需要维护一个全局变量来记录节点值的和。
栈方法是通过迭代和一个辅助栈来模拟递归过程,需要把当前节点到最右边叶子路径上的点全部压入栈中,
然后弹出并更新节点值,再考虑左子树。
Morris 遍历方法是通过修改二叉搜索树的结构来实现常数空间复杂度的遍历,
需要找到当前节点在中序遍历下的前驱节点,并建立临时链接或者断开链接。
参考答案Java
import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* public TreeNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @return TreeNode类
*/
public TreeNode convertBST (TreeNode root) {
/*
考察点
总结一下这个题目的要点:
题目给定一个二叉搜索树,要求把它转换成累加树,即每个节点的值是原来的值加上所有大于它的值之和。
为了实现这个转换,我们需要按照节点值降序遍历所有节点,同时记录已经遍历过的节点值的和,并把这个和加到当前节点的值中。
这种按照节点值降序遍历的方法被称为反序中序遍历,它可以利用二叉搜索树的性质,即左子树的值小于根节点的值,右子树的值大于根节点的值。
反序中序遍历可以用递归,栈或者 Morris 遍历三种方法来实现,它们的思路都是先遍历右子树,再遍历根节点,最后遍历左子树。
递归方法是通过调用栈来回溯之前的节点,需要维护一个全局变量来记录节点值的和。
栈方法是通过迭代和一个辅助栈来模拟递归过程,需要把当前节点到最右边叶子路径上的点全部压入栈中,然后弹出并更新节点值,再考虑左子树。
Morris 遍历方法是通过修改二叉搜索树的结构来实现常数空间复杂度的遍历,需要找到当前节点在中序遍历下的前驱节点,并建立临时链接或者断开链接。
*/
//本答案用栈
List<TreeNode> list = new ArrayList<>();
TreeNode cur = root;
Stack<TreeNode> stack = new Stack<>();
int sum=0;
while (cur!=null || !stack.isEmpty()){
while (cur!=null){
stack.add(cur);
cur = cur.right;
}
cur = stack.pop();
list.add(cur); //list[i]存放节点,sum[i]存放前缀和
sum+= cur.val;
cur.val=sum;
cur =cur.left;
}
return root;
}
}
参考答案Go
package main
import . "nc_tools"
/*
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @return TreeNode类
*/
func convertBST( root *TreeNode ) *TreeNode {
/*
考察点
总结一下这个题目的要点:
题目给定一个二叉搜索树,要求把它转换成累加树,即每个节点的值是原来的值加上所有大于它的值之和。
为了实现这个转换,我们需要按照节点值降序遍历所有节点,同时记录已经遍历过的节点值的和,并把这个和加到当前节点的值中。
这种按照节点值降序遍历的方法被称为反序中序遍历,它可以利用二叉搜索树的性质,即左子树的值小于根节点的值,右子树的值大于根节点的值。
反序中序遍历可以用递归,栈或者 Morris 遍历三种方法来实现,它们的思路都是先遍历右子树,再遍历根节点,最后遍历左子树。
递归方法是通过调用栈来回溯之前的节点,需要维护一个全局变量来记录节点值的和。
栈方法是通过迭代和一个辅助栈来模拟递归过程,需要把当前节点到最右边叶子路径上的点全部压入栈中,然后弹出并更新节点值,再考虑左子树。
Morris 遍历方法是通过修改二叉搜索树的结构来实现常数空间复杂度的遍历,需要找到当前节点在中序遍历下的前驱节点,并建立临时链接或者断开链接。
*/
//本答案用栈,GO中,我暂时用切片模拟栈
cur := root
stack := []*TreeNode{}
sum := 0
for len(stack) > 0 || cur != nil {
for cur != nil {
stack = append(stack, cur)
cur = cur.Right
}
size := len(stack)
pop := stack[size-1]
sum = sum + pop.Val
pop.Val = sum
//fmt.Println(sum)
stacknew := []*TreeNode{}
for k := 0; k < size-1; k++ {
stacknew = append(stacknew, stack[k])
}
stack = stacknew
cur = pop.Left
}
return root
}
参考答案PHP
<?php
/*class TreeNode{
var $val;
var $left = NULL;
var $right = NULL;
function __construct($val){
$this->val = $val;
}
}*/
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @return TreeNode类
*/
function convertBST( $root )
{
/*
考察点
总结一下这个题目的要点:
题目给定一个二叉搜索树,要求把它转换成累加树,即每个节点的值是原来的值加上所有大于它的值之和。
为了实现这个转换,我们需要按照节点值降序遍历所有节点,同时记录已经遍历过的节点值的和,并把这个和加到当前节点的值中。
这种按照节点值降序遍历的方法被称为反序中序遍历,它可以利用二叉搜索树的性质,即左子树的值小于根节点的值,右子树的值大于根节点的值。
反序中序遍历可以用递归,栈或者 Morris 遍历三种方法来实现,它们的思路都是先遍历右子树,再遍历根节点,最后遍历左子树。
递归方法是通过调用栈来回溯之前的节点,需要维护一个全局变量来记录节点值的和。
栈方法是通过迭代和一个辅助栈来模拟递归过程,需要把当前节点到最右边叶子路径上的点全部压入栈中,然后弹出并更新节点值,再考虑左子树。
Morris 遍历方法是通过修改二叉搜索树的结构来实现常数空间复杂度的遍历,需要找到当前节点在中序遍历下的前驱节点,并建立临时链接或者断开链接。
*/
// 反序中序遍历可以用递归
//本答案用栈,PHP中,我暂时用数组模拟栈
$cur = $root;
$q = array();
$sum = 0;
while (count($q) >0 || $cur!=null){
while ($cur!=null){
array_push($q,$cur);
$cur =$cur->right;
}
$size = count($q);
$pop = $q[$size-1];
$sum = $sum+$pop->val;
$pop ->val=$sum;
$qbak = array();
for($i=0;$i<$size-1;$i++){
array_push($qbak,$q[$i]);
}
$q =$qbak;
$cur = $pop->left;
}
return $root;
}