题解 | #扔骰子#

扔骰子

http://www.nowcoder.com/practice/4921c3ebdffc4c4eab344fa78de89c67

题目描述

每个人可以扔面骰子,来获得个数
得分为任意选取个数中的某些数求和所不能得到的最小的正整数
问数组的得分与数组得分的大小关系

方法一 有序哈希表

解题思路

可以考虑使用C++的STL中的有序set存放每个数组可以得到的所有整数,然后遍历该set,找到不连续的最小正整数即为该数组的得分.
得到所有求和数很简单,两层循环即可做到.为了找到set中最小的不连续的正整数,比较直接的方法是从开始枚举,但是这样每次枚举需要在set中执行find操作,时间复杂度过高.一个优化方法是遍历一遍有序set,并且定义一个指针,每迭代一次,看迭代的数组是否是,以此判断是否连续.
以数组为为例,进行第二次迭代时,,set中的数字为,出现了不连续,所以返回值即为.

图片说明

代码示例

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param n int整型 n
     * @param m int整型 m
     * @param a int整型vector a
     * @param b int整型vector b
     * @return string字符串
     */
    // n:数组长度,a:数组
    // return:数组a的得分
    int cal(int n, vector<int>& a) {
        // num:用于存储数组a能得到的所有数字的set
        set<int> num;
        // 枚举所有数字
        for(int i = 0; i < n; i++) {
            int sum = 0;
            // 枚举第i个数字之后的数字
            for(int j = i; j < n; j++) {
                sum += a[j];
                num.insert(sum);
            }
        }

        // 遍历set,寻找最小的不连续的正整数
        int ret = 1;
        for(int t : num) {
            // set中存在ret,ret++
            if(t == ret) {
                ret++;
            }
            // set中不存在ret,返回ret
            else {
                return ret;
            }
        }
        return ret;
    }

    string Throwdice(int n, int m, vector<int>& a, vector<int>& b) {
        // 根据a,b得分返回
        if(cal(n, a) > cal(n, b))
            return "Happy";
        else
            return "Sad";
    }
};

复杂度分析

  • 时间复杂度:为了找到所有通过求和可以得到的数字,需要对数组进行两层循环的迭代,每次迭代需要在有序哈希表中插入一个数;为了找到set中不连续的最小正整数,需要对set迭代一次,所以时间复杂度为
  • 空间复杂度:使用set存储通过求和可以得到的数字,set的最大大小为,所以空间复杂度为

方法二 模拟+贪心

解题思路

可以通过贪心的思路进行模拟.与方法一相同,还是定义函数计算数组的得分.在函数中,先对数组进行排序,然后根据贪心的思路找到答案.具体来说,迭代到第个数时,我们贪心地认为新增加的范围是下图中黄色部分,即,因为是连续的,所以我们认为区间之内也是连续的.但是如果,之间的范围就出现了间断,就出现了不连续的情况,这时我们就找到了所需要的最小不连续的整数.根据此思路,我们可以模拟得出答案.

图片说明

代码示例

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param n int整型 n
     * @param m int整型 m
     * @param a int整型vector a
     * @param b int整型vector b
     * @return string字符串
     */
    // n:数组长度,a:数组
    // return:数组a的得分
    int cal(int n, vector<int>& a) {
        // 对数组排序
        sort(a.begin(), a.end());
        // 目前连续区间的上界
        int sum = 0;
        // 遍历数组
        for(int i = 0; i < n; i++) {
            // 数组新添加的区间与目前已有的连续区间之间存在间断
            if(a[i] > sum + 1)
                return sum + 1;
            // 更新连续区间的上界
            sum += a[i];
        }
        return sum + 1;
    }

    string Throwdice(int n, int m, vector<int>& a, vector<int>& b) {
        // 根据a,b得分返回
        if(cal(n, a) > cal(n, b))
            return "Happy";
        else
            return "Sad";
    }
};

复杂度分析

  • 时间复杂度:需要对数组a,b分别进行一次遍历和一次排序,时间复杂度为
  • 空间复杂度:使用了常数个辅助变量,空间复杂度为
全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务