【问题标题】:Java "fractile" method returning wrong outputJava“fractile”方法返回错误的输出
【发布时间】:2016-08-24 11:57:39
【问题描述】:

方向: 给定一个int[] x 和一个百分比p (0 - 100),找到x 中最小的元素y,使得x 的至少百分比p 元素小于或等于y

Example 1:
x = {-3, -5, 2, 1}, p = 50 
Method should return -3 
Reason: 50% of the elements in x are less than or equal to -3:  -5 and -3

Example 2:
x = {7, 9, 2, -10, -6}, p = 50 
Method should return 2 
Reason: 60 percent of the elements in x are less than or equal to 2: 2, -10 and -6 
-6 would be wrong because only 40% of the elements are less than or equal
(100% of the elements are less than or equal to 9, but that isn't the smallest value)

Example 3:
x = {1,2,3,4,5,6,7,8,9,1,2,3,4,5,7,9,5,43,124,94}, p = 0
Method should return 1
Reason: Only 0% is needed, so in theory any number will do, but 1 is the smallest value

到目前为止,这是我为该方法编写的内容:

public static int fractile(int[] x, int p)
   {
      int smallestInt = x[0];            
      for (int i = 0; i < x.length; i++) {
         int testNum = x[i];
         int percentage;
         int count = 0;
         for (int j = 0; j < x.length; j++) {
            if (x[j] <= testNum)
               count++;
         }
         percentage = (count / x.length) * 100;
         if (testNum <= smallestInt && percentage >= p)
            smallestInt = testNum;
      }
      return smallestInt;
   }

但我的样本编号输出错误:

INPUT: 
[6, 5, 4, 8, 3, 2]
40%
Method returns: 6
INPUT: 
[7, 5, 6, 4, 3, 8, 7, 6, 9, 10]
20%
Method returns: 7
INPUT: 
[3, 4, 2, 6, 7, 5, 4, 4, 3, 2]
60%
Method returns: 3

这几乎就好像它正在抓取第一个索引并且不查看它后面的数字,但我不知道为什么。

我做错了什么?

【问题讨论】:

  • 最大的问题可能是你的初始化行int smallestInt = x[0];。这是完全错误的。将其替换为 int smallestInt = Integer.MAX_VALUE
  • 罗伯特,你是指最高指数还是最高价值?
  • 请记住,您必须按照下面的一些 cmets 和答案中的说明修正百分比计算。

标签: java algorithm


【解决方案1】:

将您的百分比更改为双精度/浮点数,并将除法中的一个变量也转换为双精度/浮点数。

类似:

double percentage=0.0;
...
percentage = ((double)count / x.length) * 100;

所以方程返回双精度/浮点数。

--

基元类型的数值提升规则

  1. 如果两个值具有不同的数据类型,Java 会自动将其中一个值提升为两种数据类型中较大的一个。

  2. 如果其中一个值是整数而另一个是浮点数,Java 会自动将整数值提升为 浮点值的数据类型。

  3. 较小的数据类型,即 byte、short 和 char,在与 Java 二进制算术一起使用时首先被提升为 int 运算符,即使两个操作数都不是 int。

  4. 发生所有提升并且操作数具有相同的数据类型后,结果值将具有与其相同的数据类型 提升的操作数。

Jeanne Boyarsky 和 ​​Scott Selikoff - OCA 学习指南

【讨论】:

  • 好的,这适用于我的前两个输出。当我到达第 3 部分时,它返回了“3”,而它本应返回“4”。这是因为 60% 的数字不小于或等于 3,只有 40%。 {2、2、3、3、4、4、4、5、6、7}
  • 是的,这是由于初始化。也解决这个问题!
  • 您对我如何解决它有什么建议吗?您建议的 MIN_VALUE 想法对我不起作用。其他人建议先对数组进行排序——这有必要吗?
【解决方案2】:

排队

percentage = (count / x.length) * 100;

count 和 x.length 都是整数。因此,将它们相除会得到一个整数值,而不是浮点数。百分比可能包含 0 或 100,而不是介于两者之间的某个值。

【讨论】:

  • 会强制转换为 (int) 解决此问题,还是会产生不准确的结果?
  • 我刚试过这个,它仍然返回相同的输出。我不确定这是不是问题所在。
  • 这是问题的一部分。见this SO question
  • Floris,我认为这可能与初始化有关,但如果我将“smallestInt”设置为低值,那么 testNum 将永远不会更小。同样,我刚刚尝试使用 MAX_VALUE,有趣的是,输出现在总是返回最高索引。
【解决方案3】:

您需要的是选择算法,以给定的比例划分数组。

简单快速的一个是QuickSelect

我怀疑在 Java 中有现成的实现,比如 C++ std::nth_element

【讨论】:

    【解决方案4】:

    对于从最低到最高排序的数组,您只需将长度乘以百分比即可获得搜索元素的正确索引。欲了解更多信息Quantiles

    这将使您的代码更短

     public static int fractile(int[] x, double p){   
       Arrays.sort(x);       
       int k = (int) Math.ceil(x.length*p)-1;
       return x[k];
    }
    

    【讨论】:

      【解决方案5】:

      你可以试试:

      public static int fractile( int[] x, int p )
         {
              Arrays.sort(x);
              return x[Math.max((int) Math.ceil(x.length / 100.0 * p) - 1, 0)];
         }
      

      这假设您被允许操作数组。对数组进行排序几乎总是使操作更容易。这将有效,除非数组必须保持原样。

      此代码对数组进行排序,由于初始输入“p”告诉您要查找的百分比,它会查看数组中的大致位置并返回存储在那里的值。

      【讨论】:

        【解决方案6】:

        我对这个问题有另一种实现:

        public static void main(String args[]){
        		int[] a1 = {-3,-5,2,1};
        		int[] a2 = {7,9,2,-10,-6};
        		int[] a3 = {1,2,3,4,5,6,7,8,9,10};
        		int[] a4 = {1,2,3,4,5,6,7,8,9,1,2,3,4,5,7,9,5,43,124,94};
        		int[] a5 = {1};
        		int p = 50;
        		System.out.println(fractile(a1, p));
        	}
        
        	private static int fractile(int[] x, int p) {
        		Arrays.sort(x);		
        		double value0 = x.length / 100.0 * p;
        		double value1 = Math.ceil(value0);
        		int value2 = (int)value1; 
        		int value3 = value2 - 1;
        		int value4 = Math.max(value3, 0);
        		return x[value4];
        	}

        【讨论】:

          猜你喜欢
          • 2015-05-07
          • 1970-01-01
          • 2017-11-06
          • 2014-01-03
          • 1970-01-01
          • 2020-12-20
          • 2013-07-23
          • 2021-09-06
          相关资源
          最近更新 更多