【问题标题】:Count the number of integers in an array divisible by a given query k计算数组中可被给定查询 k 整除的整数个数
【发布时间】:2017-09-24 08:27:05
【问题描述】:

在这个问题中,我有许多查询,我必须在 array 中输出 integers 的计数,该计数可被 k 整除(其中一个查询)。array 包含重复的元素。我正在尝试优化问题,我的方法如下:

代码:

public static void main(String[] args) {
    Scanner sc=new Scanner(System.in);
     int[] ar={2,4,6,9,11,34,654,23,32,54,76,21432,32543,435,43543,643,2646,4567,457654,75,754,7,567865,8765877,53,2};
     int query=sc.nextInt();
     int length=ar.length;
     int count=0;
     for (int i=0;i<query ;i++ ) {
        int x=sc.nextInt();
        for (int j=0;j<length ;j++ ) {
            if(ar[j]>x){
                if(ar[j]%x==0){
                    count++;
                }
            }
        }
        System.out.println("Count:"+count);
     }
}

上面的代码给出了正确的输出,但复杂度是O(query*length),如果数组大小更大,程序会timeout

谁能帮我优化问题?

【问题讨论】:

  • 您可以将ar 数组分成三个较小的数组:一个是素数,一个是小非素数,一个是大非素数。对于素数,您不必检查模余数。一个等于素数的数不能等于另一个素数。根据x的大小,可以跳过小数组数字。
  • 这是来自任何编码平台(如hackerank 或leetcode)的问题吗?如果是,您能否提供问题的链接以验证测试用例?
  • 好的,我试试
  • @CodeHunter,这是来自编码平台hackerearth的问题,但没有显示任何测试用例。
  • 数组的最大长度是多少?该数组中元素的最大值是多少?

标签: java arrays algorithm performance optimization


【解决方案1】:

您可以做的一种优化是利用short-circuiting,并使用一个 if 语句(而不是两个)。

所以改变这个:

if(ar[j]>x) {
  if(ar[j]%x==0) {

到这里:

if(ar[j]>x && ar[j]%x==0) {

这不会影响算法的时间复杂度,但会帮助Branch Prediction

【讨论】:

  • 是的,试过了,但我的主要动机是打破O(query*length)并优化它。
  • 不会的。这两个 sn-ps 是等价的,编译器(JITc 不是 javac)知道这一点。
【解决方案2】:

数组中一个元素的最大值是10^5

这使它变得微不足道。使用boolean[10001] 并标记所有查询的所有倍数。然后用它来测试元素。

新的问题是当有很多小查询时如何标记所有的倍数。最坏的情况是像{1, 1, 1, ...} 这样的查询,但是可以简单地删除重复项,例如使用HashSet。现在最坏的情况是{1, 2, 3, 4, ...},它需要10001/1 + 10001/2 + 10001/3... 步骤。您可以对最小的查询进行一些特殊处理,例如删除多个查询。

例如,当您查看最多 10 个查询并删除其中的多个查询时,最坏的情况是 {2, 3, 5, 7, 11, 12, 13, 14...},这应该会使标记非常快。这一步可能根本不需要。

【讨论】:

    【解决方案3】:

    您可以执行预计算步骤来构建除数表。对于数组中的每个元素,计算它的除数。假设V 是数组中的最大值,您可以在O(sqrt(V)) 中有效地计算数字的除数。构建完整的表将花费O(n * sqrt(V)),根据您的约束等于100,000 * sqrt(100,000) =~ 32M,这应该不会很多。内存复杂度是一样的。

    然后您可以通过查表来回答您在O(1) 中的查询。

    您可以查看link,了解如何在O(sqrt(V)) 中生成除数。

    【讨论】:

    • 好的,我试试
    • 你能帮我制作除数表吗,比如我应该使用什么数据结构来存储除数
    • 一个哈希集就足够了。每当您找到一个除以数组中任何数字的数字时,将其插入哈希集中。稍后当您收到查询时检查它是否在哈希集中。
    • 只有一个问题,如果假设数组包含重复值,查询的输出将不正确
    • 我应用了你的算法,而不是hashset,我使用了arraylist,因为数组可以包含重复的元素,但超过了时间限制。这里的主要问题是array 包含重复的元素,即使我要为每个查询构建一个除数表,我也必须在list 中获取查询的频率/计数,并且时间限制超过.
    猜你喜欢
    • 1970-01-01
    • 2013-05-12
    • 1970-01-01
    • 2017-07-05
    • 1970-01-01
    • 2015-12-22
    • 1970-01-01
    • 1970-01-01
    • 2013-03-10
    相关资源
    最近更新 更多