6.27 note | 树形dp | 推理二叉树

发布于:2025-06-29 ⋅ 阅读:(17) ⋅ 点赞:(0)

hash删除

hash.erase(key)

lcr172

找区间

简单的开区间二分

两次二分,找到左右边界

target+1找上边界的设计:

target+1不在数组中是否存在影响呢?

 

class Solution {
public:
//开区间写法
    int lowwer(vector<int>& nums,int targ)
{
    int l=-1,r=nums.size();
    while(l+1<r)
    {
        int mid=l+(r-l)/2;
        if(nums[mid]<targ)
            l=mid;
        else r=mid;
    }
    return l;
}

    int countTarget(vector<int>& scores, int target)
    {
        int l=lowwer(scores,target);
        int r=lowwer(scores,target+1);
        return r-l;
    }
};

谨记 我们找的是开区间,利用顺序也可以这么计数

int countTarget(vector<int>& scores, int target) 
    {
        
        int l=lowwer(scores,target)+1;
        int cnt=0;
        while(l<scores.size() && scores[l]==target)
        {
            cnt++;
            l++;
        }
        
        return cnt;
    }
};

 

经典例题:

知道二叉树 前中后遍历中的两个结果,反推二叉树

lcr134. 推理二叉树

分治

 class Solution {
public:
    TreeNode* deduceTree(vector<int>& preorder, vector<int>& inorder) {
        this->preorder = preorder;
        for(int i = 0; i < inorder.size(); i++)
            hmap[inorder[i]] = i;
        return recur(0, 0, inorder.size() - 1);
    }
private:
    vector<int> preorder;
    unordered_map<int, int> hmap;
    TreeNode* recur(int root, int left, int right) { 
        if(left > right) return nullptr;                        // 递归终止
        TreeNode* node = new TreeNode(preorder[root]);          // 建立根节点
        int i = hmap[preorder[root]];                           // 划分根节点、左子树、右子树
        node->left = recur(root + 1, left, i - 1);              // 开启左子树递归
        node->right = recur(root + i - left + 1, i + 1, right); // 开启右子树递归
        return node;                                            // 回溯返回根节点
    }
};
 

lc1638.统计只差一个字符的子串

 暴力

 class Solution {
public:
    int countSubstrings(string s, string t) {
        int m = s.size();
        int n = t.size();
        int ans = 0;
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                int diff = 0;
                for (int k = 0; i + k < m && j + k < n; ++k) {
                    diff += (s[i + k] != t[j + k]);

                    if (diff > 1) {
                        break;
                    }
                    if (diff == 1) {
                        ++ans;
                    }
                }
            }
        }
        return ans;
    }
};

dp

 

 

lc337.打家劫舍iii

pair<int,int> dfs

return {rob,not_rob}

 

利用return 归,后序计算,返回子树结果,自底向上

 class Solution {

    pair<int, int> dfs(TreeNode* node) {

        if (node == nullptr)

      { // 递归边界

            return {0, 0}; // 没有节点,怎么选都是 0

        }

        auto [l_rob, l_not_rob] = dfs(node->left); // 递归左子树

        auto [r_rob, r_not_rob] = dfs(node->right); // 递归右子树

        int rob = l_not_rob + r_not_rob + node->val; // 选

        int not_rob = max(l_rob, l_not_rob) + max(r_rob, r_not_rob); // 不选

        return {rob, not_rob};

    }

 

public:

    int rob(TreeNode* root) {

        auto [root_rob, root_not_rob] = dfs(root);

        return max(root_rob, root_not_rob); // 根节点选或不选的最大值

    }

};

 

扩展

没有上司的舞会

 

综合

 

lc2014. 重复k次的最长子序列

可以拆分为后面的两道=

枚举排列➕判断子序列

 

 

 

lc392.判断子序列

 

class Solution {

public:

    bool isSubsequence(string s, string t) {

        int i=0,j=0;

        while(i<s.size() && j<t.size())

        {

            if(s[i]==t[j])

                i++;

            j++;

        }

        return i==s.size();

    }

};

lc47. 全排列 II

 

class Solution {
public:
    vector<vector<int>> ret;
    vector<int> path;
    vector<bool> check;

    vector<vector<int>> permuteUnique(vector<int>& nums) 
    {
        //排序
        sort(nums.begin(),nums.end());
        check.resize(nums.size(),false); //初始化数组

        dfs(nums,0);
        return ret;
    }

    void dfs(vector<int>& nums,int pos)
    {
        if(path.size()==nums.size())//终止条件
        {
            ret.push_back(path);
            return;
        }

        for(int i=0;i<nums.size();i++)//遍历所有元素
        {
    //legal
            if(check[i]==false && (i==0 || nums[i]!=nums[i-1] || check[i-1]==true))
        {
            check[i]=true;
            path.push_back(nums[i]);

            dfs(nums,i);

            check[i]=false;//处理标记
            path.pop_back();

                }   
                     }
    }
};

 

lc2673. 路径值相等的最小代价

自底向上,取最大值补全

ans等于做差

 

class Solution {

public:

    int minIncrements(int n, vector<int>& cost) {

        int ans = 0;

        function<int(int)> dfs = [&](int u)

{

            if(u >= n) return 0;

            int l = dfs(u*2 + 1);   //+1

            int r = dfs(u*2 + 2); 
   //+2   数组下标为0 起始
   
            ans += abs(l-r);   //加上差的绝对值

            return cost[u] + max(l, r);

//补全为最大值

        };

        dfs(0);

        return ans;

    }

};


取出hash第一个次数为例的方法

int cnt=hash.begin()->second;

 


网站公告

今日签到

点亮在社区的每一天
去签到