Codility刷题之旅 - Challenges - Challenges of 2011 (1)

381 阅读1分钟

Challenge - Gamma 2011 - CountPalindromicSlices

image.png

def solution(S):
    result = 0
    N = len(S)
    MAX_RES = 100000000
    # 单个s,为palindromic的中间元素(奇数)
    for i,s in enumerate(S[1:-1]):
        search_i1, search_i2 = i, i+2
        while search_i1>=0 and search_i2<=N-1:
            if S[search_i1]==S[search_i2]: 
                result += 1
                if result > MAX_RES:
                    return -1
                search_i1 -= 1
                search_i2 += 1
            else:
                break 

    # 连续两个s,为palindromic的中间元素(偶数)
    for i, s in enumerate(S[:-1]):
        search_i1, search_i2 = i, i+1
        while search_i1>=0 and search_i2<=N-1:
            if S[search_i1]==S[search_i2]: 
                result += 1
                if result > MAX_RES:
                    return -1
                search_i1 -= 1
                search_i2 += 1
            else:
                break 
    return result 

image.png

可以看到,虽然Correctness可以达到100%,但是Performance并不能符合题目要求的Efficiency,目前算法的时间复杂度是O(N**2)。

稍微上网搜索了下,本题还算是比较经典的回文数的题了,Leetcode上也有。而这道题有一个复杂度为O(n)的马拉车解法(Manacher Algorithm),是1975年由Manacher发明的。知乎上有一个专门的帖子,各路大神从各个角度来尝试讲清楚这个算法,相信总有一款适合你:www.zhihu.com/question/37…

而我主要是看了答案中的这一篇看懂的:

具体Python实现如下:

def solution(S):
    T = '#'.join('^{}$'.format(S))
    # T = s
    P = [0] * len(T)
    R, C = 0, 0
    for i in range(1,len(T) - 1):
        if i < R:
            P[i] = min(P[2 * C - i], R - i)
        
        while T[i+(P[i]+1)] == T[i-(P[i]+1)]:
            P[i] += 1
        
        if i + P[i] > R:
            R, C = i + P[i], i
    # print(T)
    # print(P)
    result = sum([p//2 for p in P if p>=2]) 
    return result if result<=100000000 else -1

image.png

Challenge - Delta 2011 - MinAbsSum

本题也是Lessons中出现过的题目,是Lessons17 - Dynamic Programming这一章节的,之前在这篇文章中也讲过解题思路,就不再赘述了:juejin.cn/post/722303…