二叉树——leetcode

宫水三叶

230. 二叉搜索树中第K小的元素 - 力扣(LeetCode)

二叉搜索树的中序遍历是有序的,因此我们只需要对二叉搜索树执行中序遍历,并返回第 k 小的值即可。

class Solution {
public:
    int ans = -1;
    int cnt = 0;
    int kthSmallest(TreeNode* root, int k) {
        //中序遍历
        dfs(root, k);
        return ans;
    }
    void dfs(TreeNode* root, int k)
    {
        if(ans != -1) return ;//找到答案。
        if(root == nullptr) return ;
        dfs(root->left, k);
        cnt += 1;
        if(cnt == k) ans = root->val;//这说正好是根为第k小
        dfs(root->right, k);
    }
};

240. 搜索二维矩阵 II - 力扣(LeetCode)

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int n = matrix.size(), m = matrix[0].size();
        int x = 0, y = m - 1;
        while(x < n && y >= 0)
        {
            if(target == matrix[x][y]) return true;
            else if(target > matrix[x][y]) x ++;
            else y --;
        }
        return false;
    }
};

297. 二叉树的序列化与反序列化 题解 - 力扣(LeetCode)

istringstream、ostringstream、stringstream 类介绍
层序遍历

class Codec {
public:

    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        ostringstream out;
        queue<TreeNode*> q;
        q.push(root);
        while(!q.empty())//层序遍历
        {
            TreeNode* tmp = q.front();
            q.pop();
            if(tmp)
            {
                out << tmp->val << " ";
                q.push(tmp->left);
                q.push(tmp->right);
            }
            else out << "null ";
        }
        return out.str();
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        istringstream input(data);
        string val;
        vector<TreeNode*> vec;
        while(input >> val)
        {
            if(val == "null")
                vec.push_back(NULL);
            else
                vec.push_back(new TreeNode(stoi(val)));
        }
        int j = 1;//j是儿子i是父亲
        for(int i = 0; i < vec.size(); i ++ )
        {
            if(vec[i] == NULL) continue;
            if(j < vec.size()) vec[i]->left = vec[j ++];
            if(j < vec.size()) vec[i]->right = vec[j ++];
        }
        return vec[0];
    }
};

前序遍历

class Codec {
public:
    ostringstream out;
    istringstream input;
    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        dfs1(root);
        cout << out.str() << endl;
        return out.str();
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        cout << data;
        input.str(data);//输入到input中
        string sroot;
        input >> sroot;
        if(sroot == "NULL") return nullptr;
        TreeNode* root = new TreeNode(stoi(sroot));
        dfs2(root);
        return root;
    }
    void dfs1(TreeNode* root)
    {
        //前序遍历
        if(root == nullptr)
        {
            out << "NULL ";
            return;
        }
        out << to_string(root->val) << " ";
        dfs1(root->left);
        dfs1(root->right);
    }
    void dfs2(TreeNode* root)
    {
        if(root == nullptr) return;
        string l, r;
        //有了根节点,先找左树再找右数
        input >> l;
        if(l != "NULL") root->left = new TreeNode(stoi(l));
        dfs2(root->left);
        
        input >> r;
        if(r != "NULL") root->right = new TreeNode(stoi(r));
        dfs2(root->right);
    }
};

437. 路径总和 III - 力扣(LeetCode)

class Solution {
public:
    int ans = 0;
    int pathSum(TreeNode* root, int targetSum) {
       dfs1(root, targetSum);
       return ans;
    }
    int dfs2(TreeNode* root, int sum)//以root为根节点的和为sum的路径数量       
    {
        if(root == nullptr) return 0;
        int res = 0;
        if(root->val == sum) res ++;//可能还可以往下走

        res += dfs2(root->right, sum - root->val);
        res += dfs2(root->left, sum - root->val);
        return res;
    }
    void dfs1(TreeNode* root, int sum)
    {
        if(root == nullptr) return ;
        ans += dfs2(root, sum);

        dfs1(root->right, sum);
        dfs1(root->left, sum);
    }
};
class Solution {
public:
    unordered_map<long long, int> prefix;

    int dfs(TreeNode *root, long long curr, int targetSum) {
        if (!root) {
            return 0;
        }

        int ret = 0;
        curr += root->val;
        if (prefix.count(curr - targetSum)) {
            ret = prefix[curr - targetSum];
        }

        prefix[curr]++;
        ret += dfs(root->left, curr, targetSum);
        ret += dfs(root->right, curr, targetSum);
        prefix[curr]--;

        return ret;
    }

    int pathSum(TreeNode* root, int targetSum) {
        prefix[0] = 1;
        return dfs(root, 0, targetSum);
    }
};

563. 二叉树的坡度 - 力扣(LeetCode)

