当前位置: 首页 > 知识库问答 >
问题:

java代码训练基因组范围查询

翟卓君
2023-03-14

任务是:

给出了一个非空的零索引字符串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

查询K要求您从范围(P[K],Q[K]),0中找到最小核苷酸≤ P【i】≤ 问题[i]

例如,考虑字符串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,使得:

P[0] = 0    Q[0] = 8
P[1] = 0    Q[1] = 2
P[2] = 4    Q[2] = 5
P[3] = 7    Q[3] = 7

如上所述,该函数应返回值 [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。

共有3个答案

苏翰学
2023-03-14

Java,100/100,但是没有累积/前缀和!我在一个数组“地图”中隐藏了低3个核苷酸的最后出现索引。稍后我检查最后一个索引是否在P-Q之间。如果是,它返回nuclotide,如果没有找到,它是顶部的一个(T):

class Solution {

int[][] lastOccurrencesMap;

public int[] solution(String S, int[] P, int[] Q) {
    int N = S.length();
    int M = P.length;

    int[] result = new int[M];
    lastOccurrencesMap = new int[3][N];
    int lastA = -1;
    int lastC = -1;
    int lastG = -1;

    for (int i = 0; i < N; i++) {
        char c = S.charAt(i);

        if (c == 'A') {
            lastA = i;
        } else if (c == 'C') {
            lastC = i;
        } else if (c == 'G') {
            lastG = i;
        }

        lastOccurrencesMap[0][i] = lastA;
        lastOccurrencesMap[1][i] = lastC;
        lastOccurrencesMap[2][i] = lastG;
    }

    for (int i = 0; i < M; i++) {
        int startIndex = P[i];
        int endIndex = Q[i];

        int minimum = 4;
        for (int n = 0; n < 3; n++) {
            int lastOccurence = getLastNucleotideOccurrence(startIndex, endIndex, n);
            if (lastOccurence != 0) {
                minimum = n + 1; 
                break;
            }
        }

        result[i] = minimum;
    }
    return result;
}

int getLastNucleotideOccurrence(int startIndex, int endIndex, int nucleotideIndex) {
    int[] lastOccurrences = lastOccurrencesMap[nucleotideIndex];
    int endValueLastOccurenceIndex = lastOccurrences[endIndex];
    if (endValueLastOccurenceIndex >= startIndex) {
        return nucleotideIndex + 1;
    } else {
        return 0;
    }
}
}
曾新立
2023-03-14

简单,优雅,领域特定,100/100 JS解决方案,带注释!

function solution(S, P, Q) {
    var N = S.length, M = P.length;

    // dictionary to map nucleotide to impact factor
    var impact = {A : 1, C : 2, G : 3, T : 4};

    // nucleotide total count in DNA
    var currCounter = {A : 0, C : 0, G : 0, T : 0};

    // how many times nucleotide repeats at the moment we reach S[i]
    var counters = [];

    // result
    var minImpact = [];

    var i;

    // count nucleotides
    for(i = 0; i <= N; i++) {
        counters.push({A: currCounter.A, C: currCounter.C, G: currCounter.G});
        currCounter[S[i]]++;
    }

    // for every query
    for(i = 0; i < M; i++) {
        var from = P[i], to = Q[i] + 1;

        // compare count of A at the start of query with count at the end of equry
        // if counter was changed then query contains A
        if(counters[to].A - counters[from].A > 0) {
            minImpact.push(impact.A);
        }
        // same things for C and others nucleotides with higher impact factor
        else if(counters[to].C - counters[from].C > 0) {
            minImpact.push(impact.C);
        }
        else if(counters[to].G - counters[from].G > 0) {
            minImpact.push(impact.G);
        }
        else { // one of the counters MUST be changed, so its T
            minImpact.push(impact.T);
        }
    }

    return minImpact;
}
那昊
2023-03-14

这是 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;
    }
 类似资料:
  • 问题内容: 任务是: 给出了一个非空的零索引字符串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要求

  • 下面是一些代码的压缩版本,它会导致范围检查错误和溢出错误,如果我打开这些编译器检查指令的话。我理解为什么这会导致溢出,在C1的乘法上,它似乎可能会超过数据类型的最大值。但为什么这也会触发范围检查错误?Delphi的文档和其他关于堆栈溢出的文章听起来像是范围检查错误通常是针对超出范围的数组访问。但是我没有访问一个数组,因为它说的数组导致了范围检查错误。也许是在派往param1的任务上?但如果是这样的

  • 可以对模型的查询和写入操作进行封装,例如: <?php namespace app\index\model; use think\Model; class User extends Model { public function scopeThinkphp($query) { $query->where('name','thinkphp')->field('i

  • 自我介绍 介绍上段实习 redis底层有了解吗 这些数据结构使用场景 redis为什么单线程快 上段实习redis使用场景和数据类型 什么是雪崩,怎么解决 sql写的多吗,考虑过优化方面的吗 一个表最多多少索引 mysql 索引底层 联合索引原理 线程池创建方法 什么时候用到线程池 Lock底层原理 上段实习做了什么有意义的事 遇到些什么问题 为什么离职,来得物会不会也离职 反问阶段

  • 本文向大家介绍django 按时间范围查询数据库实例代码,包括了django 按时间范围查询数据库实例代码的使用技巧和注意事项,需要的朋友参考一下 从前台中获得时间范围,在django后台处理request中数据,完成format,按照范围调用函数查询数据库。 介绍一个简单的功能,就是从web表单里获取用户指定的时间范围,然后在数据库中查询此时间范围内的数据。 数据库里的model举例是这样: 假

  • MySQL 提供了  BETWEEN AND 关键字,用来判断字段的数值是否在指定范围内。 BETWEEN AND 需要两个参数,即范围的起始值和终止值。如果字段值在指定的范围内,则这些记录被返回。如果不在指定范围内,则不会被返回。 使用 BETWEEN AND 的基本语法格式如下: [NOT] BETWEEN 取值1 AND 取值2 其中: NOT:可选参数,表示指定范围之外的值。如果字段值不满