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

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

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

给你一个长度为 m 的整数数组 rolls ,其中 rolls[i] 是第 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;
    }
}
相关推荐
xlsw_2 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹3 小时前
基于java的改良版超级玛丽小游戏
java
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭3 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
XH华3 小时前
初识C语言之二维数组(下)
c语言·算法
暮湫3 小时前
泛型(2)
java
超爱吃士力架3 小时前
邀请逻辑
java·linux·后端
南宫生4 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
转码的小石4 小时前
12/21java基础
java
不想当程序猿_4 小时前
【蓝桥杯每日一题】求和——前缀和
算法·前缀和·蓝桥杯
李小白664 小时前
Spring MVC(上)
java·spring·mvc