Aprendizaje de Python versión-LeetCode: 76. Subcadena de cobertura mínima

Darle una cadena S y una cadena T. Busque en la cadena S: la subcadena más pequeña que contiene todos los caracteres de T.

Ejemplo: Entrada: S = "ADOBECODEBANC", T = "ABC"
Salida: "BANC"
Nota: Si no existe tal subcadena en S, se devolverá una cadena vacía "".
Si existe una subcadena de este tipo en S, garantizamos que es la única respuesta.

Fuente: LeetCode
Enlace: https://leetcode-cn.com/problems/minimum-window-substring

Método 1: este método utiliza principalmente la idea de la ventana deslizante y su significado general:

Utilice izquierda, derecha para representar los límites izquierdo y derecho de la ventana deslizante. Al cambiar i, j para expandir y contraer la ventana deslizante, puede imaginar una ventana subiendo por la cadena. Cuando los elementos contenidos en esta ventana cumplen las condiciones, contiene caracteres Todos los elementos de la cuerda T, registran la longitud de la ventana deslizante derecha-izquierda +1, el mínimo de estas longitudes es el resultado requerido

El proceso de implementación específico es el siguiente:

(1) Calcule el número de cada carácter en el valor objetivo t como la lista de necesidades de requisitos de caracteres, es decir, se requieren k * v caracteres necesarios;

         Uso: cuando se recupera un carácter en la ventana deslizante , el valor de carácter correspondiente que se necesita se compensa, es decir, necesita [char] -1; cuando no se encuentra un carácter en la función de ventana , se incrementa el carácter correspondiente que se necesita Valor, es decir, necesita [char] +1;

(2) Registre la longitud del valor objetivo t, needCnt, es decir, el número total de cadenas necesarias y needCnt es igual a la suma del valor necesario.

         Uso: en lugar de atravesar la necesidad, juzgue si la ventana deslizante contiene todos los caracteres en t por el número total

(3) Siga aumentando el puntero para aumentar rightla ventana deslizante hasta que la ventana contenga todos los elementos de T: cuando la ventana contiene todos los caracteres necesarios (es decir, needCnt = 0), significa que los caracteres innecesarios incluidos en la ventana pueden eliminarse. Puede encoger la ventana

(4) Siga aumentando a la izquierda para encoger la ventana deslizante . Debido a que se requiere la cadena mínima , los elementos innecesarios se excluyen y la longitud se reduce hasta que se encuentra un elemento que debe incluirse (de hecho, la subcadena que debe incluirse en la lista no debe ser menor que 0. Cuando = 0, significa La demanda se acaba de cumplir) , esta vez no se puede tirar. Lanzar de nuevo no cumple las condiciones. Registre los valores de izquierda y derecha de la ventana deslizante en este momento, derecha-izquierda +1, que es la longitud de la subcadena mínima. Y guarda el valor mínimo.

(5) Cuando la derecha agrega otra posición y la ventana deslizante no cumple la condición, esto significa moverse hacia la izquierda, lo que significa que la ventana deslizante aumenta hasta que la ventana contiene todos los caracteres necesarios (es decir, needCnt = 0). En este momento, desde el paso (3), busque una nueva ventana deslizante que satisfaga las condiciones y repita hasta que la izquierda exceda el rango de la cuerda S.

