剑指Offer II --- 2021/9/5

剑指 Offer II 104. 排列的数目

在这里插入图片描述
分析:
  动态规划:设dp[i]表示总和为i的组合的个数,最终需要返回dp[target];初始条件:dp[0] = 1;转移方程:dp[i]等于所有dp[i - x]之和,x是nums中的元素。
代码:

class Solution {
public:
    int combinationSum4(vector<int>& nums, int target) {
        vector<long long> dp(target + 1);
        dp[0] = 1;
        for(int i = 1; i <= target; i++) {
            for(int& x : nums) {
                if(x <= i && dp[i] + dp[i - x] <= INT_MAX) {
                    dp[i] += dp[i - x];
                }
            }
        }
        return dp[target];
    }
};

剑指 Offer II 105. 岛屿的最大面积

岛屿最大面积

剑指 Offer II 041. 滑动窗口的平均值

在这里插入图片描述
分析:
  双端队列deque:元素入队后如果队列长度大于滑动窗口长度,则队头元素出队。
代码:

class MovingAverage {
public:
    /** Initialize your data structure here. */
    long long sum = 0;
    int max_cnt = 0;
    deque<int> que;
    MovingAverage(int size) {
        max_cnt = size;
    }
    
    double next(int val) {
        que.push_back(val);
        sum += val;
        if(que.size() > max_cnt) {
            sum -= que.front();
            que.pop_front();
        }
        // cout << sum << " " << que.size() << endl;
        double x = (double)sum / que.size();
        return x;
    }
};

/**
 * Your MovingAverage object will be instantiated and called as such:
 * MovingAverage* obj = new MovingAverage(size);
 * double param_1 = obj->next(val);
 */

剑指 Offer II 106. 二分图

在这里插入图片描述
分析:
  并查集:对每一个节点的节点数组,如果存在一个跟该节点在一个集合的节点,说明一条边的两个节点在同一个集合里面,不是二分图,返回false;否则将节点数组里面的所有节点合并到一个集合里面。
代码:

class Solution {
private:
    vector<int> par;
    void init(int n) {
        par.resize(n);
        for(int i = 0; i < n; i++) {
            par[i] = i;
        }
    }
    
    int get_root(int x) {
        if(par[x] != x) {
            par[x] = get_root(par[x]);
        }
        return par[x];
    }
    
    void merge(int x, int y) {
        par[get_root(x)] = get_root(y);
    }
    
    bool check(int x, int y) {
        return get_root(x) == get_root(y);
    }
    
public:
    bool isBipartite(vector<vector<int>>& graph) {
        int n = graph.size();
        init(n);
        for(int i = 0; i < n; i++) {
            for(int& x : graph[i]) {
                if(check(i, x)) {
                    return false;
                }
            }
            for(int j = 1; j < graph[i].size(); j++) {
                merge(graph[i][0], graph[i][j]);
            }
        }
        return true;
    }
};

剑指 Offer II 043. 往完全二叉树添加节点

在这里插入图片描述
分析:
  二叉树的结点序号如果从0开始,则序号为i的左右子树结点(如果有的话)序号分别为2i+1和2i+2。
代码:

/**
 * 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 CBTInserter {
public:
    vector<TreeNode*> nodes;
    CBTInserter(TreeNode* root) {
        if(root == NULL) {
            return;
        }
        //建树
        queue<TreeNode*> que;
        que.push(root);
        while(!que.empty()) {
            TreeNode* fr = que.front();
            nodes.push_back(fr);
            que.pop();
            if(fr->left) {
                que.push(fr->left);
            }
            if(fr->right) {
                que.push(fr->right);
            }
        }
    }
    
    int insert(int val) {
        TreeNode* x = new TreeNode(val);
        nodes.push_back(x);
        int ind = nodes.size() - 1;
        int fa = 0;
        if(ind & 1) {
            //左子树
            fa = (ind - 1) / 2;
            nodes[fa]->left = x;
        }else {
            //右子树
            fa = (ind - 2) / 2;
            nodes[fa]->right = x;
        }
        return nodes[fa]->val;
    }
    
    TreeNode* get_root() {
        return nodes.size() == 0 ? NULL : nodes[0];
    }
};

/**
 * Your CBTInserter object will be instantiated and called as such:
 * CBTInserter* obj = new CBTInserter(root);
 * int param_1 = obj->insert(val);
 * TreeNode* param_2 = obj->get_root();
 */

