【问题标题】:Algorithm to find the largest integer in array查找数组中最大整数的算法
【发布时间】:2012-09-04 07:07:12
【问题描述】:

我正在尝试创建一个返回 int 的方法 - 已发送数组中最大整数的值。 我希望这种方法起作用的方式是在 for 循环中检查数组的第一个 最后一个元素,然后按照它们的方式工作到中间。所以 i = 第一个整数,k = 最后一个整数。当i = 0, k = n-1(索引),当i = 1, k = n-2,如果你发现我的想法。在每个循环中,它都需要检查if a[i]>a[k]。然后他们交换位置。然后我知道最大的数字在数组的前半部分,然后我想让它检查那一半,所以最终最大的 int 在索引 0 处。

我试过这样:

public static int maxOfArray(int[] a)
{
    int length = a.length;

    if(length<1)
        throw new NoSuchElementException("Not at least one integer in array");

    while (length > 1)
    {
        int k = length;

        for(int i = 0; i < length/2; i++)
        {
            k--;

            if(a[i]<a[k])
            {
                int j = a[i];
                a[i] = a[k];
                a[k] = j;
            }
        }
        length /=2;
    }
    return a[0];
}

..但我真的不明白..我很难“想象”这里发生了什么..但它并不总是有效..(尽管有时)。

编辑 另外:数组{6,15,2,5,8,14,10,16,11,17,13,7,1,18,3,4,9,12};将吐出 17 作为最大的数字。我意识到我必须修复奇数长度的错误,但我想先解决这个偶数长度的数组..

【问题讨论】:

  • 您能否详细说明您为什么要尝试线性扫描这种复杂方法的原因?是硬件吗?书中的例子?面试?它可能会帮助我们为您提供更有针对性的答案。
  • "[...] 然后他们交换位置" - 看起来 OP 实际上想要以某种冒泡排序样式对数组进行 排序。请添加 quiz 标签!
  • @amit 嗯,是的。这是一个小学校项目。我可以用其他方法看到很多答案,但要求是比较第一个和最后一个,如果最后一个更大,则切换位置 - 然后继续朝向数组的中间。最大的不是放在索引0,而是放在数组的“左边”,这样到时候就放在索引0了..
  • 最大的并不总是在前半部分。假设您的数组是 [1, 5, 3],那么您首先比较 (1 > 3),然后比较 (5 > 5),最后比较 (3 > 1)。您现在有 [3, 5, 1] 并将长度除以 2 得到数组 [3]。您丢失了 5。此外,如果您切换比较,则不必扫描整个数组,只需扫描一半。现在您首先将大数移到上半部分,然后再移回下半部分。
  • 所以for(int i = 0; i &lt; length; i++)是错误的,你只需要遍历数组的前半部分:for(int i = 0; i &lt; length / 2; i++)。还要检查如果数组大小是奇数会发生什么。

标签: java arrays algorithm integer


【解决方案1】:

但我真的不明白..我很难“想象”这里发生了什么..但它并不总是有效..(尽管有时)。

在这种情况下,您应该使用调试器单步执行代码,以了解每行代码的作用。


我会做的是:

public static int maxOfArray(int[] a) {
    int max = a[0];
    for (int i : a)
        if (max < i)
            max = i;
    return max;
}

public static int findMaxTheHardWay(int[] array) {
    for (int length = array.length; length > 1; length = (length + 1) / 2) {
        for (int i = 0; i < length / 2; i++) {
            if (array[i] < array[length - i - 1])
                array[i] = array[length - i - 1]; // don't need to swap.
        }
    }
    return array[0];
}

public static void main(String... args) {
    Random rand = new Random(1);
    for (int i = 1; i <= 1000; i++) {
        int[] a = new int[i];
        for (int j = 0; j < i; j++) a[j] = rand.nextInt();
        int max = maxOfArray(a);
        int max2 = findMaxTheHardWay(a);
        if (max != max2)
            throw new AssertionError(i + ": " + max + " != " + max2);
    }
}

【讨论】:

  • 它没有回答 OP 的问题。 The way I want this method to work, is to....
  • @amit 添加了一个解决方案,用于以困难的方式找到最大值。 ;)
