【问题标题】:How to deal with big arrays/lists如何处理大数组/列表
【发布时间】:2023-04-06 14:07:01
【问题描述】:

最近我尝试做一些代码任务。 我经常使用数组作为输入来完成一项任务,您需要解决以下问题:找到数组中不会出现的最小正整数等。 我可以轻松处理小数组,但是当我汇总代码并通过测试(包括具有> 1000(或 10 000)个元素的数组)获得摘要时,我几乎总是遇到运行时错误。

那么你能告诉我如何处理大数组吗?

大多数情况下,我会尝试像这样将数组转换为列表:

List<Integer> arrayList = Arrays.stream(A)
                .boxed()
                .filter(c -> (c > -1001 && c < 1001)) // predicate
                .collect(Collectors.toList());

有时我会使用过滤器,如您所见,有时我会在需要时使用 distinct/sort。 但是我仍然有很多运行时错误。

我会很高兴提供一些如何处理它的提示。

@cricket_007

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

class Solution {
    public int solution(int[] A) {

        List<Integer> integerList = Arrays.stream(A)
                .boxed()
                .collect(Collectors.toList());

        if ((integerList.size() == 2 && integerList.get(0) == integerList.get(1)) || A.length == 1) {
            return 0;
        }
        if ((integerList.size() == 2 && integerList.get(0) != integerList.get(1))) {
            return Math.abs(integerList.get(0) - integerList.get(1));
        }

        int sublistSum1;
        int sublistSum2;

        List<Integer> scoreList = new ArrayList<>();

        Integer temp;
        for (int i = 1; i < integerList.size(); i++) {
            sublistSum1 = integerList.subList(0, i).stream().mapToInt(n -> n).sum();
            sublistSum2 = integerList.subList(i, integerList.size()).stream().mapToInt(n -> n).sum();
            temp = Math.abs(sublistSum1 - sublistSum2);
            scoreList.add(temp);
        }
        return scoreList.stream()
                .min(Integer::compareTo)
                .get();
    }
}

所以这是我对这个任务的解决方案:https://app.codility.com/programmers/lessons/3-time_complexity/tape_equilibrium/

我得到了 100% 的正确性,但性能却为 0%,因为:“TIMEOUT ERROR Killed。达到硬限制:6.000 秒。”所有 6 次性能测试都返回此错误。

在这种情况下我该怎么办?

下一个任务,下一个大数组的问题。 https://app.codility.com/programmers/lessons/5-prefix_sums/passing_cars/

我的代码:

import java.util.Arrays;

class Solution {
    public int solution(int[] A) {

        if (Arrays.stream(A).distinct().count() == 1) {
            return 0;
        }
        int score = 0;

        for (int i = 0; i < A.length; i++) {
            if (A[i] == 0) {
                for (int j = 1; j < A.length; j++) {
                    if (A[j] == 1 && j > i) {
                        score++;
                    }
                }
            }
        }
        if (score < 1_000_001) {
            return score;
        }
        return -1;
    }
}

所以基本上当我试图用嵌套循环解决这个任务时,我得到了 O(N^2) 的算法复杂度。如何解决?

【问题讨论】:

  • 这是什么语言?爪哇?
  • 是的,它是 Java。
  • 您观察到的那些运行时错误是什么?
  • 如果只需要查找单个整数,则不需要分配集合。
  • 我认为您应该链接到您遇到问题的单个问题和您的解决方案,而不是就所有问题提出一个模糊的问题

标签: java runtime-error java-stream


【解决方案1】:

首先,您必须问自己是否真的需要需要装箱的List&lt;Integer&gt;,或者int[] 数组是否也足以完成您的任务。

所以

int[] array = Arrays.stream(A)
    .filter(c -> (c > -1001 && c < 1001))
    .toArray();

会更有效率。但是,如果您真的需要 List&lt;Integer&gt;,您仍然应该在 装箱值之前尽可能多地完成工作,即

List<Integer> arrayList = Arrays.stream(A)
    .filter(c -> (c > -1001 && c < 1001))
    .boxed()
    .collect(Collectors.toList());

这样,只有匹配的 int 值被装箱,而不是全部装箱。这是 Stream 实现无法自行执行的优化,因为当您在 Stream&lt;Integer&gt; 上使用 .boxed().filter(c -&gt; (c &gt; -1001 &amp;&amp; c &lt; 1001)) 时,您正在调用 filter,传递 Predicate&lt;Integer&gt; 而不是 IntPredicate 并且实现别无选择但要将Integer 传递给该代码。

类似的事情也适用于sort;当应用于原始类型数据而不是Integer 对象时,它的效率更高。 distinct 也有类似的潜力,但目前的实现并没有实现这一点。

你必须自己实现更好的算法,这就是挑战的全部内容。

找到数组中不包含的最小正整数的一种解决方案是

int first = Arrays.stream(A)
    .filter(i -> i >= 0)
    .collect(BitSet::new, BitSet::set, BitSet::or)
    .nextClearBit(0);

如果“正”表示“大于零”,则必须使用 i &gt; 0nextClearBit(1)。该解决方案还支持并行处理。

了解现有算法和Java API 提供的数据结构是此类任务的必要条件。以及知道什么是真正不存在的,需要自己去实现。

【讨论】:

  • 嗯,你的回答给了我一些重要的信息。下一个问题:现在我正在尝试处理任务,我需要找到两个数组部分之间的最小差异(类似于子列表)。如何解决?我尝试将其转换为列表,计算所有子列表的总和,最后使用 min() 方法(list.stream().min()),但仍然需要太多时间。
猜你喜欢
  • 1970-01-01
  • 2010-12-12
  • 1970-01-01
  • 1970-01-01
  • 2016-01-30
  • 2015-12-05
  • 2014-12-30
  • 2018-10-22
  • 2010-09-14
相关资源
最近更新 更多