剑指 Offer II 107. 矩阵中的距离

01矩阵

剑指 Offer II 044. 二叉树每层的最大值

在这里插入图片描述
分析:
  层序遍历。
代码:

/**
 * 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:
    vector<int> largestValues(TreeNode* root) {
        vector<int> res;
        if(root == NULL) {
            return res;
        }
        queue<TreeNode*> que;
        que.push(root);
        while(!que.empty()) {
            int n = que.size();
            int re = INT_MIN;
            for(int i = 0; i < n; i++) {
                TreeNode* fr = que.front();
                que.pop();
                re = max(re, fr->val);
                if(fr->left) {
                    que.push(fr->left);
                }
                if(fr->right) {
                    que.push(fr->right);
                }
            }
            res.push_back(re);
        }
        return res;
    }
};

剑指 Offer II 045. 二叉树最底层最左边的值

找树左下角的值

剑指 Offer II 046. 二叉树的右侧视图

二叉树的右视图

剑指 Offer II 047. 二叉树剪枝

在这里插入图片描述
分析:
  递归。
代码:

/**
 * 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:
    TreeNode* pruneTree(TreeNode* root) {
        if(root == NULL) {
            return NULL;
        }
        TreeNode* lt = pruneTree(root->left);
        TreeNode* rt = pruneTree(root->right);
        if(root->val == 0 && lt == NULL && rt == NULL) {
            return NULL;
        }
        root->left = lt;
        root->right = rt;
        return root;
    }
};

剑指 Offer II 109. 开密码锁

在这里插入图片描述
分析:
  求从一个状态变化到另一个状态的最短步骤,往往就会想到BFS,此题与2017蓝桥杯省赛:青蛙跳杯子(BFS求最短路径长度)类似。
代码:

class Solution {
public:
    int openLock(vector<string>& deadends, string target) {
        //bfs
        queue<pair<string, int>> que;
        unordered_set<string> dead(deadends.begin(), deadends.end());
        unordered_set<string> st;
        if(dead.count("0000")) {
            return -1;
        }
        st.insert("0000");
        que.push(make_pair("0000", 0));
        int dirs[8][2] = {{0, 1}, {0, -1}, {1, 1}, {1, -1}, {2, 1}, {2, -1}, {3, 1}, {3, -1}};
        while(!que.empty()) {
            auto p = que.front();
            string x = p.first;
            int step = p.second;
            que.pop();
            if(x == target) {
                return step;
            }
            for(int k = 0; k < 8; k++) {
                string t = x;
                int i = dirs[k][0];
                if(t[i] == '0' && dirs[k][1] == -1) {
                    t[i] = '9';
                }else if(t[i] == '9' && dirs[k][1] == 1) {
                    t[i] = '0';
                }else {
                    t[i] += dirs[k][1];
                }
                if(dead.count(t) == 0 && st.count(t) == 0) {
                    que.push(make_pair(t, step + 1));
                    st.insert(t);
                }
            }
        }
        return -1;
    }
};

总结一下层序遍历的题目:

  1. 二叉树的锯齿形层序遍历
  2. 二叉树的右视图
  3. 填充每个节点的下一个右侧节点指针
  4. 二叉树的层序遍历
  5. 剑指 Offer 32 - II. 从上到下打印二叉树 II
  6. 剑指 Offer 55 - I. 二叉树的深度
  7. 剑指 Offer 32 - III. 从上到下打印二叉树 III
  8. 找树左下角的值
  9. 二叉树的层平均值
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cyril_KI

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值