给定一串数字,计算任何回文字符的子字数(一致子序列)。
我在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]
答案 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]
有趣的问题 - 是否存在更好的复杂性解决方案?