class Solution {
public:
    int ans = 0;
    int findTilt(TreeNode* root) {
        dfs(root);
        return ans;
    }
    int dfs(TreeNode* root)
    {
        if(root == nullptr) return 0;
        int ls = dfs(root->right);
        int rs = dfs(root->left);
        ans += abs(ls - rs);
        return ls + rs + root->val;
    }
};
class Solution {
public:
    int findTilt(TreeNode* root) {
       if(root == nullptr) return 0;
       return findTilt(root->left) + findTilt(root->right) + abs(get(root->right) - get(root->left));
    }
    int get(TreeNode* root)
    {
        if(root == nullptr) return 0;
        return get(root->left) + get(root->right) + root->val;
    }
};

783. 二叉搜索树节点最小距离 - 力扣(LeetCode)

class Solution {
public:
    int ans = 1e9;
    int minDiffInBST(TreeNode* root) {
        int a = -1, b = 1e9;
        dfs(root, a, b);			
        return ans;
    }
    void dfs(TreeNode* root, int &a, int &b)//最大、最小
    {
        if(root == nullptr) return;
        int m1 = -1, m2 = 1e9, m3 = -1, m4 = 1e9;
        dfs(root->left, m1, m2);
        dfs(root->right, m3, m4); 
        if(m1 != -1) ans = min(ans, abs(root->val - m1));
        if(m4 != 1e9) ans = min(ans, abs(root->val - m4));
        a = max({a, m1, m3, root->val});
        b = min({b, m2, m4, root->val});
    }
};

中序遍历

class Solution {
public:         
    int last = -1;
    int ans = 1e9;
    int minDiffInBST(TreeNode* root) {
        dfs(root);
        return ans;
    }
    void dfs(TreeNode* root)
    {
        if(root == nullptr) return;
        dfs(root->left);
        if(last >= 0) ans = min(ans, abs(last - root->val));
        last = root->val;
        dfs(root->right);
    }
};

863. 二叉树中所有距离为 K 的结点 - 力扣(LeetCode)

class Solution {
public:
    vector<int> ret;
    unordered_map<TreeNode*, TreeNode*> mp;
    unordered_set<TreeNode*> se;
    vector<int> distanceK(TreeNode* root, TreeNode* target, int k) {
        dfs(root);//找到父亲节点
        calc(target, k);//从target开始找
        return ret;
    }
    void calc(TreeNode* t, int k)
    {
        if(!t || se.count(t)) return;//寻找过了
        se.insert(t);
        if(!k)
        {
            ret.push_back(t->val);
            return;
        }
        calc(t->left, k - 1);
        calc(t->right, k - 1);
        calc(mp[t], k - 1);
    }
    void dfs(TreeNode* t)
    {
        if(!t) return;
        if(t->left) mp[t->left] = t, dfs(t->left);
        if(t->right) mp[t->right] = t, dfs(t->right);
    }
};

938. 二叉搜索树的范围和 - 力扣(LeetCode)

class Solution {
public:
    int rangeSumBST(TreeNode* root, int low, int high) {
        if(root == nullptr) return 0;
        if(root->val < low || root->val > high) root->val = 0;
        return rangeSumBST(root->right, low, high) + rangeSumBST(root->left, low, high) + root->val;
    }
};

987. 二叉树的垂序遍历 - 力扣(LeetCode)

class Solution {
public:
    unordered_map<int, unordered_map<int,int>> mp;
    struct point
    {
        int x, y;
        vector<int> g;
        bool operator < (const point &rhs) const
        {
            if(y == rhs.y)
            return x < rhs.x;
            return y < rhs.y;        
        }
    }e[2000];
    int cnt = 0;
    int m1 = 0;
    int m2 = 0;
    vector<vector<int>> verticalTraversal(TreeNode* root) {
        e[cnt ++ ] = {0, 0, {root->val}};
        mp[0][0] = cnt - 1;
        dfs(root->right, 1, 1);
        dfs(root->left, 1, -1);
        sort(e, e + cnt);
        vector<vector<int>> ans(m2 - m1 + 1);
        for(int i = 0; i < cnt; i ++ )
        {
            if(e[i].g.size() > 1) sort(e[i].g.begin(), e[i].g.end());
            int index = e[i].y;//列
            for(int j = 0; j < e[i].g.size(); j ++ )
            {
                ans[index - m1].push_back(e[i].g[j]);
            }
        }
        return ans;
    }
    void dfs(TreeNode* root, int x, int y)
    {
        if(root == nullptr) return;
        if(!mp[x][y])
        {
            e[cnt].x = x, e[cnt].y = y;
            e[cnt].g.push_back(root->val);
            mp[x][y] = cnt;
            cnt ++;
        }
        else e[mp[x][y]].g.push_back(root->val);
        m2 = max(m2, y);//最大
        m1 = min(m1, y);//最小
        dfs(root->right, x + 1, y + 1);
        dfs(root->left, x + 1, y - 1);
    }
};

