剑指Offer---2021/7/26(完结)

剑指 Offer 14- II. 剪绳子 II

在这里插入图片描述
方法一:
  按照老思路解法:剑指 Offer 14- I. 剪绳子,发现溢出。
代码:

class Solution {
public:
    int cuttingRope(int n) {
        vector<long long> dp(n + 1, 0);
        long long mod = 1e9 + 7;
        dp[2] = 1;
        for(int i = 3; i <= n; i++) {
            for(int j = 1; j <= i - 2; j++) {
                dp[i] = max(dp[i], max((long long)j * (i - j), dp[i - j] * j));
                dp[i] = dp[i] % mod;
            }
        }
        return dp[n];
    }
};

方法二:
  参考官方题解,核心思路是:尽可能把绳子分成长度为3的小段,这样乘积最大,证明略。
代码:

class Solution {
public:
    int cuttingRope(int n) {
        if(n < 4) {
            return n - 1;
        }
        long long mod = 1e9 + 7;
        int res = 1;
        while(n > 4) {
            res = (res % mod) * 3 % mod;
            n -= 3;
        }
        res = (res % mod) * n % mod;
        return res;
    }
};

剑指 Offer 20. 表示数值的字符串

在这里插入图片描述
分析:
  模拟,参考官方题解。
代码:

class Solution {
public:
    bool scan_integer(string &s, int &i) {
        int temp = i;
        if(i < s.size() && (s[i] == '+' || s[i] == '-'))
            ++i;
        return scan_unsigned_integer(s, i);
    }

    bool scan_unsigned_integer(string &s, int &i) {
        int temp = i;
        while(i < s.size() && isdigit(s[i]))
            ++i;
        return i > temp;
    }

    bool isNumber(string s) {
        //指针,记录扫描到s的哪个字符了
        int i = 0;

        //跳过初始的空格
        for(; i < s.size(); ++i)
            if(s[i] != ' ')
                break;

        //先判断打头的字符是不是一个有符号整数
        bool flag = scan_integer(s, i);
        
        //如果有小数点
        if(s[i] == '.') {
            ++i;
            //小数点的前后至少有一个整数
            //注意:这里要先判断小数点后是否有无符号整数!!!
            flag = scan_unsigned_integer(s, i) || flag;
        }

        //如果有e
        if(s[i] == 'e' || s[i] == 'E') {
            ++i;
            //e后面必须存在有符号整数
            flag = flag && scan_integer(s, i);
        }
        //最后必须以空格收尾
        for(; i < s.size(); ++i) {
            if(s[i] != ' ') {
                flag = false;
                break;
            }
        }
        return flag;
    }
};

剑指 Offer 37. 序列化二叉树

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

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Codec {
public:
    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        string str = "";
        //层次遍历
        if(!root) {
            return "";
        }
        queue<TreeNode*> que;
        que.push(root);
        while(!que.empty()) {
            TreeNode* fr = que.front();
            que.pop();
            if(fr) {
                str += to_string(fr->val);
                str += ",";
                que.push(fr->left);
                que.push(fr->right);  //这里不需要判断是否为NULL
            }else {
                str += "NULL,";
            }
        }
        return str;
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        vector<string> res;
        //拆分
        if(data == "") {
            return NULL;
        }
        int n = data.size();
        //cout << data;
        for(int i = 0; i < n; i++) {
            int j = i;
            while(data[j] != ',') {
                j++;
            }
            string temp = data.substr(i, j - i);
            if(temp == "NULL") {
                res.push_back("NULL");
            }else {
                res.push_back(data.substr(i, j - i));
            }
            i = j;
        }
        //建树
        TreeNode* root = new TreeNode(atoi(res[0].c_str()));
        int ind = 1;
        queue<TreeNode*> que;
        que.push(root);
        while(!que.empty()) {
            TreeNode* fr = que.front();
            que.pop();
            //左子树
            if(res[ind] == "NULL") {
                fr->left = NULL;
            }else {
                fr->left = new TreeNode(atoi(res[ind].c_str()));
                que.push(fr->left);
            }
            ind++;
            //右子树
            if(res[ind] == "NULL") {
                fr->right = NULL;
            }else {
                fr->right = new TreeNode(atoi(res[ind].c_str()));
                que.push(fr->right);
            }
            ind++;
        }
        return root;
    }
};

// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.deserialize(codec.serialize(root));

剑指 Offer 59 - II. 队列的最大值

