【问题标题】:Making null values from array into averages of existing values将数组中的空值转换为现有值的平均值
【发布时间】:2013-06-12 14:04:16
【问题描述】:

好的,我有一个包含一些值的随机数组:

Integer[] array = {null,null,5,111,21,null,22,null,null,null,98,25,47,null,1,23,null}

我想用最接近的两个现有数组值的平均值替换所有 null 值。 例如:前两个null 值需要替换为数字5{null,null,5,... 变为{5,5,5,...)。

下一个例子:{...,22,null,null,null,98,...} 应该变成:{...,22,60,60,60,98,...};所有三个null 值都将替换为2298 ((22+98)/2) 的平均值。

最后一个例子:{...,23,null}应该变成{...,23,23}null 被替换为 23,因为它是数组的最后一个元素。

有人知道如何为这个问题编写算法吗?

【问题讨论】:

  • 为什么将前两个空值替换为 5 而不是最接近的两个现有数组值的平均值,即 5 和 111?
  • @jwpat7:“两个最近”应该理解为空值左右分别取的2个最近的值,我假设。
  • @haylem 也许,也许不是......这个问题根本不够清楚。
  • 抱歉,回答迟了。当数组以空值开头时,将它们替换为右侧的第一个现有值,因为如果该空值的右侧和左侧都没有现有值,则无法计算空值的平均值。空值两边都必须有整数值。

标签: java arrays algorithm null


【解决方案1】:

假设这是在ArrayList<Integer>上完成的:

//iterate over all values
for (int i=0; i<array.size(); i++) {
    //get the value at the current position
    Integer value= array.get(i);

    //if the value is null...
    if (value == null) {

        //find out the closes left and right values
        Integer leftValue= goLeft(array, i);
        Integer rightValue= goRight(array, i);

        //if both are integer values, find middle
        if (leftValue != null && rightValue != null) {
            array.add(i, (leftValue + rightValue)/2);

        //if left one is integer, and the other one is null? end of the array
        } else if (leftValue != null && rightValue == null) {
            array.add(i, leftValue);

        //if the right one is integer, and the left one is null? begin of the array
        } else if (leftValue == null && rightValue != null) {
            array.add(i, rightValue);

        //well, if everything is null, just add zeros
        } else {
            array.add(i, 0);
        }
    }
}

剩下的就是实施

  • goLeft(ArrayList&lt;Integer&gt; array, int index)
  • goRight(ArrayList&lt;Integer&gt; array, int index)

我认为他们从上下文中非常直接,只需查看他们的名字。

【讨论】:

  • 我不喜欢编辑其他人的答案,因为这些事情实际上不是错误的。
【解决方案2】:

这是我的看法:

public static void fill(Integer[] newarr, Integer[] arr, int index) {
    if (arr[index] != null) {
        newarr[index] = arr[index];
        return;
    }

    Integer a = null, b = null;

    int i = index;
    while (i < arr.length - 1 && (a = arr[++i]) == null);

    i = index;
    while (i > 1 && (b = arr[--i]) == null);

    newarr[index] = (a == null) ? b : (b == null) ? a : (a + b) / 2;
}

然后:

Integer[] arr = { null, null, 5, 111, 21, null, 22, null, null, null,
        98, 25, 47, null, 1, 23, null };

Integer[] newarr = new Integer[arr.length];

for (int i = 0; i < arr.length; i++)
    fill(newarr, arr, i);

System.out.println(Arrays.toString(newarr));
[5, 5, 5, 111, 21, 21, 22, 60, 60, 60, 98, 25, 47, 24, 1, 23, 23]

【讨论】:

    【解决方案3】:
    1. 确定所有空序列(存储开始和结束索引 每个序列)
    2. 确定每个元素的边框 序列和计算平均值(一定要处理额外的情况 数组的开始和结束正确)
    3. 将 null 替换为 计算值

    【讨论】:

      【解决方案4】:

      另一种可能的、更简单但可能效率较低的解决方案:

      1. 为每个空值检查左右值 一个。如果它们都是数字,取平均值 湾。如果一个为空,一个为数字,则将中间值设置为该值,另一个为空
      2. 重复直到没有空值

      它是如何工作的?

      {null,null,5,111,21,null,22,null,null,null,98,25,47,null,1,23,null}
      {null,5   ,5,111,21,21,  22,  22,null,98  ,98,25,47,24  ,1,23,23  }
      {5   ,5   ,5,111,21,21,  22,  22,60  ,98  ,98,25,47,24  ,1,23,23  }
      

      这些值的平均值相同,算法更简单。

      优势

      • 无需任何修改即可处理开始/结束空值
      • 需要更少的内存

      缺点

      • 有点不同...!
      • 可能需要多次迭代
      • 在悲观的情况下需要更多时间

      【讨论】:

      • 算法错误:22,null,null,null,98 应替换为 22,60,60,60,98 而不是 22,22,60,98,98。来自 OP:“下一个示例:{...22,null,null,null,98...} 应变为:{...22,60,60,60,98...}” i>.
      • @m0skit0 你读过我的帖子吗?我在回答中说过。
      • 你说的到底是什么?你的回答不是对所提问题的回答?
      • @Dariusz:不错的主意,需要多做一些工作。感谢您的努力!
      猜你喜欢
      • 1970-01-01
      • 2021-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-21
      • 2013-10-25
      • 2023-02-21
      相关资源
      最近更新 更多