第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時(shí)綁定郵箱和手機(jī)立即綁定

洛谷P3365 改造二叉樹:從問題分析到代碼實(shí)現(xiàn)

標(biāo)簽:
C++

https://img1.sycdn.imooc.com/43cedb680870805209240765.jpg

一、问题分析

题目要求我们计算将二叉树修改为二叉搜索树(BST)所需的最少修改次数。二叉搜索树的性质是:对于任意节点,其左子树所有节点的值都小于该节点的值,右子树所有节点的值都大于该节点的值。

二、解题思路


  1. 中序遍历序列‌:BST的中序遍历结果是一个严格递增序列

  2. 问题转化‌:将原二叉树的中序遍历序列转换为严格递增序列所需的最少修改次数

  3. 最长递增子序列(LIS)‌:最少修改次数 = 序列长度 - 最长递增子序列长度

三、C++代码实现

#include <iostream>
#include <vector>
#include <algorithm>
using namespACe std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

// 构建二叉树
TreeNode* buildTree(int n, const vector<int>& vals, const vector<pair<int, int>>& edges) {
    vector<TreeNode*> nodes(n + 1);
    for (int i = 1; i <= n; ++i) {
        nodes[i] = new TreeNode(vals[i - 1]);
    }
    
    for (int i = 2; i <= n; ++i) {
        int fa = edges[i - 2].first;
        int ch = edges[i - 2].second;
        if (ch == 0) {
            nodes[fa]->left = nodes[i];
        } else {
            nodes[fa]->right = nodes[i];
        }
    }
    return nodes[1];
}

// 中序遍历收集节点值
void inorder(TreeNode* root, vector<int>& seq) {
    if (!root) return;
    inorder(root->left, seq);
    seq.push_back(root->val);
    inorder(root->right, seq);
}

// 计算最长递增子序列长度
int lengthOfLIS(vector<int>& nums) {
    vector<int> dp;
    for (int num : nums) {
        auto it = lower_bound(dp.begin(), dp.end(), num);
        if (it == dp.end()) {
            dp.push_back(num);
        } else {
            *it = num;
        }
    }
    return dp.size();
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n;
    cin >> n;
    
    vector<int> vals(n);
    for (int i = 0; i < n; ++i) {
        cin >> vals[i];
    }
    
    vector<pair<int, int>> edges(n - 1);
    for (int i = 0; i < n - 1; ++i) {
        cin >> edges[i].first >> edges[i].second;
    }
    
    TreeNode* root = buildTree(n, vals, edges);
    vector<int> seq;
    inorder(root, seq);
    
    int lis_len = lengthOfLIS(seq);
    cout << n - lis_len << endl;
    
    return 0;
}

四、 代码详解

数据结构定义

我们首先定义树节点的结构:

struct TreeNode {    int val;
    TreeNode *left;
    TreeNode *right;    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}};

2 构建二叉树

根据输入构建二叉树:

TreeNode* buildTree(int n, const vector<int>& vals, const vector<pair<int, int>>& edges) {    vector<TreeNode*> nodes(n + 1);    for (int i = 1; i <= n; ++i) {
        nodes[i] = new TreeNode(vals[i - 1]);
    }    
    for (int i = 2; i <= n; ++i) {        int fa = edges[i - 2].first;        int ch = edges[i - 2].second;        if (ch == 0) {
            nodes[fa]->left = nodes[i];
        } else {
            nodes[fa]->right = nodes[i];
        }
    }    return nodes[1];}

3 中序遍历

收集中序遍历序列:

void inorder(TreeNode* root, vector<int>& seq) {    if (!root) return;    inorder(root->left, seq);
    seq.push_back(root->val);    inorder(root->right, seq);}

4 计算最长递增子序列

使用贪心算法计算LIS长度:

int lengthOfLIS(vector<int>& nums) {
    vector<int> dp;    for (int num : nums) {        auto it = lower_bound(dp.begin(), dp.end(), num);        if (it == dp.end()) {
            dp.push_back(num);
        } else {
            *it = num;
        }
    }    return dp.size();}

五、总结

通过将问题转化为中序遍历序列的最长递增子序列问题,我们能够高效地计算出将任意二叉树修改为BST所需的最少修改次数。这种方法结合了树遍历和动态规划的思想,展示了算法设计中问题转化的重要性。

来源:洛谷P3365 改造二叉树:从问题分析到代码实现


點(diǎn)擊查看更多內(nèi)容
TA 點(diǎn)贊

若覺得本文不錯(cuò),就分享一下吧!

評論

作者其他優(yōu)質(zhì)文章

正在加載中
  • 推薦
  • 評論
  • 收藏
  • 共同學(xué)習(xí),寫下你的評論
感謝您的支持,我會繼續(xù)努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進(jìn)行掃碼打賞哦
今天注冊有機(jī)會得

100積分直接送

付費(fèi)專欄免費(fèi)學(xué)

大額優(yōu)惠券免費(fèi)領(lǐng)

立即參與 放棄機(jī)會
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號

舉報(bào)

0/150
提交
取消