菜鸡的算法之旅(0)

36 阅读3分钟

今天是第一次写文章,在编程,算法方面我确实算个菜鸡,毕竟大学才开始接触编程,也不是计算机科班出身,作为一个初学者也只能分享一下自己的成长经历吧哈哈

今天决定午饭后到晚饭前刷题,晚饭后散个步再去学习AI课程。哎感觉时间好不够用,早上的时间也应该抽出来学习的,希望能完成字节的项目吧。

到目前为止今天才写出来一道题,好慢。下面看题吧:

最小替换子串长度

问题描述

小F得到了一个特殊的字符串,这个字符串只包含字符ASDF,其长度总是4的倍数。他的任务是通过尽可能少的替换,使得ASDF这四个字符在字符串中出现的频次相等。求出实现这一条件的最小子串长度。

思路解析

这个题我一打眼还以为是最小替换字符次数,还觉得有点太简单了。但其实要求的是最小替换字串的长度,就是说我们需要修改该串的某个子串,让四个字符出现次数相同,求可能的最小子串。 我的解题思路比较暴力,具体而言分为两个步骤:

1.记录每个字符出现的次数,由此求出需要修改的字符数量。最终目标是让每个字符出现len(s)//4次,所以我们只需要关注出现次数大于这个数的字符(下文称他们为 多余字符 )就行。在数据结构方面,我选择了字典。因为多余字符的数量不确定,有可能是1,2,3个,所以使用字典比较方便。

2.知道了多余字符以及他们多余的数量,例如多了3个'A',2个'F',我们的目标就相当于找到字符串的包含 3个'A',2个'F' 的最小子串。这里我的思路是滑动窗口(或者说双指针)。具体而言:

-   初始化两个指针 `ll` 和 `rr`,均指向字符串的起始位置。
-   不断增加 `rr`,扩展窗口的右边界,直到窗口内包含足够的多余字符。
-   一旦窗口内包含了所需的多余字符,我们开始尝试增大 `ll`,即收缩窗口的左边界,以尽量缩小窗口的大小,直到不能再缩小为止。
-   记录当前窗口的长度,作为可能的最小字串长度。
-   将 `ll` 向右移动一位,继续上述步骤,直到遍历完整个字符串。
-   最后,返回记录的最小窗口长度。

通过这种方法,我们可以高效地找到包含所需多余字符的最小子串,从而确定需要修改的最短子串长度

最后,贴上我的代码,语言为Python:

def ge(dic1:dict,dic2:dict):
# 这个函数用于比较dic1中的每个键值都大于等于dic2
    try:
        for key in dic1:
            if dic1[key]>=dic2[key]:
                continue
            break
        else:
            return True
        return False
    except KeyError:
        return False

def solution(input):
    # 统计每个字符的出现次数
    ca = cs = cd = cf = 0
    for i in input:
        if i == 'A':
            ca += 1
        elif i == 'S':
            cs += 1
        elif i == 'D':
            cd += 1
        else:
            cf += 1

    # 如果所有字符出现次数已经相等,直接返回0
    if ca == cs == cd == cf:
        return 0

    n = len(input)
    st = n // 4
    need = {'A': max(0, ca - st), 'S': max(0, cs - st), 'D': max(0, cd - st), 'F': max(0, cf - st)} # need为字串实际需要的字符以及数量
    conter = {item:0 for item in need if need[item] > 0}  # 记录窗口内目前有的字符数量
    ll = rr = 0 # 窗口边界
    ans = float('inf')

    while rr < n:
        # 扩大窗口
        for key in conter:
            if input[rr]==key:
                conter[key] += 1


        # 检查是否满足条件
        while ge(conter,need):
            # 更新答案
            ans = min(ans, rr - ll + 1)
            # 收缩窗口
            if input[ll] in conter:
                conter[input[ll]]-=1
            ll+=1

        rr += 1

    return ans if ans != float('inf') else 0


if __name__ == "__main__":
    print( solution("ADDF") == 1 )
    print( solution("ASAFASAFADDD") == 3 )