java codility training Genomic-range-query

后端 未结 30 2263
悲哀的现实
悲哀的现实 2021-02-01 12:47

The task is:

A non-empty zero-indexed string S is given. String S consists of N characters from the set of upper-case English letters A, C, G, T.

<
相关标签:
30条回答
  • 2021-02-01 13:34

    Python Solution with explanation

    The idea is to hold an auxiliary array per nucleotide X, with position i (ignoring zero) is how many times X has occurred as of now. And so if we need the number of occurrences of X from position f to position t, we could take the following equation:

    aux(t) - aux(f)

    Time complexity is:

    O(N+M)

    def solution(S, P, Q):
        n = len(S)
        m = len(P)
    
        aux = [[0 for i in range(n+1)] for i in [0,1,2]]
    
        for i,c in enumerate(S):
            aux[0][i+1] = aux[0][i] + ( c == 'A' )
            aux[1][i+1] = aux[1][i] + ( c == 'C' )
            aux[2][i+1] = aux[2][i] + ( c == 'G' )
    
        result = []
    
        for i in range(m):
            fromIndex , toIndex = P[i] , Q[i] +1
            if   aux[0][toIndex] - aux[0][fromIndex] > 0:
                r = 1
            elif aux[1][toIndex] - aux[1][fromIndex] > 0:
                r = 2
            elif aux[2][toIndex] - aux[2][fromIndex] > 0:
                r = 3
            else:
                r = 4
    
            result.append(r)
    
        return result
    
    0 讨论(0)
  • 2021-02-01 13:34
       static public int[] solution(String S, int[] P, int[] Q) {
        // write your code in Java SE 8
    
        int A[] = new int[S.length() + 1], C[] = new int[S.length() + 1], G[] = new int[S.length() + 1];
    
        int last_a = 0, last_c = 0, last_g = 0;
    
        int results[] = new int[P.length];
        int p = 0, q = 0;
        for (int i = S.length() - 1; i >= 0; i -= 1) {
            switch (S.charAt(i)) {
                case 'A': {
                    last_a += 1;
                    break;
                }
                case 'C': {
                    last_c += 1;
                    break;
                }
    
                case 'G': {
                    last_g += 1;
                    break;
                }
    
            }
            A[i] = last_a;
            G[i] = last_g;
            C[i] = last_c;
        }
    
    
        for (int i = 0; i < P.length; i++) {
            p = P[i];
            q = Q[i];
    
            if (A[p] - A[q + 1] > 0) {
                results[i] = 1;
            } else if (C[p] - C[q + 1] > 0) {
                results[i] = 2;
            } else if (G[p] - G[q + 1] > 0) {
                results[i] = 3;
            } else {
                results[i] = 4;
            }
    
        }
        return results;
    }
    
    0 讨论(0)
  • 2021-02-01 13:37

    Here's a simple javascript solution which got 100%.

    function solution(S, P, Q) {
        var A = [];
        var C = [];
        var G = [];
        var T = [];
        var result = [];
        var i = 0;
    
        S.split('').forEach(function(a) {
            if (a === 'A') {
                A.push(i);
            } else if (a === 'C') {
                C.push(i);
            } else if (a === 'G') {
                G.push(i);
            } else {
                T.push(i);
            }
    
            i++;
        });
    
        function hasNucl(typeArray, start, end) {
            return typeArray.some(function(a) {
                return a >= P[j] && a <= Q[j];
            });
        }
    
        for(var j=0; j<P.length; j++) {
            if (hasNucl(A, P[j], P[j])) {
                result.push(1)
            } else if (hasNucl(C, P[j], P[j])) {
                result.push(2);
            } else if (hasNucl(G, P[j], P[j])) {
                result.push(3);
            } else {
                result.push(4);
            }
        }
    
        return result;
    }
    
    0 讨论(0)
  • 2021-02-01 13:39

    simple php 100/100 solution

    function solution($S, $P, $Q) {
        $result = array();
        for ($i = 0; $i < count($P); $i++) {
            $from = $P[$i];
            $to = $Q[$i];
            $length = $from >= $to ? $from - $to + 1 : $to - $from + 1;
            $new = substr($S, $from, $length);
    
            if (strpos($new, 'A') !== false) {
                $result[$i] = 1;
            } else {
                if (strpos($new, 'C') !== false) {
                    $result[$i] = 2;
                } else {
                    if (strpos($new, 'G') !== false) {
                        $result[$i] = 3;
                    } else {
                       $result[$i] = 4;
                    }
                }
            }
        }
        return $result;
    }
    
    0 讨论(0)
  • 2021-02-01 13:40

    Here's 100% Scala solution:

    def solution(S: String, P: Array[Int], Q: Array[Int]): Array[Int] = {
    
    
        val resp = for(ind <- 0 to P.length-1) yield {
    
          val sub= S.substring(P(ind),Q(ind)+1)
    
    
          var factor = 4
    
          if(sub.contains("A")) {factor=1}
          else{
            if(sub.contains("C")) {factor=2}
            else{
              if(sub.contains("G")) {factor=3}
            }
          }
          factor
    
        }
    
        return resp.toArray
    
      }
    

    And performance: https://codility.com/demo/results/trainingEUR4XP-425/

    0 讨论(0)
  • 2021-02-01 13:40

    pshemek's solution constrains itself to the space complexity (O(N)) - even with the 2-d array and the answer array because a constant (4) is used for the 2-d array. That solution also fits in with the computational complexity - whereas mine is O (N^2) - though the actual computational complexity is much lower because it skips over entire ranges that include minimal values.

    I gave it a try - but mine ends up using more space - but makes more intuitive sense to me (C#):

    public static int[] solution(String S, int[] P, int[] Q)
    {
        const int MinValue = 1;
        Dictionary<char, int> stringValueTable = new Dictionary<char,int>(){ {'A', 1}, {'C', 2}, {'G', 3}, {'T', 4} };
    
        char[] inputArray = S.ToCharArray();
        int[,] minRangeTable = new int[S.Length, S.Length]; // The meaning of this table is [x, y] where x is the start index and y is the end index and the value is the min range - if 0 then it is the min range (whatever that is)
        for (int startIndex = 0; startIndex < S.Length; ++startIndex)
        {
            int currentMinValue = 4;
            int minValueIndex = -1;
            for (int endIndex = startIndex; (endIndex < S.Length) && (minValueIndex == -1); ++endIndex)
            {
                int currentValue = stringValueTable[inputArray[endIndex]];
                if (currentValue < currentMinValue)
                {
                    currentMinValue = currentValue;
                    if (currentMinValue == MinValue) // We can stop iterating - because anything with this index in its range will always be minimal
                        minValueIndex = endIndex;
                    else
                        minRangeTable[startIndex, endIndex] = currentValue;
                }
                else
                    minRangeTable[startIndex, endIndex] = currentValue;
            }
    
            if (minValueIndex != -1) // Skip over this index - since it is minimal
                startIndex = minValueIndex; // We would have a "+ 1" here - but the "auto-increment" in the for statement will get us past this index
        }
    
        int[] result = new int[P.Length];
        for (int outputIndex = 0; outputIndex < result.Length; ++outputIndex)
        {
            result[outputIndex] = minRangeTable[P[outputIndex], Q[outputIndex]];
            if (result[outputIndex] == 0) // We could avoid this if we initialized our 2-d array with 1's
                result[outputIndex] = 1;
        }
    
        return result;
    }
    

    In pshemek's answer - the "trick" in the second loop is simply that once you've determined you've found a range with the minimal value - you don't need to continue iterating. Not sure if that helps.

    0 讨论(0)
提交回复
热议问题