在这里插入代码片

993. 二叉树的堂兄弟节点 - 力扣(LeetCode)

class Solution {
public:
    int dx, dy, fx, fy;
    bool isCousins(TreeNode* root, int x, int y) {
        dfs(root, x, y, 0, root->val);
        return dx == dy && fx != fy;
    }
    void dfs(TreeNode* root, int x, int y, int dep, int fa)
    {
        if(root == nullptr) return;
        dfs(root->right, x, y, dep + 1,  root->val);
        dfs(root->left, x, y, dep + 1, root->val);
        if(root->val == x) dx = dep, fx = fa;
        if(root->val == y) dy = dep, fy = fa;
    }
};

class Solution {
public:
    int dep[200];//200层的数量
    vector<int> ans;
    vector<int> pathInZigZagTree(int label) {
        //首先判断是哪一行
        int sum = 0;
        int p;
        for(int i = 1; i <= label; i ++ )
        {
            sum += pow(2, i - 1);
            dep[i] = sum;
            if(sum >= label)
            {
                p = i;
                break;
            }
        }
        dfs(label, p);
        reverse(ans.begin(), ans.end());
        return ans;
    }
    void dfs(int x, int p)
    {
        ans.push_back(x);
        if(x == 1)
            return;
        int y;//经典值
        if(p % 2 == 0) //偶数行,从右往左
        {
            y = dep[p] - x + 1 + dep[p - 1];
            dfs(y / 2, p - 1);//上一行的真实值
        }
        else
        {
            y = x;
            dfs(dep[p - 1] + (dep[p - 1] + 1)/ 2 - y / 2, p - 1);
        }
    }
};

1104. 二叉树寻路 - 力扣(LeetCode)

class Solution {
public:
    int dep[200];//200层的数量
    vector<int> ans;
    vector<int> pathInZigZagTree(int label) {
        //首先判断是哪一行
        int sum = 0;
        int p;
        for(int i = 1; i <= label; i ++ )
        {
            sum += pow(2, i - 1);
            dep[i] = sum;
            if(sum >= label)
            {
                p = i;
                break;
            }
        }
        dfs(label, p);
        reverse(ans.begin(), ans.end());
        return ans;
    }
    void dfs(int x, int p)
    {
        ans.push_back(x);
        if(x == 1)
            return;
        int y;
        if(p % 2 == 0) //偶数行,从右往左
        {
            y = dep[p] - x + 1 + dep[p - 1];
            dfs(y / 2, p - 1);
        }
        else
        {
            y = x;
            dfs(dep[p - 1] + (dep[p - 1] + 1)/ 2 - y / 2, p - 1);
        }
    }
};

东哥

226. 翻转二叉树 - 力扣(LeetCode)


class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        //每个根节点的左右翻转
        if(root == nullptr) return root;
        invertTree(root->left);
        invertTree(root->right);
        swap(root->left, root->right);
        return root;
    }
};

117. 填充每个节点的下一个右侧节点指针 II - 力扣(LeetCode)

层序遍历

class Solution {
public:
//层序遍历
    Node* connect(Node* root) {
        queue<Node*> q;
        q.push(root);
        Node* last;
        int cnt = 0;
        while(!q.empty())
        {
            auto h = q.front();
            cnt ++;
            q.pop();
            if(!h) continue;
            if(pow(2, (int)log2(cnt)) != cnt) last->next = h;
            last = h;
            q.push(h->left);
            q.push(h->right);
        }
        return root;
    }
};

递归

class Solution {
public:
    Node* connect(Node* root) {
        if(root == NULL) return root;
        con(root->left, root->right);
        return root;
    }
    void con(Node* l, Node* r)
    {
        if(l == NULL) return;
        l->next = r;
        con(l->left, l->right);
        con(r->left, r->right);
        con(l->right, r->left);
    }
};

114. 二叉树展开为链表 - 力扣(LeetCode)

class Solution {
public:
    TreeNode* last;
    void flatten(TreeNode* root) {
        if(root == nullptr) return;
        TreeNode* l = root->left;//一定要记录下左右节点,因为后边可能改变
        TreeNode* r = root->right;
        if(last != nullptr)
        {
            last->left = nullptr;
            last->right = root;
        }
        last = root;
        flatten(l);
        flatten(r);
    }
};

105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)

106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)

654. 最大二叉树 - 力扣(LeetCode)

