LeetCode破解之缺失的观测数据

91 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情

题目描述

现有一份 n + m 次投掷单个 六面 骰子的观测数据,骰子的每个面从 16 编号。观测数据中缺失了 n 份,你手上只拿到剩余 m 次投掷的数据。幸好你有之前计算过的这 n + m 次投掷数据的 平均值

给你一个长度为 m 的整数数组 rolls ,其中 rolls[i] 是第 i 次观测的值。同时给你两个整数 ansn

返回一个长度为 n 的数组,包含所有缺失的观测数据,且满足这 n + m 次投掷的 平均值ans 。如果存在多组符合要求的答案,只需要返回其中任意一组即可。如果不存在答案,返回一个空数组。

k 个数字的 平均值 为这些数字求和后再除以 k

注意 ans 是一个整数,所以 n + m 次投掷的总和需要被 n + m 整除。

示例 1:

输入:rolls = [3,2,4,3], ans = 4, n = 2
输出:[6,6]
解释:所有 n + m 次投掷的平均值是 (3 + 2 + 4 + 3 + 6 + 6) / 6 = 4

示例 2:

输入:rolls = [1,5,6], ans = 3, n = 4
输出:[2,3,2,2]
解释:所有 n + m 次投掷的平均值是 (1 + 5 + 6 + 2 + 3 + 2 + 2) / 7 = 3

思路分析

首先利用测试用例搞清楚题目中的除法是指整除而非向下取整,然后看了下标签是数学模拟,没有用到任何dfs或者dp,最后一气呵成。(但是看标签习惯很不好,因为面试时候没有人告诉你这题是考察什么的)

贪心解法

1 计算总数,并且排除不能分配的情况 剩余待分配总数 大于可以分配的最大值并且最少每个位置可以分配一个 2 计算每个位置分配个数+多余轮分配的多一个

class Solution {
public:
    vector<int> missingRolls(vector<int>& rolls, int ans, int n) {
        int sum=accumulate(rolls.begin(),rolls.end(),0),m=rolls.size();
        vector<int> ret;
        int x=mean*(m+n);
        if(x<sum+n||x>sum+6*n)//都取1或都取6,判断是否存在答案
            return ret;
        int y=x-sum;
        while(n)//向其中添加剩余和的平均值
        {
            ret.push_back(y/n);
            y=y-ret.back();
            --n;
        }
        return ret;
    }
};
模拟解法

分析一波:我们通过m次骰子的数字,得到了一个总数sum,再结合题目的均值ans,便可以知道剩余未知的n次骰子数字求和应该是dis = ans * (n+m) - sum。有了这个思路,做法便很明朗了,只需要求出dis的均值ans_n= (int)(dis / n)。然后从1~n个数字遍历,每个数字从ans _n到6遍历,找到n的求和为dis的话,直接返回。

class Solution {
public:
    vector<int> missingRolls(vector<int>& rolls, int ans, int n) {
        int temp=0;
        for(int num:rolls){
            temp+=(num-ans);
        }
        temp=mean*n-temp;
        int key=temp/n;
        int add=temp%n;
        if(temp<n || temp>6*n){
            return {};
        }
        vector<int>ans(n,key);
        for(int i=0;i<add;i++){
            ans[i]+=1;
        }
        return ans;
        
    }
};