在这里插入图片描述
方法一:
  暴力求解。
代码:

class MaxQueue {
public:
    queue<int> que;
    vector<int> res;
    MaxQueue() {

    }
    
    int max_value() {
        if(que.empty()) {
            return -1;
        }
        return *max_element(res.begin(), res.end());
    }
    
    void push_back(int value) {
        que.push(value);
        res.push_back(value);
    }
    
    int pop_front() {
        if(que.empty()) {
            return -1;
        }
        int t = que.front();
        que.pop();
        res.erase(res.begin());
        return t;
    }
};

/**
 * Your MaxQueue object will be instantiated and called as such:
 * MaxQueue* obj = new MaxQueue();
 * int param_1 = obj->max_value();
 * obj->push_back(value);
 * int param_3 = obj->pop_front();
 */

方法二:
  双端队列。
代码:

class MaxQueue {
    queue<int> q;
    deque<int> d;
public:
    MaxQueue() {
    }
    
    int max_value() {
        if (d.empty())
            return -1;
        return d.front();
    }
    
    void push_back(int value) {
        while (!d.empty() && d.back() < value) {
            d.pop_back();
        }
        d.push_back(value);
        q.push(value);
    }
    
    int pop_front() {
        if (q.empty())
            return -1;
        int ans = q.front();
        if (ans == d.front()) {
            d.pop_front();
        }
        q.pop();
        return ans;
    }
};

剑指 Offer 60. n个骰子的点数

在这里插入图片描述
分析:
  动态规划,参考官方题解。
代码:

class Solution {
public:
    vector<double> dicesProbability(int n) {
        vector<vector<double>> dp(n + 1, vector<double>(n + 5 * n + 1, .0));
        for(int j = 1; j <= 6; j++) {
            dp[1][j] = 1.0/6;
        }
        for(int i = 2; i <= n; i++) {
            for(int j = i; j < i + 5 * i + 1; j++) {
                double res = 0;
                for(int k = 1; k <= 6; k++) {
                    if(j - k < 0) {
                        continue;
                    }
                    res += dp[i - 1][j - k] / 6;
                }
                dp[i][j] = res;
            }
        }
        return vector<double>(dp[n].begin() + n, dp[n].end());
    }
};

剑指 Offer 67. 把字符串转换成整数

在这里插入图片描述
分析:
  模拟。
代码:

class Solution {
public:
    int strToInt(string str) {
        int i = 0;
        //1. 过滤掉前置空格,直到不为空格的字符。
        while(i < str.size() && str[i] == ' '){
            ++i;
        }
        if(i>=str.size()){
            return 0;
        }
        bool sign=false;
        //提取+,-符号。
        if(str[i] == '-'){
            sign=true;
            ++i;
        }else if(str[i] == '+'){
            ++i;
        }
        //
        if(i >= str.size()){
            return 0;
        }
        if(!isdigit(str[i])){
            return 0;
        }
        long long ans = 0;
        //提取整数部分。累加过程中,如果正数 > INT_MAX时,返回INT_MAX. 如果负数 < INT_MIN时,返回INT_MIN.
        while(i < str.size() && isdigit(str[i])){
            ans = ans*10 +(str[i] - '0');
            if(!sign && ans > INT_MAX){
                return INT_MAX;
            }else if(sign && -ans < INT_MIN){
                return INT_MIN;
            }
            ++i;
        }

        return sign ? -ans : ans;
    }
};

剑指 Offer 33. 二叉搜索树的后序遍历序列

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

class Solution {
public:
    bool verifyPostorder(vector<int>& postorder) {
        const int n = postorder.size();
        return recur(postorder,0,n-1);
    }

    bool recur(vector<int>& postorder,int l,int r) {
        if(l >= r) {
            return true;
        }
        int i = l;
        while(i < r && postorder[i] < postorder[r]) ++i;//找到右子树序列的第一个
        if(i == r) {
            return recur(postorder,l,r-1); //没有右子树序列,对应的数是只有左子树的单支树,递归考虑左子树
        }
        int tmp = i;//存储找到的右子树序列的第一个位置
        while(i < r && postorder[i] > postorder[r]) ++i;//判断右子树序列的元素是否都比根节点大
        if(i < r) return false;
        return recur(postorder,l,tmp-1) && recur(postorder,tmp, r-1);//递归考虑左子树和右子树
    }
};
  • 2
    点赞
  • 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、付费专栏及课程。

余额充值