class Solution {
public:
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        return build(0, nums.size() - 1, nums);   
    }
    TreeNode* build(int l, int r, vector<int>& nums)
    {
        if(l > r) return nullptr;
        int p, ma = -1e9;
        for(int i = l; i <= r; i ++ )
        {
            if(nums[i] > ma)
            {
                ma = nums[i];
                p = i;
            }
        }
        TreeNode* root = new TreeNode(nums[p]);
        root->left = build(l, p - 1, nums);
        root->right = build(p + 1, r, nums);
        return root;
    }
};

652. 寻找重复的子树 - 力扣(LeetCode)

//序列化问题
class Solution {
public:
    unordered_map<string, int> mp;
    vector<TreeNode*> ans;
    vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
        xlh(root);
        return ans;
    }
    string xlh(TreeNode* root)
    {
        if(root == nullptr) return "NULL ";
        string res = "";
        res.append(xlh(root->left));
        res.append(xlh(root->right));//后序遍历
        res.append(to_string(root->val) + " ");//序列化一定要加空格
        mp[res] ++;//这种树的数量
        if(mp[res] == 2)//
            ans.push_back(root);
        return res;
    }
};

剑指 Offer 68 - II. 二叉树的最近公共祖先 - 力扣(LeetCode)

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {

        if (root == NULL || p == root || q == root) {
            return root;
        }

        TreeNode* l = lowestCommonAncestor(root->left, p, q);
        TreeNode* r = lowestCommonAncestor(root->right, p, q);
    
        return l == NULL ? r : (r == NULL ? l : root);
    
    }
};

补充

101. 对称二叉树 - 力扣(LeetCode)

对于一个节点左右节点,如果他们对称,那么是左节点的右节点与右节点的左节点对称。


class Solution {
public:
    bool check(TreeNode* l, TreeNode* r)
    {
        if(!l && !r) return true;
        if(!l || !r) return false;
        return l->val == r->val && check(l->left, r->right) && check(l->right, r->left);
    }
    bool isSymmetric(TreeNode* root) {
        return check(root, root);
    }
};

111. 二叉树的最小深度 - 力扣(LeetCode)

class Solution {
public:
    int minDepth(TreeNode* root) {
        if(!root) return 0;
        if(!root->left && !root->right) return 1;//到达叶子节点
        int m1 = minDepth(root->left);
        int m2 = minDepth(root->right);
        if(!root->left || !root->right) return m1 + m2 + 1;
        return min(m1, m2) + 1;
    }
};

236. 二叉树的最近公共祖先 - 力扣(LeetCode)

class Solution {
public:
    unordered_map<TreeNode*, bool> mp;
    TreeNode* ans;
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        //标记法, 第一次标记路径,第二次找到最后一个相交点
        dfs1(root, p);
        dfs2(root, q);
        return ans;
    }
    bool dfs1(TreeNode* root, TreeNode* p)
    {
        if(root == NULL) return false;
        if(root == p) 
        {
            mp[root] = true;
            return true;
        }
        return mp[root] = dfs1(root->left, p) || dfs1(root->right, p);
    }
    bool dfs2(TreeNode* root, TreeNode* q)
    {
        if(root == NULL || ans) return false;
        if(root == q)
        {
            if(mp[root]) ans = root;
            return true;
        }
        bool flag = dfs2(root->left, q) || dfs2(root->right, q);
        if(flag && ans == NULL && mp[root])//表明是通向q的, 而且还没有答案, 而且是通向p的
        {
            ans = root;
        }
        return flag;

    }
};

有三种情况,p、q在左树、p、q在右树、p、q一左一右。如果遇到pq那么就返回,如果一左一右就返回root,否则递归查找左右两个树

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(!root) return NULL;
        if(root == p || root == q) return root;
        TreeNode* l = lowestCommonAncestor(root->left, p, q);
        TreeNode* r = lowestCommonAncestor(root->right, p, q);
        if(!l)//pq在右边
            return r;
        if(!r)//pq在左边
            return l;
        else return root;
    }
};

337. 打家劫舍 III - 力扣(LeetCode)

树上dp

/**
 * Definition for a binary tree node.
 * 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) {}
 * };
 */
class Solution {
public:
    unordered_map<TreeNode*, unordered_map<int, int>> dp;
    int rob(TreeNode* root) {
        //打劫了父房子,不能打劫子房子
        dfs(root);
        return max(dp[root][0], dp[root][1]);
    }
    void dfs(TreeNode* root)
    {
        if(root == nullptr) return;
        dfs(root->left);
        dfs(root->right);
        dp[root][0] += max(dp[root->left][0], dp[root->left][1]);
        dp[root][0] += max(dp[root->right][0], dp[root->right][1]);

        dp[root][1] += dp[root->left][0] + root->val;
        dp[root][1] += dp[root->right][0];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值