【解决方案2】:

为什么不将数组的第一个值存储到变量max

之后,只需从第二个位置到最后一个位置循环遍历数组, 在循环中检查当前值是否大于max。如果大于则分配max该值。

返回max,你的数字最大。

public int FindLargest()
{
    int[] num = { 1, 2, 5, 12, 13, 56, 16, 4 };
    int max = num[0];

    for (int i = 1; i <num.length; i++)
    {
        if (num[i] > max)
        {
            max = num[i];
        }
    }

    return max;
}

【讨论】:

  • (1) 它不回答 OP 的问题。 The way I want this method to work, is to.... (2) 它不是 java (Length 字段)。 C# 我怀疑
  • @amit 好的,它不回答 OP 的问题,但提供了一个可行的替代方案。为什么不呢?
  • @amit num.length 完全正确,请查看Java Arrays 以获取 SO 示例。
  • @f_puras 添加此评论时是num.Length ;)
  • @freebird num.length 是正确的,num.Length 是不正确的。为什么要改回来?
【解决方案3】:

一个错误是遇到length 是奇怪的。

在这些情况下,您“错过”了中间元素。

示例:对于输入 int[] arr = { 8, 1, 5, 4, 9, 4, 3, 7, 2 }; - 元素 9 将与自身进行比较和检查,但随后您减小了 length 的大小,将 9 从数组中排除你接下来要迭代。

我相信可以通过将问题减少到ceil(length/2) 而不是length/2 来解决(并处理length==1 的特殊情况)

cmets 中提到的另一个问题是:您需要迭代到 length/2 而不是到 length,否则您将覆盖自己。

最后 - 标志是错误的

if(a[i]>a[k])

应该是

if(a[i]<a[k])

请记住 - 如果第一个元素小于第二个元素,则您正在尝试交换元素,以便将较大的元素推到数组的头部。

【讨论】:

  • 谢谢,我现在意识到奇数长度会损坏它,但是,我正在用不同的数组测试我的方法,其中一些有效,而(到目前为止)失败的是偶数长度数组 = {6,15,2,5,8,14,10,16,11,17,13,7,1,18,3,4,9,12} 在索引 0 处设置 17,偶数虽然 18 更大。
  • @StianF:我相信 f_puras 在他的评论中也是正确的。除了我在这里提到的内容之外,您还应该迭代到 length/2
  • @StianF:给你 - if 条件符号也是错误的。我编辑了答案以反映它。
  • @StianF:你解决了奇数数组长度问题吗?即使是偶数长度的数组也可能出现,因为你不断地划分问题(例如长度=18,第二次迭代将有长度=9)
  • 可以通过length = (int)Math.ceil((double)length/2);修改length
【解决方案4】:
int a[] = {1,7,3};   
List<Integer> list = Arrays.asList(a);  
Integer largest = Collections.max(list);

这将为您提供数组中的最大数。

