【发布时间】:2016-01-13 07:28:04
【问题描述】:
在二维数组中获得最大i(即行数)和j(即列数)的最佳且有效的方法是什么?
希望每种情况的时间复杂度都低于O(n)。这里没有循环,仍然可以找到最大值j。
例如,如果我有一个这样的数组
[
[18,18,19,19,20,22,22,24,25,26],
[1,2,3],
[0,0,0,0]
]
那么我想在这里得到i = 3和j = 10结果。
谁能帮帮我?
【问题讨论】:
在二维数组中获得最大i(即行数)和j(即列数)的最佳且有效的方法是什么?
希望每种情况的时间复杂度都低于O(n)。这里没有循环,仍然可以找到最大值j。
例如,如果我有一个这样的数组
[
[18,18,19,19,20,22,22,24,25,26],
[1,2,3],
[0,0,0,0]
]
那么我想在这里得到i = 3和j = 10结果。
谁能帮帮我?
【问题讨论】:
您可以避免自己编写循环,但您不能避免运行时间至少为O(n),因为“某人”需要循环源数组。
这是在 Java 8 中实现此目的的一种可能方法:
Arrays.stream(arr).map(row -> row.length).max(Integer::compare).get();
这将返回二维数组中“行”的最大长度:
10
另一个版本避免使用Comparator,因此可能更容易阅读:
Arrays.stream(arr).mapToInt(row -> row.length).max().getAsInt();
arr 应该是您的源数组。
编辑:旧版本使用.max(Integer::max),这是错误的并导致错误的结果。请参阅this answer 了解说明。
【讨论】:
Arrays.asList(array).parallelStream() 也是一个没有太多开销的选项。
假设你的数组不包含空值,你可以这样写:
private static final Comparator<int[]> lengthComparator = new Comparator<int[]> () {
@Override
public int compare(int[] o1, int[] o2) {
return o1.length - o2.length;
}
};
@Test
public void soArrayMaxLength() {
int[][] array = new int[][] {
{18,18,19,19,20, 22, 22, 24, 25,26},
{1,2,3},
{0,0,0,0}
};
int i = array.length;
Optional<int[]> longestArray =
Arrays.stream(array)
.max(lengthComparator);
int j = longestArray.isPresent() ? longestArray.get().length : 0;
System.out.println(String.format("i=%d j=%d", i, j));
}
如果您碰巧从数组创建并行流,则可以进一步加快速度。
另一种选择是按长度对数组进行排序,快速排序的平均复杂度通常为 O(n*log(n)),因此不会更快;
int i = array.length;
Arrays.parallelSort(array, lengthComparator);
int j = array[i-1].length;
System.out.println(String.format("i=%d j=%d", i, j));
【讨论】:
Optional<int[]> longestArray = Arrays.asList(array).parallelStream().max(lengthComparator);
您的i 是行数,它只是二维数组的length(假设您可以在此计数中包含空/空行)。
然而,最大行长度 j 需要遍历所有行才能找到具有最大 arr[i].length 的行 i。
【讨论】:
O(N),其中N 是行数。 for 的显式循环效率低。这是一个使用 for 循环的巧妙解决方案
int max = o;
for (int i = 0; i < array.length; i++) {
max = Math.max(max, array[i].length);
}
这适用于array.length == 0 的边缘情况,但如果array 或任何array[i] 是null,您将得到NullPointerException。 (您可以修改代码以允许这样做,但如果不希望出现空值,则 NPE 可能是更好的结果。)
1 - 理论上,您可以将所有 array.length 情况的循环展开,从 0 到 Integer.MAX_VALUE,您不需要循环。但是,该代码不会在任何已知的 Java 编译器上编译,因为它会超过 JVM 对字节码段等的限制。由于各种原因,性能会很糟糕。
【讨论】:
你可以试试这个方法:在数组上循环并找到这个数组中数组的最大长度
byte[][] arrs = new byte[3][];
int maxLength = 0;
for (byte[] array : arrs) {
if (maxLength < array.length) {
maxLength = array.length;
}
}
【讨论】: