【问题标题】:Find average of an array of ints查找整数数组的平均值
【发布时间】:2020-09-06 18:53:18
【问题描述】:

给定一个任务

返回整数数组的“居中”平均值,我们将说它是值的平均平均值,但忽略数组中的最大值和最小值。如果最小值有多个副本,则只忽略一个副本,最大值也是如此。使用 int 除法产生最终平均值。您可以假设该数组的长度为 3 或更多。

centeredAverage([1, 2, 3, 4, 100]) → 3
centeredAverage([1, 1, 5, 5, 10, 8, 7]) → 5
centeredAverage([-10, -4, -2, -4, -2, 0]) → -3

我尝试过这样解决,但我有点困惑(捕获 ArrayIndexOutOfBounds 异常):

public class Main {
    public static void main(String[] args) {
        int[] num = {1, 2, 3, 4, 100};
        int[] num1 = {1, 1, 5, 5, 10, 8, 7};
        int[] num2 = {-10, -4, -2, -4, -2, 0};
        System.out.println(centeredAverage(num));
        System.out.println(centeredAverage(num1));
        System.out.println(centeredAverage(num2));
    }

public static int centeredAverage(int[] nums) {
    int count = 0;
    int average = 0;
    //to search for max and min
    Arrays.sort(nums);
    //the last int of an array
    int end = nums[nums.length - 1];

    if (nums.length > 3) {
        //exclude minimum and maximum values
        for (int i = 1; i < end; i++) {
            if (!(nums[i] == nums[i + 1])) {
                count++;
                average = (nums[i] + nums[i + 1]) / count;
            }
        }
    }

    return average;
}

}

【问题讨论】:

  • 这不是很容易吗?对所有元素求和并跟踪最小值和最大值。从总和中减去它们并除以数组长度 - 2。通过排序,它将从索引1 到索引length - 2 的元素相加,然后除以length - 2
  • (int i = 1; i &lt; end; i++) 中应该是i &lt; end - 1
  • @Amongalen 错了。 i &lt; end 正在比较 indexvalueend 是数组中的最后一个值)。应该是i &lt; nums.length - 2。 (-1 保持在索引范围内,-2 获得倒数第二个元素)。
  • @Thomas 是的,出于某种原因,我认为end == nums.length

标签: java arrays indexoutofboundsexception


【解决方案1】:

我会稍微扩展一下我对您问题的评论:

您的解决方案是首先对数组进行排序,然后跳过第一个和最后一个元素。想法不错,但实现是错误的:

  • int end = nums[nums.length - 1]; 应该是 int end = nums.length - 1 因为您的意思似乎是 end 是最后一个元素的索引
  • average = (nums[i] + nums[i + 1]) / count; 在循环内部是错误的,因为您划分得太频繁了。此外,该行意味着您只添加 2 个元素并将其除以 count。这不是除最小和最大之外的所有数组元素的平均值。
  • if(nums.length &gt; 3) 是不必要的,因为“您可以假设数组的长度为 3 或更多。” (如果你想使用那个条件,应该是if(nums.length &gt;= 3)
  • if (!(nums[i] == nums[i + 1])) 似乎错了,为什么要跳过具有相同值的连续元素?您已经跳过了第一个和最后一个元素。

因此,您的代码应如下所示:

int sum= 0;
//to search for max and min
Arrays.sort(nums);
//the last int of an array
int end = nums.length - 1;


//exclude minimum and maximum values which are at index 0 and "end"
for (int i = 1; i < end; i++) {               
   sum += nums[i];
}

int average = sum / nums.length - 2;

您的方法的一个缺点是您正在更改传递的数组,因为排序是就地操作。因此,如果不应该发生这种情况,您至少必须制作数组的副本。

您也根本不需要排序,只需跟踪最小和最高的元素:

int smallest = Integer.MAX_VALUE;
int highest = Integer.MIN_VALUE;
int sum = 0;

for( int value : nums ) {
  sum += value;
  smallest = Math.min(smallest, value); //or use if(smallest > value) smallest = value;
  highest = Math.max(highest , value);  //or use if(highest < value) highest = value;
}

//smallest and highest are part of the sum so subtract them again
//since we ignore 2 elements we divide by length - 2
int average = (sum - smallest - highest) / (nums.length - 2);

【讨论】:

  • 感谢详细解释!
【解决方案2】:

问题在于,不是将长度为 2 的值存储在末尾,而是将值存储在长度为 1 的末尾。 声明结束为:

int end = nums.length - 2;

还有一件事我注意到了:

如果 (nums.length >= 3)

【讨论】:

  • 请注意,int end = nums.length - 2;i &lt; end 也会跳过倒数第二个元素。应该是int end = nums.length - 1;i &lt;= end :)
【解决方案3】:

这应该可行:

public static int centeredAverage(int[] nums) {
//array to ArrayList
ArrayList<Integer> list = (ArrayList<Integer>)Arrays.stream(nums)     
                                .boxed()        
                                .collect(Collectors.toList());
//Sorting the ArrayList
Collections.sort(list);
//Removing first and last number
list.remove(0);
list.remove(list.size()-1);
//Returning the average
return (int) list.stream().mapToDouble(val -> val).average().orElse(0.0);
}

【讨论】:

    【解决方案4】:

    现在我在 codingbat.com (https://codingbat.com/prob/p136585) 中对同一问题的解决方案对于所有可能的组合都是正确的。详细解答如下:

    public int centeredAverage(int[] nums) {
      //first find Min and Max
      int min=nums[0], max = nums[0];
      for(int i=1;i<nums.length;i++){
        min=Math.min(min,nums[i]);
        max=Math.max(max,nums[i]);
      }
          
      int total=0,count=0,mincount=0,maxcount=0;
      for(int i=0;i<nums.length;i++){
        //exclude min and max only once to total count
        if(nums[i]==min&&mincount==0) {
          mincount++;
            continue;
        }
        else if(nums[i]==max&&maxcount==0) {
          maxcount++;
            continue;
        }
        //find total excluding min and max number only once
        total+=nums[i];
        //also count the numbers included in total
        count++;
      }
        //return average
        return total/count;
    }
    

    【讨论】:

      【解决方案5】:

      1.设置我们可能得到的ma​​xmin值。 2.让int total计算数组中所有值的总和。 3.设置两个条件,nums[i]大于max,nums[i]小于min。如果满足条件,则将 nums[i] 值分配给 max/min。 4.最后,从总数中减去最大值和最小值,计算平均值。

      public int centerAverage(int[] nums)
      int max= Integer.MIN_VALUE;
      int min= Integer.MAX_VALUE;
      int total=0;
      for(int i=0;i<nums.length;i++){
       total+=nums[i];
       if(nums[i]>max){
        max=nums[i];
       }
       if(nums[i]<min){
        min=nums[i];
       }
      }
      return (total-max-min)/(nums.length-2);
      }
      

      【讨论】:

      • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
      猜你喜欢
      • 2015-01-15
      • 1970-01-01
      • 1970-01-01
      • 2017-06-11
      • 2021-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多