【问题标题】:Efficient method to find the second largest even int in an array在数组中找到第二大偶数 int 的有效方法
【发布时间】:2014-09-26 16:56:14
【问题描述】:

任务是创建一个方法,在 int 数组中找到第二大的偶数 int。我被限制使用任何库中的任何方法。

这是适用于所有情况的代码:

public static int getSecondLargestEven(int[] ary) {


int i;

    aryLength = ary.length;
    int largestEven = -1;
    int secondLargestEven = -1;

    for (i = 0; i < aryLength; i++) {
        if (ary[i] % 2 == 0) {
            if (ary[i] > largestEven) {
                if (largestEven != -1)
                    secondLargestEven = largestEven;

                largestEven = ary[i];
            } else { 
                if (ary[i] != largestEven) {
                    if (secondLargestEven == -1 || ary[i] >= secondLargestEven) {
                        secondLargestEven = ary[i];
                    }
                }
            }
        }
    }

在调用方法之前我要求数组有多个,否则没有方法调用。 所以,当 secondLargestEven == -1 时,我知道有重复。

是否有更有效(更少使用运算符、使用更少循环、更少内存分配)的方式来实现目标?如何改进代码的逻辑?如何整体改进我的代码? 我不喜欢我必须将幻数 -1 分配给 secondLargestEven 和 maximumEven,因为它们在技术上被命名为持有 EVENS。使用循环将数组中的有效偶数分配给 secondLargestEven 和 maximumEven 然后继续搜索是否有效?提前致谢。

【问题讨论】:

  • 对于您想要改进的工作代码(运行时、资源或一般样式/架构),您最好在CodeReview.SE
  • 您的代码在性能方面似乎很高效,即使它不是很好。代码优雅和最佳效率往往是不相容的
  • @Joel 我认为在大多数情况下,渐近效率与优雅非常兼容。现在减少使用 1 个字节可能会产生丑陋的代码。
  • 感谢您查看我的代码!
  • 这个问题似乎跑题了,因为关于最佳实践和性能的问题属于codereview.stackexchange.com

标签: java arrays search int


【解决方案1】:

您可以通过不显式检查largestsecond 变量等于-1 的情况来使代码更简洁。

只需在循环之前将这些变量设置为 Integer.MIN_VALUE - 这与假设数组中有两个附加值位于所有其他值之前相同,并且它们都具有值 Integer.MIN_VALUE

public static int secondLargestEven(int[] x) {

    int largest = Integer.MIN_VALUE;
    int second = Integer.MIN_VALUE;

    for (int i = 0; i < x.length; i++) {
        if (x[i] % 2 == 0) {
            if (x[i] > largest) {
                second = largest;
                largest = x[i];
            } else if (x[i] > second) {
                second = x[i];
            }
        }
    }

    return second;

}

编辑——我想我会说你可以通过在循环中使用continue 语句来删除一层嵌套,以跳过你有一个奇数整数的情况,尽管有些人会认为这更困难比上面的代码理解。

这是一种权衡 - 您在循环内使用显式控制流(不好),但删除了嵌套级别(好)。

public static int secondLargestEven(int[] x) {

    int largest = Integer.MIN_VALUE;
    int second = Integer.MIN_VALUE;

    for (int i = 0; i < x.length; i++) {
        if (x[i] % 2 != 0) 
            continue;
        if (x[i] > largest) {
            second = largest;
            largest = x[i];
        } else if (x[i] > second)
            second = x[i];
        }
    }

    return second;

}

只是一个有趣的想法......在Haskell中,这个函数可以写在一行

import Data.List (sort)

secondLargestEven = (!! 1) . reverse . sort . filter even

或者,如果你想提高效率

import Data.List (sortBy)
import Data.Ord  (comparing)

secondLargestEven = (!! 1) . sortBy (comparing negate) . filter even

【讨论】:

  • 如果您愿意,可以将Integer.MIN_VALUE 替换为-2147483648,但我认为这会使代码变得不那么清晰:)
  • 快速问题:将 x.length 分配给一些 int 类型的变量是否更有效,这样我就不会在每次循环迭代时调用 .length()?
  • 不,因为length 是数组的特殊属性,而不是方法,所以不会产生方法调用开销。看到这个答案 - stackoverflow.com/questions/9297899/arrays-length-property
  • 我从没想过。感谢分享!
【解决方案2】:

这只是为了好玩的实现:

public static int secondLargestEven(int[] array) {

    Set<Integer> evenSet = new TreeSet<>(Collections.reverseOrder());
    for (int n : array) if (n % 2 == 0) evenSet.add(n);
    return new ArrayList<>(evenSet).get(1);
}

这个方法效率极低(我看不下去了)但是返回第二大的偶数:)

方法只有在数组有第二大偶数时才有效。

【讨论】:

    猜你喜欢
    • 2022-12-31
    • 1970-01-01
    • 2018-04-07
    • 1970-01-01
    • 2011-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-01
    相关资源
    最近更新 更多