day16|● 513.找树左下角的值 ● 112. 路径总和 113.路径总和ii ● 106.从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构造二叉树

513.找树左下角的值

找树左下角的值
这道题迭代法很容易做出来

112. 路径总和

路径总和
因为求路径总和,所以应该是从上往下遍历,所以选用的是前序遍历。
还是没有习惯用go的闭包函数

func hasPathSum(root *TreeNode, targetSum int) bool {
    return getSum(root, targetSum, 0)
}

func getSum(root *TreeNode, targetSum, tmpsum int) bool{
    if root == nil {return false}
    
    tmpsum += (*root).Val

    if (*root).Left == nil && (*root).Right == nil{
        if tmpsum == targetSum{
            return true
        }
    }
    leftbool := getSum((*root).Left, targetSum , tmpsum )
    rightbool := getSum((*root).Right, targetSum , tmpsum )
    
    return leftbool || rightbool
}

113.路径总和ii

路径总和ii
append添加切片有坑,*ret = append(*ret, tmp) 会被改掉,
*ret = append(*ret, append([]int(nil),tmp…))才可以

//正确的代码
func pathSum(root *TreeNode, targetSum int) [][]int {
    ret := make([][]int, 0)
    tmp := make([]int, 0)
    
    getPath(root, targetSum, 0, &ret, tmp)
    return ret
}

func getPath(root *TreeNode, targetSum, tmpsum int, ret *[][]int, tmp []int) {
    if root == nil {return}
    tmpsum += root.Val
    
    tmp = append(tmp, root.Val)
    fmt.Printf("address:%p-------末尾元素%d\n", &tmp, root.Val)
    if root.Left == nil && root.Right == nil && tmpsum == targetSum{
            *ret = append(*ret, append([]int(nil),tmp...))
            //*ret = append(*ret, tmp)
    }

    getPath(root.Left, targetSum , tmpsum , ret, tmp) 
    getPath(root.Right, targetSum , tmpsum , ret, tmp)
    
}

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

从中序与后序遍历序列构造二叉树
这道题难度倒是不难,主要是知道了思路没办法用代码的形式表现出来。特别是返回值这里,就更难了。
首先后序遍历的最后的值就是当前子树的根节点,然后根据根节点找到中序遍历的根节点,前后分别就是左右子树,依次类推即可。

func buildTree(inorder []int, postorder []int) *TreeNode {
  idxMap := map[int]int{}
    for i, v := range inorder {
        idxMap[v] = i
    }
    var build func(int, int) *TreeNode
    build = func(inorderLeft, inorderRight int) *TreeNode {
        // 无剩余节点
        if inorderLeft > inorderRight {
            return nil
        }

        // 后序遍历的末尾元素即为当前子树的根节点
        val := postorder[len(postorder)-1]
        postorder = postorder[:len(postorder)-1]
        root := &TreeNode{Val: val}

        // 根据 val 在中序遍历的位置,将中序遍历划分成左右两颗子树
        // 由于我们每次都从后序遍历的末尾取元素,所以要先遍历右子树再遍历左子树
        inorderRootIndex := idxMap[val]
        root.Right = build(inorderRootIndex+1, inorderRight)
        root.Left = build(inorderLeft, inorderRootIndex-1)
        return root
    }
    return build(0, len(inorder)-1)


}

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

从前序与中序遍历序列构造二叉树
这题目思路是一样的,但是这个步骤感觉比较详细一写

lass Solution {
public:
    void travel(TreeNode* root, vector<int>& preorder, vector<int>& inorder){
        int pos;
        for(int i = 0; i < inorder.size(); ++i){
            if(inorder[i] == preorder[0]){
                pos = i;
                break;
            }
        }
        vector<int> leftpre,rightpre,leftin,rightin;
        for(int i = 0; i < pos; ++i){
            leftin.push_back(inorder[i]);
        }
        for(int i = pos + 1; i < inorder.size(); ++i){
            rightin.push_back(inorder[i]);
        }
        for(int i = 1; i <= leftin.size(); ++i){
            leftpre.push_back(preorder[i]);
        }
        for(int i = 0;( leftpre.size() + 1+i) < preorder.size(); ++i){
            rightpre.push_back(preorder[leftpre.size() + 1+i]);
        }

        if(leftin.size() != 0){
            TreeNode* tmp = new TreeNode(leftpre[0]);
            root->left = tmp;
            travel(root->left,leftpre,leftin);
        }
        if(rightin.size() != 0){
            TreeNode* tmp = new TreeNode(rightpre[0]);
            root->right = tmp;
            travel(root->right,rightpre,rightin);
        }


    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        TreeNode* root= new TreeNode(preorder[0]);
        travel(root,preorder,inorder);
        return root;
    }

    
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值