leetcode337.打家劫舍iii(“树形动态规划”,DP)

文章介绍了一种使用递归解决LeetCode上的‘HouseRobberIII’问题的方法,涉及二叉树的遍历和节点值的最大和计算。代码示例展示了如何构建二叉树,以及如何通过递归函数找到抢劫的最大收益。在后续部分,作者指出了一种错误的遍历方式及其问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

递归方法

  • 求解过程,最终结果res =max(9,8)
    在这里插入图片描述
#include <stdio.h>
#include <algorithm>
#include<vector>
#include<queue>
#include<iostream>
#include<memory>
using namespace std;


//Definition for a binary tree node.
struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
//使用数组建立二叉树
TreeNode *CreateBiTree(vector<int> &a, int n, int start)//*a为data,n为数组长度,start为根节点
{
    if (a[start] == -1)return nullptr;//当根节点为空,即空树

    TreeNode* root = new TreeNode(a[start]);//新建一个根结点
    //给根结点root的成员变量data,lchild,rchild赋初值
    root->left = nullptr;
    root->right = nullptr;

    int lnode = 2 * start + 1;//用根节点确定左节点的位置
    int rnode = 2 * start + 2;//用根节点确定右节点的位置

    if (lnode > n - 1) root->left = nullptr;//超出范围为空
    else root->left = CreateBiTree(a, n, lnode);//lnode替换start,为左子树的根节点

    if (rnode > n - 1) root->right = nullptr;
    else root->right = CreateBiTree(a, n, rnode);//rnode替换start,为右子树的根节点

    return root;
}

// 打印二叉树
void out_tree(TreeNode *head){
    if(head!= nullptr){
        cout<< head->val;
        out_tree(head->left);
        out_tree(head->right);
    }
}




class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if(root == nullptr) return root;
        TreeNode* root_right = root->right;//deal with heap use after free
        root->right = invertTree(root->left);
        root->left = invertTree(root_right);
        return root;
    }

    int _rob_(TreeNode *head){ //  c++ 不支持返回值  https://www.zhihu.com/question/497145024/answer/2211413721
    //这样只有前一个值(比如下面的left)能正确赋值
        if(head!= nullptr){
            int left,right ,maxleft,maxright;
            left    =0;  maxleft =0; right= 0; maxright=0;
            if(head->left != nullptr){
                left ,maxleft = _rob_(head->left);
            }  

            if(head->right!= nullptr){
                right ,maxright  = _rob_(head->right);
            } 

            int sum1 = left+right;
            int sum2 = head->val+maxleft+maxright;
            if( sum1 > sum2){
                return sum1, left+right;
            }else{
                return sum2,left+right;
            }
        }
    }


    vector<int> _rob(TreeNode *head){
        if(head!= nullptr){
            int left,right ,subleft,subright;
            left=0;  subleft =0; right= 0; subright=0;
            vector<int> v;
            if(head->left != nullptr){
                v = _rob(head->left);
                left =v[0];subleft =v[1];
            }  

            if(head->right!= nullptr){
                v  = _rob(head->right);
                right=v[0] ;subright =v[1];
            } 

            int sum1 = left+right;
            int sum2 = head->val+subleft+subright;
            if( sum1 > sum2){  // {maxvalue for cur node, sub node for cur like 1 and 3 for 4}
                return {sum1, left+right};
            }else{
                return {sum2,left+right};
            }
        }
    }



    int rob(TreeNode *head){
        int a,b;
        vector<int> res = _rob(head);
        a=res[0];b=res[1];
        return max(a,b);
    }
};



int main()
{
    //Solution *myslo = new Solution();
    unique_ptr<Solution> myslo = unique_ptr<Solution>(new Solution());
    //vector<int> v1 = {3,4,5,1,3,-1,1};
    vector<int> v1 = {3,2,3,-1,3,-1,1};
    TreeNode *tree = CreateBiTree(v1,v1.size(),0);
    out_tree(tree); // 123
    cout<<"*************************************************************"<<endl;
    cout<< myslo->rob(tree) <<endl;

    TreeNode *res = myslo->invertTree(tree);
    out_tree(res); //132
    cout<<"*************************************************************"<<endl;
    //delete myslo;
    return 0;
}


errorsolve

在这里插入图片描述

  • 后续遍历,从低向上计算,返回当前值或者左右子树值之和的较大一个。
  • 这种方式对于用例[3,2,3,N,3,N,-1]返回错误值6
    int rob(TreeNode *head){
        if(head!= nullptr){
            int left,right;
            if(head->left != nullptr){  left  = rob(head->left); }  else{ left =0;}
            if(head->right!= nullptr){  right  = rob(head->right); } else{ right= 0;}
            int sum = left+right;
            if( sum > head->val){
                return sum;
            }else{
                return head->val;
            }
        }
    }
  • 后续需要考虑 当前节点 3 和“隔代的子树值” 3+1
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值