day 4:2028. 找出缺失的观测数据

Leetcode 2028. 找出缺失的观测数据

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

给你一个长度为 m 的整数数组 rolls ,其中 rollsi 是第 i 次观测的值。同时给你两个整数 mean 和 n 。

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

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

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

已知部分数据、平均值即数据量大小,求平均值。那么就可以得到未知数据的总和。

java 复制代码
int m = rolls.length;
int sum = 0;
for (int i = 0 ; i < m; i++) {
    sum += rolls[i];
}

int rest = (m + n) * mean - sum;

需要判断得到的 rest 是否符合要求,不符合要求就直接返回 null 或一个长度为 0 的数组。

java 复制代码
if (rest < n || rest > (n * 6)) return new int[0];

那么就是知道位置数组的总和的数据量大小,只需要返回其中一个结果。

  • 贪心法,让前面的数据尽可能大,或者让前面的数据尽可能小,这两种实现类似。
  • 平均法,让数组数据保持一个平均值。
  • 随机法,真的每次获取一个随机数,但是要记得保证。

贪心法:

java 复制代码
// 代码 1 
for (int i = 0; i < n - 1; i++) {
    int num = 6;
    while ((rest - num) < (n - i - 1)) num--;
    res[i] = num;
    rest -= num;
}
res[n - 1] = rest;

// 代码 2
int num = 6;
for (int i = 0; i < n - 1; i++) {
    while ((rest - num) < (n - i - 1)) num--;
    res[i] = num;
    rest -= num;
}
res[n - 1] = rest;

比较一下代码 1 和 代码 2 的区别,就是局部变量的位置,一个在作用域包括 for 循环外,一个只作用在循环内。

后者需要在判断一次之前已经判断过的情况,因此会导致重复的计算浪费实现。

结果证明其时间有 6ms 变为了 3ms。

上述是让前面的数据尽可能大。如果想让前面的数据尽可能小,只要让 num 从 1 开始,修改 while 的条件为 while((res - num) > ((n - i - 1) * 6)) num++;即可。

平均法:

java 复制代码
int num = rest / n;
for (int i = 0; i < n - 1; i++) {
    while ((rest - num) > ((n - i - 1) * 6)) num++;
    res[i] = num;
    rest -= num;
}
res[n - 1] = rest;

这种方式还是逃不掉 for 循环判断剩余的能否放下。效率还是一样的。

随机法:

java 复制代码
Random random = new Random();
for (int i = 0; i < n - 1; i++) {
    int num = random.nextInt(5) + 1;
    while (((rest - num) < (n - i - 1)) || ((rest - num) > ((n - i - 1) * 6))) {
        num = random.nextInt(5) + 1;
    }
    res[i] = num;
    rest -= num;
}
res[n - 1] = rest;

哈哈,非常浪费时间,在一些特殊情况下,即结果都为 1 或都为 6,可能永远也取不到想要的值。

完整代码

java 复制代码
class Solution {
    public int[] missingRolls(int[] rolls, int mean, int n) {
        int m = rolls.length;
        int sum = 0;
        for (int i = 0 ; i < m; i++) {
            sum += rolls[i];
        }

        int rest = (m + n) * mean - sum;
        if (rest < n || rest > (n * 6)) return new int[0];
        int res[] = new int[n];
        int num = 6;
        for (int i = 0; i < n - 1; i++) {
            while ((rest - num) < (n - i - 1)) num--;
            res[i] = num;
            rest -= num;
        }
        res[n - 1] = rest;
        return res;
    }
}
相关推荐
y = xⁿ5 小时前
DeepSeek Harness 学习日记:关于Agent接口,工具调用的底层实现
android·java·学习
侧耳倾听1116 小时前
jwt使用简介
java·jwt
顶点多余6 小时前
那些在算法中适合巩固的知识点---1
java·前端·算法
AI人工智能+电脑小能手6 小时前
大白话说Java设计模式-46-责任链模式(业务实战篇)
java·设计模式·责任链模式·风控校验·servlet filter·spring interceptor·链式处理
jay神7 小时前
【计算机毕业设计】基于SpringBoot的程序教学辅助系统
java·前端·vue.js·spring boot·后端·毕业设计·课程设计
2601_962066497 小时前
【Sql Server】Update中的From语句,以及常见更新操作方式
android·java·数据库
罗西的思考8 小时前
【Agentic RL / 强化学习框架】Molt 设计解读
人工智能·算法·机器学习
yaoxin5211238 小时前
507. Java 反射 - 在 BeanFactory 中实现依赖注入
java·开发语言
OPEN-F8 小时前
C++模板教程:变参模板、折叠表达式与SFINAE
java·开发语言·c++
hahaha60168 小时前
HLS高层次综合设计技巧--C++类和模板
图像处理·人工智能·算法·计算机视觉