【问题标题】:How to calculate GCD for every index in array with some constraints如何计算具有某些约束的数组中每个索引的 GCD
【发布时间】:2016-11-19 22:30:31
【问题描述】:

给定一个 1 索引数组 A,大​​小为 N,任意之间的距离 ij 数组的 2 个索引由 |i−j| 给出。现在,根据这些信息,我需要为每个索引 i (1≤i≤N) 找到一个索引 j,这样 1≤j≤N、i≠jGCD(A[i],A[j])>1

如果一个索引i有多个这样的候选,必须找到索引j,使得i之间的距离>j 是最小的。如果仍然存在多个候选,则打印满足上述约束的最小 j

示例: 数组(A) 2 3 4 9 17

输出:3 4 1 2 -1

注意:数组大小可以大到 2*10^5。 并且每个数组元素可以取最大值 2*10^5 和最小值 1。

我应该最多可以在 1 秒内计算出来。

这是我的代码,但它超出了时间限制。有没有办法优化它。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class GCD {


public static void main(String[] args) throws IOException {

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    int n = Integer.parseInt(br.readLine().trim());
    int[] a = new int[n+1];
    StringBuilder sb =new StringBuilder("");
    String[] array = br.readLine().trim().split(" ");

    for(int i=1; i<=n; i++){
        a[i] = Integer.parseInt(array[i-1]);
    }

    int c,d;
l1: for(int i=1; i<=n; i++){
        c = i-1;
        d = i+1;
        while((c>0||d<=n)){
            if(c>0){
                if(GCD(a[i],a[c])>1){
                    sb.append(c+" ");
                    continue l1;
                }
            }
            if(d<=n){   
                if(GCD(a[i],a[d])>1){
                    sb.append(d+" ");
                    continue l1;
                }   
            }
            c--;
            d++;
        }

         sb.append("-1 ");
    }
    System.out.println(sb);
}


    static long GCD(int a, int b){
        if(b==0)
           return a;
        return GCD(b, a%b);
    }

}

【问题讨论】:

  • 你注意到我的答案和 div 的答案实际上根本没有计算 GCD 吗?

标签: arrays algorithm greatest-common-divisor


【解决方案1】:

您知道问题可以在一秒钟内解决。你知道数组可以有 200,000 个元素。将 200,000 个元素与 200,000 个元素进行比较需要 400 亿次比较。如果幸运的话,您的计算机每秒执行 30 亿次操作。您会看到将 200,000 个元素与 200,000 个元素进行比较是行不通的。 (这会发生在所有数组元素都等于 1 的简单情况下)。所以优化你的代码不会有帮助。

因此,让您的注意力远离问题的提出方式。它要求找到 j 使得 gcd (a [i], a [j]) != 1。它真正的意思是找到 j 使得 a [j] 与 a [i] 有一个共同的质因数。并且 j 需要是最大的 j i。

数字很小,不到 200,000。因此,您可以非常快速地找到 a [i] 的所有不同质因数。

所以首先你创建一个数组“index”:对于每个素数 p

遍历数组 i = 1 到 n:对于每个 a [i],找到所有质因子。对于每个因子 p:如果 j = index [p] > 0,那么 a [j] 也可以被 p 整除,所以 gcd (a [i], a [j]) > 1。这样做你会得到最大的 j 1。在找到素因子时也更新数组索引。

而且如果你发现 a [i] 和 a [j] 有一个公因子,那么你为 j 存储的解可能是错误的,因为它只考虑小于 j 的索引,所以也要更新解。伪代码:

Create array "index" filled with -1.
Create array "solution" filled with -1.

for all i
    for all prime factors p of a [i]
        let j = index [p]
        index [p] = j
        if j >= 0
            if solution [i] = -1
                solution [i] = j
            else if j > solution [i]
                solution [i] = j

            if solution [j] = -1
                solution [j] = i
            else if solution [j] < j && i-j < j - solution [j]
                solution [j] = i

print solution

您可以看到,具有公因数的数组元素相距多远并不重要。执行时间是素数因子数的一个非常小的数字,加上寻找因子的时间,如果所有元素都是大素数,这是最差的。因此,您需要做的就是在 3-4 微秒内找到任何小于 200,000 的所有因数。应该很容易。在开始之前,您可以创建一个最多 500 个素数的表格。

【讨论】:

    【解决方案2】:

    要在 1 秒内运行,您的算法应该是 θ(N) 或 θ(N * log(N)),N

    1. 让我们在数组的 1 次迭代中找到所有数字中除 1 之外的所有因子。复杂度 = θ(N) * θ(GCD) = θ(N * log(N))
    2. 制作一个散列图,其中键 = 我们刚刚找到的因子,值 = 输入中元素索引的排序数组,它们是它们的因子。 (哈希图中的数组是按顺序排列的,所以不需要显式排序。因子数
    3. 现在我们遍历元素并在每个元素中遍历因子,对于每个因子,我们使用二分搜索从哈希图中找到该因子存在于最近索引中的位置。我们为每个元素的所有因子选择最接近的值,并将其作为答案。复杂度 = θ (N * log(N) * log(log(N)))。

    【讨论】:

    • 查找给定数组的所有元素的因子不会超过 O(NlogN) 吗?如果 HashMap 如下所示是否有益: HashMap(,) 因为这样可以节省对索引的搜索?
    • 你可以分享一个 pastebin 链接或者把代码邮寄给我 divyanshu102201@gmail.com
    • 抱歉,我指的是主要因素,可以在 log(n) 时间内找到。可能需要一个最大为 2*10^5 的素数数组来加快处理速度,可以使用 Eratosthenes seive。
    猜你喜欢
    • 1970-01-01
    • 2021-05-28
    • 2022-06-03
    • 1970-01-01
    • 2013-05-23
    • 2018-02-26
    • 2020-06-24
    • 2011-09-01
    • 1970-01-01
    相关资源
    最近更新 更多