宝石手串——字符的最小距离

描述

小红有一个 nn 颗宝石构成的环形宝石手串,即第一颗和最后一颗宝石相连,其中第 i个宝石的属性为 si​ ;若两个宝石的属性相同,那么这两个宝石会相互排斥,导致断开。
小红可以从手串中摘掉一些宝石,每次摘掉后,这个宝石左右的两个宝石会相接,手串依旧是环形。

小红想要破坏这个手串。她想要知道,最少还需要摘掉多少个宝石才会导致手串断开。特别的,当手串上剩余的宝石数量恰好为 2 而依旧没能

输入描述:

每个测试文件均包含多组测试数据。第一行输入一个整数 T(1≦T≦100)代表数据组数,每组测试数据描述如下:

第一行输入一个整数 n(2≦n≦105)代表手串初始的宝石数量。

第二行输入一个长度为 n 、仅由小写字母构成的字符串,代表手串上每个宝石的属性。

除此之外,保证单个测试文件的 n 之和不超过 105 。

断开时,视为破坏失败,直接输出 −1 。

输出描述:

对于每一组测试数据,如果手环无法破坏,直接输出 −1 ;否则,在一行上输出一个整数,代表手串断开需要的最少操作次数。 

解答

#本质在于删除字符,使得相同字符之间的距离尽可能小

def main():

    T = int(input())#测试组数

    for _ in range(T):#遍历每个测试用例

        n = int(input())#手串初始的宝石数量

        s = input().strip()#手串上每个宝石的属性

        len_s = len(s)

        vet = [[] for _ in range(26)]#给每个字母创建一个数组存储其下标位置

        #遍历字符串的每个属性,将其下标存入数组

        for i in range(len_s):

            vet[ord(s[i])-ord('a')].append(i)

            #初始化最小操作数

        ans = 99999

            #遍历每个字母

        for j in range(26):

                #如果出现的次数是0或1,跳过

            if len(vet[j])==0 or len(vet[j])==1:

                continue

            l = vet[j][0]#字母在字符最左边出现的位置

            r = vet[j][-1]#字母在字符最右边出现的位置

            ans = min(ans,r-l-1)#去除中间所有字符的最小操作次数

            ans = min(ans,len_s-(r-l+1))#去除两端所有字符的最小操作次数

            #进一步遍历看是否还有更近的距离

            for k in range(1,len(vet[j])):

                l = vet[j][k-1]

                r = vet[j][k]

                ans = min(ans,r-l-1)

        if ans == 99999:

            print(-1)

        else:

            print(ans)

main()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值