子串的数量,其字谜是回文

时间:2017-12-04 08:43:52

标签: python algorithm

给定一串数字,计算任何回文字符的子字数(一致子序列)。

我在Python中的尝试:

def ispalin(s):
    if len(s)%2==0:
        for i in s:
            if s.count(i)%2!=0:
                return False
    else:
        sum =0
        for i in set(s):
            if s.count(i)%2==1:
                sum = sum+1
        if sum == 1:
            return True
        else:
            return False

    return True

def solution(S):
    # write your code in Python 3.6
    count=len(S)
    for i in range(len(S)):
        for j in range(i+1,len(S)):
            if ispalin(S[i:j+1]):
                count=count+1

    return count

i / o格式

For example, given:

    S = "02002"
the function should return 11. 
these are 11 substrings whose anagrams are palindrome
"0", "2", "0", "0", "2", "00", "020", "200", "002", "2002", "02002"

大字符串超出时限。如何优化上述代码?

我敢打赌,存在一种比这更好的解决方案,这就是证据 [图像] [1]

https://i.stack.imgur.com/7x3Jq.png

2 个答案:

答案 0 :(得分:1)

这个问题有一个O(n)解决方案。首先要注意的是,子串是任何回文的字谜,如果它的数字包括偶数或最多只有一个奇数存在。例如“20020”是plaindrome的字谜,因为'2'的数字是偶数,'0'的数字是奇数(最多一个奇数),而“200202”不合适。

所以我们唯一需要保留的是数字位数的奇偶校验,而不是它们的总和。我们可以使用10位数来显示所有数字的奇偶校验。每次我们访问字符串中的数字时从0开始,我们可以用(2 ^位)x来表示奇偶校验数。按照“02002”的示例,这里是通过以二进制格式迭代字符串生成的奇偶校验数:

parity_array = {0000000000, 0000000001, 0000000101, 0000000100, 0000000101 0000000001}

现在我们需要计算线性时间内字谜的数量。迭代于parity_array,我们使用另一个大小为1024的数组(让我们称之为memo)来保持我们访问parity_array中特定数字的次数。正如我之前提到的,子串是可以的,当且仅当它们的二进制奇偶校验表示中的1位数最多为1.因此对于parity_array的每个成员,我们需要检查并在备注中添加11个元素,其中xor与当前的parity_array值相等to:{0或1或2或4或8 ...或1024}并总结结果。 总复杂度为O(n)。

修改 我为上面解释的内容添加了C ++代码。如果你愿意,我也可以添加python代码:

string sample = "02002";
int parity = 0;
vector<int> parity_array;
parity_array.push_back(parity);
for(int i=0; i<sample.size(); ++i){
    parity ^= 1<<(sample[i]-'0');
    parity_array.push_back(parity);
}
int memo[1025] = {0};
int res=0;
for(int i=0;i<parity_array.size();++i){
    for(int j=-1;j<10;++j)
        res += memo[(1<<j)^parity_array[i]];
    memo[parity_array[i]]++;
}
cout<<res<<endl;

答案 1 :(得分:0)

使用O(n)内存可以获得二次复杂度。

制作数字计数器[0..9](或使用另一种方便Python的数据结构)

遍历字符串,递增当前数字的计数器,并将修改后的数组添加到列表中。之后该列表将包含“累积总和” - 每个数字的计数直到每个索引(例如,在第40个字符串输入之前的5个2)

现在要计算第i个和第j个条目之间的数字,只需减去C[j][digit] - C[i][digit]

有趣的问题 - 是否存在更好的复杂性解决方案?