class Solution:
    def minWindow(self, s: str, t: str) -> str:
        # 目标字符记录
        need=collections.defaultdict(int)
        for c in t:
            need[c]+=1
        # 目标字符长度
        needCnt=len(t)
        left=0
        res=(0,float('inf'))
        for r,c in enumerate(s):
            if need[c]>0:
                # 如果need[c]>0,意味着窗口搜索到目标值
                needCnt-=1
            # 目标值被搜索到,则need相应value-1,即用以记录搜索到need中字符的个数;
            # =0代表搜索到的值和need值相同;<0代表need中同一个字符被多次搜索到;
            # >0,代表need中该字符没有全部被遍历出来
            need[c]-=1   
            
            if needCnt==0: # 滑动窗口包含了所有T元素  
                # 开始窗口函数内部的搜索
                while True:  # 移动滑动窗口右边界i,排除多余元素
                    c=s[left] 
                    if need[c]==0:  
                        # need[c]==0,break 情况,代表着这轮的滑动窗口不符合要求
                        break
                    # 窗口中字符和need相互抵消
                    need[c]+=1
                    r+=1
                if r-left <res[1]-res[0]:   #记录结果
                    res=(left,r)
                # 窗口函数内部计算完后,向下一步迭代
                # s[left]是目标集中t的字符,这时从窗口函数清除,
                # 则意味着窗口函数需要新的字符填充,即need[s[left]]和needCnt需要加一
                need[s[left]]+=1  # left增加一个位置,寻找新的满足条件滑动窗口
                needCnt+=1
                # 新一轮的右边界
                r+=1
        return '' if res[1]>len(s) else s[res[0]:res[1]+1]    #如果res始终没被更新过,代表无满足条件的结果

Resumen: Este tipo de tema utiliza principalmente los punteros izquierdo y derecho para hacer un bucle para formar una ventana deslizante y comparar el valor objetivo t con la ventana deslizante. La principal dificultad es cómo comparar la ventana deslizante con el valor objetivo. Usamos la forma del libro de contabilidad para registrar los caracteres requeridos como una necesidad de conjunto de caracteres enteros, y restamos 1 cada vez que se alcanza un valor objetivo. En este proceso, también registramos cada carácter en la ventana deslizante, estos caracteres no deseados Todos se registran como valores negativos. Cuando se eliminan de la ventana deslizante, estos caracteres se registran como 0. Los caracteres que se agregan a la necesidad de la ventana deslizante, el valor del carácter que no es el valor objetivo nunca será positivo.

Cuando todos los valores de caracteres necesarios son menores o iguales a 0, la demanda se satisface. La función de mantener una variable adicional needCnt es registrar el número total de elementos requeridos. Cuando encontramos un elemento requerido c, no solo el número de need [c] se reduce en 1, sino que también needCnt se reduce en 1, por lo que pasamos needCnt puede saber si se cumplen las condiciones, por lo que no es necesario recorrer el diccionario de necesidad.
Como se mencionó anteriormente, need registra todos los elementos atravesados, el valor de char que no es el valor objetivo nunca será positivo, y solo cuando need [c]> 0, significa que c es el elemento requerido, cuando todos los elementos necesitados Cuando el valor de char es 0, significa que se satisfacen todos los valores objetivo y no hay caracteres adicionales en la ventana deslizante.
Enlace: https://leetcode-cn.com/problems/minimum-window-substring/solution/tong-su-qie-xiang-xi-de-miao-shu-hua-dong-chuang-k/

Otra referencia:

class Solution:
    def minWindow(self, s: str, t: str) -> str:
        need = collections.defaultdict(int)
        for c in t:
            need[c] += 1
        needCnt = len(t)
        i = 0 #记录起始位置
        res = (0, float('inf'))  #用两个元素,方便之后记录起终点
        #三步骤:
        #1. 增加右边界使滑窗包含t
        for j,c in enumerate(s):
            if need[c] >0:
                needCnt -= 1
            need[c] -= 1 #这行放在外面不可以,看19行 need[c] == 0
        #2. 收缩左边界直到无法再去掉元素   !注意,处理的是i
            if needCnt == 0:
                while True:
                    c = s[i]
                    if need[c] == 0: #表示再去掉就不行了(need>0)
                        break
                    else:
                        need[c] += 1
                        i += 1
                if j-i < res[1] - res[0]:  #这里是否减一都可以,只要每次都是这样算的就行,反正最后也是输出子串而非长度
                    res = (i,j)
        #3. i多增加一个位置,准备开始下一次循环(注意这步是在 needCnt == 0里面进行的 )
                need[s[i]] += 1
                needCnt += 1    #由于 移动前i这个位置 一定是所需的字母,因此NeedCnt才需要+1
                i += 1
        return "" if res[1]>len(s) else s[res[0]: res[1]+1]

 

Supongo que te gusta

Origin blog.csdn.net/guyu1003/article/details/107407641
Recomendado
Clasificación