2023-07-14力扣每日一题

链接:

979. 在二叉树中分配硬币

题意:

一个二叉树,n个节点,节点权值总和为n,每次可以相邻节点间移动1权值

求让每个节点都为1的最少次数

解:

给定了一个树的结构体,先整一手DFS/BFS,n不大,随便莽莽

首先每个节点只需要剩下1,而且可以知道叶子节点如果不为1,肯定要通过父节点移动

所以只要预设该叶子结点为1,所需要的代价转移到父节点身上,就可以将该叶子结点从树中抹去(因为已经处理完毕)

分析以下几种情况:

1.该叶子结点值为1:由于是叶子结点,且数量正好,所以发生移动的可能性为0,代表这个叶子节点已经处理完毕,可以从树中抹去不在考虑

2.该叶子结点值小于1:由于具有唯一的来源(父节点)所以可以进行代价转移,先花费1-val次移动次数,同时使父节点的值减少1-val,而后将自身抹去,因为不再参与移动(由于父节点可能为0,减少后存在负数,方便理解,使用权值表示而不是金币)

3.该叶子结点值大于1:由于具有唯一的去向(父节点)所以可以进行代价转移,先花费val-1次移动次数,将多余权值全部给予父节点,而后将自身抹去,因为不再参与移动

4.当所有叶子结点从树中抹去,则原先它们的父节点称为新的叶子结点,在进行前面三种情况的处理。

5.最后只剩根节点的时候,由于权值总和为n,当每个节点为1的时候才抹去,则处理到根节点时值一定为1

实际代码:

#include<bits/stdc++.h>
using namespace std;
struct TreeNode
{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode() : val(0), left(nullptr), right(nullptr) {}
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
void add(vector<int> &temp,TreeNode *root,int mao)//建树 
{
    root->val=temp[mao-1];
    if( mao*2-1<temp.size() && temp[mao*2-1]!=-1)//left child add 
    {
        root->left=new TreeNode;
        add(temp,root->left,mao*2);
    }
    
    if( mao*2<temp.size() && temp[mao*2]!=-1)//right child add 
    {
        root->right=new TreeNode;
        add(temp,root->right,mao*2+1);
    }
}
void solve(TreeNode* now,int &ans,TreeNode* father)
{
    if(now->left!=nullptr) solve(now->left,ans,now);//DFS
    
    if(now->right!=nullptr) solve(now->right,ans,now);//DFS
    
    //if(father==nullptr) return;
    //最后只剩根节点的时候,由于权值总和为n,当每个节点为1的时候才抹去,则处理到根节点时值一定为1
    //cout<<now->val<<" "<<ans<<endl;
    if(now->val<1 && father!=nullptr)
    {
        ans+= 1-now->val;//计算移动次数 
        father->val-= 1-now->val;//代价转移 
        now->val=1;//设为1
    }
    
    if(now->val>1 && father!=nullptr)
    {
        ans+= now->val-1;//计算移动次数 
        father->val+= now->val-1;//代价转移
        now->val=1;//设为1
    }
}
int distributeCoins(TreeNode* root)
{
    int ans=0;
    solve(root,ans,nullptr);
    return ans;
}
int main()
{
    int n;cin>>n;
    vector<int> temp;TreeNode root;
    for(int i=1;i<=n;i++)
    {
        int t;cin>>t;temp.push_back(t);
    }
    add(temp,&root,1);//建树 
    
    int ans=distributeCoins(&root);
    cout<<ans<<endl;
    return 0;
}

限制:

  • 树中节点的数目为 n
  • 1 <= n <= 100
  • 0 <= Node.val <= n
  • 所有 Node.val 的值之和是 n

猜你喜欢

转载自blog.csdn.net/Fei_WuYan/article/details/131731392
今日推荐