【问题标题】:unable to pass performance at Codility GenomicRangeQuery test在 Codility GenomicRangeQuery 测试中无法通过性能
【发布时间】:2019-10-04 20:50:01
【问题描述】:

能否请您检查代码并让我知道我必须做些什么来提高性能?这个性能问题让我对 Codility 很生气。这是下面的问题和我的代码。

感谢您从现在开始的帮助。

测试:

询问描述 DNA序列可以表示为由字母A、C、G和T组成的字符串,它们对应于序列中连续核苷酸的类型。每个核苷酸都有一个影响因子,它是一个整数。 A、C、G 和 T 型核苷酸的影响因子分别为 1、2、3 和 4。您将回答以下几个问题:给定 DNA 序列的特定部分中包含的核苷酸的最小影响因子是多少?

DNA 序列以非空字符串 S = S[0]S[1]...S[N-1] 的形式给出,由 N 个字符组成。有 M 个查询,它们在非空数组 P 和 Q 中给出,每个由 M 个整数组成。第 K 次查询(0 ≤ K

例如,考虑字符串 S = CAGCCTA 和数组 P、Q,这样:

P[0] = 2    Q[0] = 4
P[1] = 5    Q[1] = 5
P[2] = 0    Q[2] = 6

这 M = 3 个查询的答案如下:

DNA 中 2 和 4 位之间的部分含有核苷酸 G 和 C(两次),其影响因子分别为 3 和 2,因此答案为 2。 位置 5 和 5 之间的部分包含一个单核苷酸 T,其影响因子为 4,因此答案为 4。 位置 0 和 6 之间的部分(整个字符串)包含所有核苷酸,特别是影响因子为 1 的核苷酸 A,因此答案为 1。 写一个函数:

类解决方案 { public int[] solution(String S, int[] P, int[] Q); }

给定一个由 N 个字符组成的非空字符串 S 和两个由 M 个整数组成的非空数组 P 和 Q,返回一个由 M 个整数组成的数组,指定所有查询的连续答案。

结果数组应作为整数数组返回。

例如,给定字符串 S = CAGCCTA 和数组 P、Q 使得:

P[0] = 2    Q[0] = 4
P[1] = 5    Q[1] = 5
P[2] = 0    Q[2] = 6

该函数应返回值 [2, 4, 1],如上所述。

为以下假设编写一个有效的算法:

N 是 [1..100,000] 范围内的整数; M 是 [1..50,000] 范围内的整数; 数组 P、Q 的每个元素都是 [0..N - 1] 范围内的整数; P[K] ≤ Q[K],其中 0 ≤ K

我的解决方案:

  public static int[] solution(String S, int[] firstArray, int[] secondArray) {
    String subStr="";
    int[] result = new int[firstArray.length];
    for(int i=0; i < firstArray.length; i++)  {
        subStr = S.substring(firstArray[i], secondArray[i] + 1);
        if(subStr.contains("A")) { result[i] = 1; }
        else if(subStr.contains("C")){ result[i] = 2; }
        else if(subStr.contains("G")){ result[i] = 3;
        } else if(subStr.contains("T")){ result[i] = 4;
        }
    }

返回结果; }

【问题讨论】:

    标签: java performance


    【解决方案1】:

    您的解决方案的复杂度为 O(M*N)。
    外循环: for(int i=0; i 内循环:评估 N 大小的列表 S 以构造 subStr(此时复杂度为 MxN)
    相同的内循环:检查每个 subStr 是否包含 4 个字母中的每一个(此时复杂度为 MxN)

    为了提高性能,您的解决方案需要取消内部循环。一种方法是将 S 转换为我们可以直接访问相关值而不是遍历(即构造 subStr)的形式。

    将 S 转换为可直接访问的相关内容的一种方法是在序列中的每个位置存储 4 个核苷酸 (A/C/G/T) 中每个核苷酸的最后可观察位置。

    例如,如果 S = "CGGT",我们可以将其转换为,-1 表示“尚未观察到”:

    Idx A, C, G, T  
    0  [-1, 0,-1,-1]  
    1  [-1, 0, 1,-1]  
    2  [-1, 0, 2,-1]  
    3  [-1, 0, 2, 3]
    

    有了这个矩阵,我们现在可以直接访问它来获取相关值。在这种情况下,如果我们试图获取 subStr "GG" 的相关值,即 P[0] = 1 和 Q[0] = 2, 那么我们只需要访问索引 2。在这种情况下,[-1, 0, 2, -1] 告诉我们在索引 1 之后最后一次观察到 G,因此,最小影响是 G 到它的影响因子的映射.

    构建矩阵的复杂度为 O(N)。遍历 P 和 Q 的复杂度为 O(M)。由于没有嵌套循环,因此整体复杂度为 O(N+M)。

    下面是 Python 实现的 sn-p:

    def solution(S,P,Q):
        l = len(S)    
        lastSeen = [[-1,-1,-1,-1] for x in range(l)]
        for x in range(len(S)):
            for i,j in enumerate(list("ACGT")):
                if S[x] == j:
                    lastSeen[x][i] = x
                elif x>0: 
                    lastSeen[x][i] = lastSeen[x-1][i]
    
        res = []
        for x in range(len(P)):
            startIdx = P[x]
            relevantLastSeen = lastSeen[Q[x]]
            res.append((min([i+1 for i,x in enumerate(relevantLastSeen) if x>=startIdx])))
    
        return res
    

    【讨论】:

      猜你喜欢
      • 2016-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-11
      • 1970-01-01
      • 2019-10-14
      • 1970-01-01
      • 2022-01-09
      相关资源
      最近更新 更多