【讨论】:

    【解决方案5】:

    这是一个符合您想要的规格的解决方案(不像这里的许多其他,嗯,嗯):

        final Integer[] input = {1, 2, 6, 32, 4, 44 ,12, 42, 3, 7, 17, 22, 57, 23, 102, 103 };
    
        int half = (input.length / 2);
        int mod = input.length % 2;
        while (half >= 0) {
            for (int i = 0, j = (half * 2) + mod - 1; i <= half && j >= half; i++, j--) {
                if (input[i] < input[j]) {
                    final int tmp = input[i];
                    input[i] = input[j];
                    input[j] = tmp;
                }
            }
            if (half == 0) break;
            half = half / 2;
            mod = half % 2;
        }
        //Here, input[0] = the biggest number in the original input.
    

    编辑:添加了 mod,所以如果最后一个元素是最大的,它就可以工作..

    【讨论】:

      【解决方案6】:

      这是一个相当疯狂的解决问题的方法,但我会继续玩。

      问题出在内部循环中。

      • 您从 i = 0 和 k = 长度 - 1 开始。
      • 如果 a[i] > a[k] 则交换它们。
      • ...
      • 你最终得到 k = 0 和 i = 长度 - 1
      • 如果 a[i] > a[k] 则交换它们。

      如果你仔细观察你会发现,如果我们在第一次交换中交换了元素,我们也会在最后一次交换中交换它们;即我们将撤消第一次交换的影响。这同样适用于整个数组切片。

      看到了吗?

      你需要做的是中途停止内循环......然后考虑length为奇数的情况。


      顺便说一句,我之所以称之为“相当疯狂”,是因为显而易见且简单的方法要快得多:O(N)O(NlogN)

      【讨论】:

      • 谢谢!但是,仍然有问题..可能是我愚蠢的代码中的其他内容,但是我现在已经将循环中途停止了i&lt;length/2,而且我还意识到我实际上将较大的整数换成了错误的一半,但我仍然某些数组出错。即 6,15,2,5,8,14,10,16,11,17,13,7,1,18,3,4,9,12。我还没有开始奇数长度,因为这是一个偶数长度还没有工作..
      • 是的,如果您将大数字向左移动,您给出的比较符号是错误的。
      • 如果您仍然无法找出代码中的问题,请尝试添加跟踪打印或使用调试器运行它。
      • 我们想通了。阿米特是对的。问题是我没有考虑奇数长度的数组。我愚蠢地选择不这样做,因为我在使用偶数长度数组时得到了错误的输出,但由于该数组的长度是18,所以在第二轮它会有一个奇数长度9。顺便说一句,我如何找出 0(NlogN) 的东西?它的英文叫什么?
      • @Stainf - 在英文中,它被称为“复杂性分析”,即“Big O”或“Landau”符号。等他们教给你,或者在维基百科上查找:-)
      【解决方案7】:

      我认为您的代码正在运行,您只需将长度 / 2 设置为奇数数组,但我的测试返回正确的结果:

      package org.devince.largestinteger;
      
      import java.util.NoSuchElementException;
      
      public class LargestInteger {
          final static int[] input = {1, 2, 6, 32, 4, 44 ,12, 42, 3, 7, 17, 22, 57, 23, 102, 103 };
      //  final static int[] input = { 8, 1, 5, 4, 9, 4, 3, 7, 2 };
      //  final static int[] input = {1,3,7};
      
          /**
           * @param args
           */
          public static void main(String[] args) {
              System.out.println(String.valueOf(maxOfArray(input)));
          }
      
          public static int maxOfArray(int[] a)
          {
              int length = a.length;
      
              if(length<1)
                  throw new NoSuchElementException("Not at least one integer in array");
      
              while (length > 1)
              {
                  int k = length;
      
                  for(int i = 0; i < length; i++)
                  {
                      k--;
      
                      if(a[i]>a[k])
                      {
                          int j = a[i];
                          a[i] = a[k];
                          a[k] = j;
                      }
                  }
                  length = (int) Math.ceil(length / 2f);
              }
              return a[0];
          }
      
      }
      

      【讨论】:

        【解决方案8】:

        同样你也可以接近,

        int length = a.length;
           while (length > 1)
            {
                int k = length;
                for(int i = 0; i < length; i++)
                { 
                    for(int y = k-1; y >= i; y--) 
                    {         
                        if(a[i]<a[y])
                        {
                            int j = a[i];
                            a[i] = a[y];
                            a[y] = j;               
                        }
                    }       
                }
                length /=2;
            }
        

        【讨论】:

          【解决方案9】:
                   final int validSampleRates[] = new int[]{
                              5644800, 2822400, 352800, 192000, 176400, 96000,
                              88200, 50400, 50000, 4800,47250, 44100, 44056, 37800, 32000, 22050, 16000, 11025, 4800, 8000};
                    ArrayList <Integer> YourArray = new ArrayList <Integer> ():
           for (int smaple : validSampleRates){
          
                              YourArray.add(smaple);
                          }
                      Integer largest = Collections.max(YourArray);
                      System.out.println("Largest   " + String.valueOf(largest));
          

          最好的方法是使用 Array 将 List Collection 扩展为 ArrayList

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-07-04
            • 2015-10-30
            • 2018-08-27
            • 2010-09-13
            • 2011-12-11
            • 1970-01-01
            • 2016-05-25
            • 1970-01-01
            相关资源
            最近更新 更多