题目
对一个字符串中重复出现三次以上的字符进行消除。
如'AAAABCCBBBA' - > 'BCCA'
,'abbbcccbba'->'abba'
解答
解法一:两个栈
一个栈放字符,一个栈放以当前字符结尾的最长连续串的长度,然后遍历字符串,
如果当前字符跟字符栈的栈顶元素不同
,那么你就检查长度栈的最后一个元素 看最长长度是否超过3,如果超过就把字符栈中的字符给消去,同时把长度栈的相应的东西也删去嘛
但是如果当前字符跟字符栈的栈顶元素相同
,就把当前字符压栈 同时在长度栈里面也加入一个新的长度 即栈顶长度加1
这样遍历完字符串 字符栈中剩余的字符就是要求的结果了。
然后因为是通过用当前元素与前一个元素比较的方式来判断,所以当最后字符栈中为[‘A’,‘A’,‘A’]时,由于没有后一个元素,所以会直接输出。解决方法就是在后面增加一个字符,然后在输出的时候再删除这个字符。
s = 'ABBBAA'
s = s + ' '
stack_1 = [s[0]] # 字符栈
stack_2 = [1] # 长度栈
for i in s[1:]:
item = stack_2[-1]
if i != stack_1[-1]:
if item >= 3:
stack_1 = stack_1[:-item]
stack_2 = stack_2[:-item]
if stack_1 and stack_1[-1] == i: # 这里是为了解决CCBBBC的情况
stack_1.append(i)
stack_2.append(stack_2[-1] + 1)
continue
stack_1.append(i)
stack_2.append(1)
else:
stack_1.append(i)
stack_2.append(item + 1)
ans = ''.join(stack_1)
print('ans:', ans.strip())
解法二:双指针
用一个左指针和一个右指针,遍历字符串,先固定左指针,
当右指针指向的值等于左指针的值时,就继续移动右指针,然后判断右指针与左指针之间的长度是否大于等于3,如果是的话,就删除掉s中的这一段,并且左指针回退2位,如果否,就移动左指针;
def elimination(s):
l = 0
while l < len(s):
r = l # 把右指针更新为当前位置
while r < len(s) and s[r] == s[l]:
r += 1
if r - l >= 3: # 如果找到三个以上重复的元素
s = s[:l] + s[r:] # 在s中删除
l -= 2 # l回退2个位置,比如CCDDD, 回退两个位置能使l指向第一个C
if l < 0:
l = 0
else:
l = r
# l += 1 # 这里也可以是l+=1,但是会存在一定的重复运算 比如CCB,l先指向第一个C,然后又要指向第二个C,但r-l都不满足>=3
return s
s = 'AAAABBBCCCBBCA'
ans = elimination(s)
print(ans)