栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

剑指offer

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

剑指offer

抽象建模能力
  • 剑指 Offer 60. n个骰子的点数
    • 题目
    • 代码
  • 剑指 Offer 61. 扑克牌中的顺子
    • 题目
    • 代码
  • 剑指 Offer 62. 圆圈中最后剩下的数字
    • 题目
    • 代码
  • 剑指 Offer 63. 股票的最大利润
    • 题目
    • 代码

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

代码

方法一:迭代解法

class Solution {
public:
    vector dicesProbability(int n) {
        //动态规划
        int min = n, max = n * 6;
        double dp[n + 1][max + 1];
        //结果数组的个数有n*5-1个
        vector res(n * 5 + 1);
        //base case 
        for(int j = 1; j <= 6; j++) {
            dp[1][j] = 1 / 6.0;
        }
        //状态转移
        for(int i = 2; i <= n;i++) {
            for(int j = i; j <= i * 6 ;j++) {
                for(int k = 1; k <= 6; k++) {
                    if(j - k > 0) {
                        //通过i-1个骰子扔出点数j-k
                        dp[i][j] = dp[i][j] + dp[i - 1][j - k]/6;
                    }else {
                        break;
                    }
                }
            }
        }
        for(int i = 0;i <= 5*n;i++){
            res[i] = dp[n][n+i];
        }
        return res;
    }
};

方法二:递归解法

class Solution {
public:
    vector dicesProbability(int n) {
        //初始化1个骰子的概率数组
        vector dp(6, 1.0 / 6.0);
        for(int i = 2; i <= n; i++) {
            //新数组存放骰子的每个总数和出现的概率
            //骰子总数为i时,骰子可能出现的点数i~6i,长度6i-i+1
            vector temp(5 * i + 1, 0);
            //遍历骰子数为i-1的概率数组,计算骰子数为i时点数的概率
            for(int j = 0; j < dp.size(); j++) {
                for(int k = 0; k < 6; k++) {
                    temp[j + k] = temp[j + k] + dp[j] / 6.0;
                }
            }
            骰子总数为i的数组赋值骰子总数为i-1的数组
            dp = temp;
        }
        return dp;
    }
};
剑指 Offer 61. 扑克牌中的顺子 题目

代码

首先要理解第二个数据用例的意思是大小王可以替代任何牌。
再遍历数组,找出数组的最大值和最小值,除开大小王即0之外,数组中不能有相等的数字,如果有则返回false,如果最大值和最小值相差超过5也返回false。

class Solution {
public:
    bool isStraight(vector& nums) {
        //注意大小王能替代任意牌
        int max = 0, min = 14;
        setrep;
        for(int i = 0; i < 5; i++) {
            if(nums[i] == 0) {
                continue;
            }
            max = max > nums[i] ? max : nums[i];
            min = min < nums[i] ? min : nums[i];
            if(rep.find(nums[i]) != rep.end()) {
                return false;
            }
            rep.insert(nums[i]);

        }
        return max - min < 5;
    }
};
剑指 Offer 62. 圆圈中最后剩下的数字 题目

本来以为该题和“CCF201712-2 游戏”这个题目时一样的原理,但仔细看是不一样的。该题是每次淘汰之后,重新从0开始记数到m个数淘汰它,而后者报数一直增加,遇到k的倍数或者个位数为k则淘汰。

代码

本题是著名的 “约瑟夫环” 问题,可使用 动态规划 解决。
长度为 n 的序列会先删除第 m % n 个元素,然后剩下一个长度为 n - 1 的序列。那么,我们可以求解 f(n - 1, m)

class Solution {
public:
    int lastRemaining(int n, int m) {
        int x = 0;
        for (int i = 2; i <= n; i++) {
            x = (x + m) % i;
        }
        return x;
    }
};
剑指 Offer 63. 股票的最大利润 题目

代码

法一:
双层for循环遍历

class Solution {
public:
    int maxProfit(vector& prices) {
        //动态规划
        int n = prices.size();
        int maxvalue = 0;
        int sell = 0;
        //外层找买入
        for(int i = 0; i < n; i++){
            //内层找卖出
            sell = prices[i];
            for(int j = i + 1; j < n; j++) {
               sell = max(sell, prices[j]);
            }
             maxvalue = max(maxvalue, sell - prices[i]);
        }
        return maxvalue;
        
    }
};

法二:
动态规划(未压缩)

class Solution {
public:
    int maxProfit(vector& prices) {
        int n = prices.size();
        if(n == 0) {
            return 0;
        }
        //dp[i][j],i表示天数,j表示当前持有状态,0表示未持有,1表示持有
        vector>dp(n, vector(2));
        //base case
        dp[0][0] = 0;
        dp[0][1] = -prices[0];
        //状态转移
        for(int i = 1; i < n; i++) {
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
            dp[i][1] = max(-prices[i], dp[i - 1][1]);
        }
        return dp[n - 1][0];
    }
};

法三:
压缩后的动态规划

class Solution {
public:
    int maxProfit(vector& prices) {
        int n = prices.size();
        if(n == 0) {
            return 0;
        }
        //base case
        int dp_i_0 = 0, dp_i_1 = -prices[0];
        //状态转移
        for(int i = 1; i < n; i++) {
            // dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])
            dp_i_0 = max(dp_i_0, dp_i_1 + prices[i]);
            // dp[i][1] = max(dp[i-1][1], -prices[i])
            dp_i_1 = max(-prices[i], dp_i_1);
        }
        return dp_i_0;
    }
};
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1037771.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号