任务是:
给出了一个非空的零索引字符串S。字符串S由N个大写英文字母A,C,G,T字符组成。
该字符串实际上代表DNA序列,大写字母代表单个核苷酸。
还为您提供了由M个整数组成的非空零索引数组P和Q。这些数组表示有关最小核苷酸的查询。我们将字符串S的字母表示为数组P和Q中的整数1、2、3、4,其中A = 1,C = 2,G = 3,T = 4,并假定A <C <G <T 。
查询K要求您从范围(P [K],Q [K])中找到最小的核苷酸,0≤P [i]≤Q [i] <N。
例如,考虑字符串S = GACACCATA和数组P,Q,使得:
P[0] = 0 Q[0] = 8 P[1] = 0 Q[1] = 2 P[2] = 4 Q[2] = 5 P[3] = 7 Q[3] = 7
这些范围内的最小核苷酸如下:
(0, 8) is A identified by 1, (0, 2) is A identified by 1, (4, 5) is C identified by 2, (7, 7) is T identified by 4.
编写一个函数:
class Solution { public int[] solution(String S, int[] P, int[] Q); }
假设给定一个由N个字符组成的非空零索引字符串S和两个由M个整数组成的非空零索引数组P和Q,则返回一个由M个字符组成的数组,指定所有查询的连续答案。
该序列应返回为:
a Results structure (in C), or a vector of integers (in C++), or a Results record (in Pascal), or an array of integers (in any other programming language).
例如,给定字符串S = GACACCATA和数组P,Q,使得:
该函数应返回值[1,1,2,4],如上所述。
假使,假设:
N is an integer within the range [1..100,000]; M is an integer within the range [1..50,000]; each element of array P, Q is an integer within the range [0..N − 1]; P[i] ≤ Q[i]; string S consists only of upper-case English letters A, C, G, T.
复杂:
expected worst-case time complexity is O(N+M); expected worst-case space complexity is O(N), beyond input storage (not counting the storage required for input arguments).
输入数组的元素可以修改。
我的解决方案是:
class Solution { public int[] solution(String S, int[] P, int[] Q) { final char c[] = S.toCharArray(); final int answer[] = new int[P.length]; int tempAnswer; char tempC; for (int iii = 0; iii < P.length; iii++) { tempAnswer = 4; for (int zzz = P[iii]; zzz <= Q[iii]; zzz++) { tempC = c[zzz]; if (tempC == 'A') { tempAnswer = 1; break; } else if (tempC == 'C') { if (tempAnswer > 2) { tempAnswer = 2; } } else if (tempC == 'G') { if (tempAnswer > 3) { tempAnswer = 3; } } } answer[iii] = tempAnswer; } return answer; } }
这不是最佳选择,我相信应该在一个循环内完成,有什么提示我该如何实现?
您可以在此处检查解决方案的质量https://codility.com/train/测试名称为Genomic- range-query。
以下是在codility.com中获得100分之100的解决方案。请阅读有关前缀和的信息,以了解解决方案:
public static int[] solveGenomicRange(String S, int[] P, int[] Q) { //used jagged array to hold the prefix sums of each A, C and G genoms //we don't need to get prefix sums of T, you will see why. int[][] genoms = new int[3][S.length()+1]; //if the char is found in the index i, then we set it to be 1 else they are 0 //3 short values are needed for this reason short a, c, g; for (int i=0; i<S.length(); i++) { a = 0; c = 0; g = 0; if ('A' == (S.charAt(i))) { a=1; } if ('C' == (S.charAt(i))) { c=1; } if ('G' == (S.charAt(i))) { g=1; } //here we calculate prefix sums. To learn what's prefix sums look at here https://codility.com/media/train/3-PrefixSums.pdf genoms[0][i+1] = genoms[0][i] + a; genoms[1][i+1] = genoms[1][i] + c; genoms[2][i+1] = genoms[2][i] + g; } int[] result = new int[P.length]; //here we go through the provided P[] and Q[] arrays as intervals for (int i=0; i<P.length; i++) { int fromIndex = P[i]; //we need to add 1 to Q[i], //because our genoms[0][0], genoms[1][0] and genoms[2][0] //have 0 values by default, look above genoms[0][i+1] = genoms[0][i] + a; int toIndex = Q[i]+1; if (genoms[0][toIndex] - genoms[0][fromIndex] > 0) { result[i] = 1; } else if (genoms[1][toIndex] - genoms[1][fromIndex] > 0) { result[i] = 2; } else if (genoms[2][toIndex] - genoms[2][fromIndex] > 0) { result[i] = 3; } else { result[i] = 4; } } return result; }