zoukankan      html  css  js  c++  java
  • prefix sums--codility

    lesson 5: prefix sums

    1. PassingCars

    Count the number of passing cars on the road.

    A non-empty zero-indexed array A consisting of N integers is given. The consecutive elements of array A represent consecutive cars on a road.

    Array A contains only 0s and/or 1s:

    0 represents a car traveling east,
    1 represents a car traveling west.
    The goal is to count passing cars. We say that a pair of cars (P, Q), where 0 ≤ P < Q < N, is passing when P is traveling to the east and Q is traveling to the west.

    For example, consider array A such that:

      A[0] = 0
      A[1] = 1
      A[2] = 0
      A[3] = 1
      A[4] = 1
    

    We have five pairs of passing cars: (0, 1), (0, 3), (0, 4), (2, 3), (2, 4).

    Assume that:

    • N is an integer within the range [1..100,000];
    • each element of array A is an integer that can have one of the following values: 0, 1.

    Complexity:

    • expected worst-case time complexity is O(N);
    • expected worst-case space complexity is O(1),

    思路:

    • 可以计算suffix sum的方式

    • 然后,从前面开始遍历list,遇到a = 0,result即加上当前的suffix sum的值

    • 此题元素是0,1,故可以不用保留每一步的计算,题目有要求限制O(1)的space, 也是给出提示,用一个变量retsum值来记录,每一步的prefix sum值,每移动一步,元素是1的话,将retsum 减1, 即是下一个prefix sum 值。

    • Detected time complexity: O(N)

    • [100%]

    def solution(A):
        # write your code in Python 2.7
        result = 0
        retsum = sum(A)
        for a in A:
            if a == 0:
                result += retsum
                if result > 1000000000:
                    return -1
            else:
                retsum -= 1
        return result
    

    2. CountDiv

    Compute number of integers divisible by k in range [a..b].

    given three integers A, B and K, returns the number of integers within the range [A..B] that are divisible by K, i.e.:

    { i : A ≤ i ≤ B, i mod K = 0 }

    For example, for A = 6, B = 11 and K = 2, your function should return 3, because there are three numbers divisible by 2 within the range [6..11], namely 6, 8 and 10.

    Assume that:

    • A and B are integers within the range [0..2,000,000,000];
    • K is an integer within the range [1..2,000,000,000];
      A ≤ B.

    Complexity:

    • expected worst-case time complexity is O(1);
    • expected worst-case space complexity is O(1).

    CountDiv solution 1

    • Test score 100%
    def solution(A, B, K):
        # write your code in Python 2.7
        ra = -1 if A == 0 else (A - 1)/K 
        rb = B/K
        
        return rb -ra
        
    

    solution 2

    • Test score 100%
    def solution(A, B, K):
        # write your code in Python 2.7
        c = 1 if A%K == 0 else 0
        return B/K -A/K + c
        
    
    def solution(A, B, K):
        # write your code in Python 2.7
        return (B/K - A/K) if (A%K != 0 ) else (B/K - A/K + 1)
    

    3. GenomicRangeQuery

    Find the minimal nucleotide from a range of sequence DNA.

    A DNA sequence can be represented as a string consisting of the letters A, C, G and T, which correspond to the types of successive nucleotides in the sequence. Each nucleotide has an impact factor, which is an integer. Nucleotides of types A, C, G and T have impact factors of 1, 2, 3 and 4, respectively. You are going to answer several queries of the form: What is the minimal impact factor of nucleotides contained in a particular part of the given DNA sequence?

    The DNA sequence is given as a non-empty string S = S[0]S[1]...S[N-1] consisting of N characters. There are M queries, which are given in non-empty arrays P and Q, each consisting of M integers. The K-th query (0 ≤ K < M) requires you to find the minimal impact factor of nucleotides contained in the DNA sequence between positions P[K] and Q[K](inclusive).

    For example, consider string S = CAGCCTA and arrays P, Q such that:

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

    The answers to these M = 3 queries are as follows:

    • The part of the DNA between positions 2 and 4 contains nucleotides G and C (twice), whose impact factors are 3 and 2 respectively, so the answer is 2.
    • The part between positions 5 and 5 contains a single nucleotide T, whose impact factor is 4, so the answer is 4.
    • The part between positions 0 and 6 (the whole string) contains all nucleotides, in particular nucleotide A whose impact factor is 1, so the answer is 1.

    the function should return the values [2, 4, 1], as explained above.

    Assume that:

    • N is an integer within the range [1..100,000];
    • M is an integer within the range [1..50,000];
    • each element of arrays P, Q is an integer within the range [0..N − 1];
    • P[K] ≤ Q[K], where 0 ≤ K < M;
    • string S consists only of upper-case English letters A, C, G, T.

    Complexity:

    • 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).

    解法一:

    • Test score 62%
    • Detected time complexity:
      O(N * M)
    • 最初的想法是:根据给出的范围,用set保存,看是否有各元素
    • 时间复杂度,明显达不到O(N+M)
    def getMinFactor(S,l,i,j):
        if j == (l-1):
            tmp = set(S[i:])  #
        else:
            tmp = set(S[i:(j+1)])
        if 'A' in tmp:
            return 1
        elif 'C' in tmp:
            return 2
        elif 'G' in tmp:
            return 3
        else:
            return 4
            
    def solution(S, P, Q):
        # write your code in Python 2.7
        length = len(S)
        result = []
        for x,y in zip(P,Q):
            #print x,y
            result.append(getMinFactor(S,length,x,y))
        return result
    

    解法二:

    • Test score 100%
    • used each list to save that states whether has element or not
    • 在用prefix sum 做差的方式,依次检查是否存在A,C,G,T字符
    • 注意数值关系
    def calcPrefixSum(S):
        l = len(S)+1
        pa,pc,pg = [0]*l,[0]*l,[0]*l
        for idx,elem in enumerate(S):
            a,c,g = 0,0,0
            if elem == 'A':
                a = 1
            elif elem == 'C':
                c = 1
            elif elem == 'G':
                g = 1
            pa[idx+1] = pa[idx] + a
            pc[idx+1] = pc[idx] + c
            pg[idx+1] = pg[idx] + g
        return pa,pc,pg
    
    def solution(S, P, Q):
        # write your code in Python 2.7
        pA,pC,pG = calcPrefixSum(S)
        result = []
        for i,j in zip(P,Q):
            if pA[j+1] - pA[i] > 0:
                ret = 1
            elif pC[j+1] - pC[i] > 0:
                ret = 2
            elif pG[j+1] - pG[i] > 0:
                ret = 3
            else:
                ret = 4
            result.append(ret)
        return result
        
    
    根据prefix sum list:
    pA = [0, 0, 1, 1, 1, 1, 1, 2]
    pC = [0, 1, 1, 1, 2, 3, 3, 3]
    pG = [0, 0, 0, 1, 1, 1, 1, 1]
    
    故,是下标[j+1]-[i]
    

    4. MinAvgTwoSlice

    Find the minimal average of any slice containing at least two elements.

    A non-empty zero-indexed array A consisting of N integers is given. A pair of integers (P, Q), such that 0 ≤ P < Q < N, is called a slice of array A (notice that the slice contains at least two elements). The average of a slice (P, Q) is the sum of A[P] + A[P + 1] + ... + A[Q] divided by the length of the slice. To be precise, the average equals (A[P] + A[P + 1] + ... + A[Q]) / (Q − P + 1).

    For example, array A such that:

    A[0] = 4
    A[1] = 2
    A[2] = 2
    A[3] = 5
    A[4] = 1
    A[5] = 5
    A[6] = 8
    

    contains the following example slices:

    • slice (1, 2), whose average is (2 + 2) / 2 = 2;
    • slice (3, 4), whose average is (5 + 1) / 2 = 3;
    • slice (1, 4), whose average is (2 + 2 + 5 + 1) / 4 = 2.5.

    The goal is to find the starting position of a slice whose average is minimal.

    Complexity:

    • expected worst-case time complexity is O(N);
    • expected worst-case space complexity is O(N),

    sloution

    • Test score 100%

    note: transfer to 2/3 ,

    • 只要查看相邻两个和三个的数的平均值即可
    • proof
    def solution(A):
        # write your code in Python 2.7
        length = len(A)
        minStartPos = 0
        minSum = (A[0] + A[1])/2.0
        
        for i in xrange(length - 2):
            tmp = (A[i] + A[i+1])/2.0
            if tmp < minSum:
                minSum = tmp
                minStartPos = i
            tmp = (tmp*2 + A[i+2])/3.0
            if tmp < minSum:
                minSum = tmp
                minStartPos = i
        if (A[-1] + A[-2])/2.0 < minSum:
            minStartPos = length - 2
        
        return minStartPos
    
  • 相关阅读:
    Provisioning profile 浅析
    Swift --> Map & FlatMap
    Swift 学习笔记(五)
    Swift 学习笔记(四)
    Swift 学习笔记 (三) 之循环引用浅析
    Swift 学习笔记 (二)
    HomeBrew
    UIGestureRecognizer 手势浅析
    frame、bounds表示大小和位置的属性以及center、position、anchorPosition
    UIViewContentMode 图文解说
  • 原文地址:https://www.cnblogs.com/Qwells/p/5839762.html
Copyright © 2011-2022 走看看