LeetCode Notes: Weekly Contest 215 Contest Record

0. Resumen después del partido

Esta vez, el ranking de la competencia sigue siendo razonable. El 327 nacional, el 830 mundial, finalmente están en el 10% superior, pero el proceso es realmente eh, 4 veces incorrecto, 3 de los cuales son errores extremadamente estúpidos, y finalmente yo se rindió media hora antes, y la última pregunta realmente no tenía ninguna idea, por lo que la sensación general fue extremadamente mala.

Oye, ¿cuándo recibiré las 4 preguntas de manera constante? . .

Vamos muchacho.

1. Tema uno

El enlace a la pregunta dada para la pregunta uno es el siguiente:

1. Ideas para resolver problemas

En esencia, la dificultad de esta pregunta radica en la lectura de la pregunta, una vez que la comprende, puede resolverla directamente. . .

De hecho, en esencia, esta pregunta es dar una secuencia fuera de orden, y luego dar un puntero de posición inicial ptr de 1, y luego completar la secuencia fuera de orden una por una, cuando el elemento relleno ocurre para ser el elemento al que apunta la posición de ptr Cuando, mueva ptr hacia atrás a la siguiente posición que no se haya llenado en el elemento y devuelva estos valores.

2. Implementación del código

La implementación del código de Python es la siguiente:

class OrderedStream:

    def __init__(self, n: int):
        self.val = ["" for _ in range(n+1)]
        self.flag = 1
        self.n = n


    def insert(self, id: int, value: str) -> List[str]:
        self.val[id] = value
        res = []
        if id == self.flag:
            while self.flag <= self.n and self.val[self.flag] != "":
                res.append(self.val[self.flag])
                self.flag += 1
        return res

Después de enviar la evaluación del código, tomó 220 ms y ocupó 14,7 MB de memoria.

La implementación del código óptimo actual toma 216ms, y su implementación es ligeramente diferente a la nuestra, nosotros guardamos los elementos, usamos una lista para almacenar los elementos y ellos usan directamente un elemento de almacenamiento.

Sin embargo, en esencia, no hay mucha diferencia, así que no haré más.

2. Tema 2

El enlace a las preguntas del examen para el tema dos es el siguiente:

1. Ideas para resolver problemas

La esencia de esta pregunta radica en el análisis de la pregunta. Aunque revoqué esta pregunta descuidadamente, después de analizar las condiciones de la pregunta, la pregunta es en realidad muy simple:

  1. Dado que las posiciones de los dos elementos se pueden intercambiar en cualquier momento, la secuencia es independiente del orden;
  2. Dado que dos tipos de elementos cualesquiera se pueden intercambiar como un todo, la secuencia es independiente de los tipos de letras.

Por lo tanto, siempre que se cumplan las dos condiciones siguientes, las dos cadenas (indicadas como s1 y s2) están cerca:

  1. Dos cadenas tienen el mismo tipo de letras, es decir, si una letra aparece en s1, debe aparecer en s2 y viceversa;
  2. El conjunto numérico de cada letra en s1 es exactamente el mismo que el conjunto numérico de letras en s2, es decir, si hay tres tipos de caracteres en s1 y los números son respectivamente [a,b,c], entonces el número de tres caracteres en s2 debe ser lo mismo [a,b,c].

2. Implementación del código

El código de Python se proporciona de la siguiente manera:

class Solution:
    def closeStrings(self, word1: str, word2: str) -> bool:
        s1 = Counter(word1)
        s2 = Counter(word2)
        return sorted(s1.keys()) == sorted(s2.keys()) and sorted(s1.values()) == sorted(s2.values())

Después de enviar la evaluación del código, tomó 128 ms y ocupó 14,6 MB de memoria. Pertenece a la implementación óptima del código actual.

3. Tema tres

El enlace a las preguntas de la prueba para el tema tres es el siguiente:

1. Ideas para resolver problemas

Después de obtener el título de esta pregunta, mi primer pensamiento fue usar un algoritmo dp para resolverlo violentamente, y luego se agotó el tiempo. . .

Más tarde, consideré cuidadosamente este tema. Se siente similar al algoritmo de búsqueda bidireccional, porque los elementos son mayores que 0. Por lo tanto, primero damos que todos los elementos provienen del lado derecho para llegar a x, y luego vemos cuántos elementos son necesarios, y luego cada vez que se agrega un elemento a la izquierda, y luego se elimina el elemento de la derecha para que alcance x nuevamente.

Repite el proceso anterior hasta que todos los elementos sean de la izquierda.

2. Implementación del código

El código de Python se proporciona de la siguiente manera:

class Solution:
    def minOperations(self, nums: List[int], x: int) -> int:
        tot = sum(nums)
        if tot < x:
            return -1
        elif tot == x:
            return len(nums)
        
        n = len(nums)
        l, r = 0, n-1
        s = 0
        used = 0
        while s < x:
            s += nums[r]
            r -= 1
            used += 1
        res = -1 if s != x else used
        while r < n-1 and l <= r :
            used -= 1
            r += 1
            s -= nums[r]
            while s < x and l <= r:
                s += nums[l]
                l += 1
                used += 1
            if s == x:
                res = used if res == -1 else min(res, used)
        return res

Después de enviar el código para su evaluación, tomó 1164 ms y ocupó 28,9 MB de memoria.

La implementación del código óptimo actual toma 652ms. Mirando su algoritmo, no es muy diferente del nuestro en esencia, pero usa un diccionario para guardar la suma anterior, optimizando así la eficiencia.

Los lectores interesados ​​pueden echarle un vistazo por sí mismos, no voy a profundizar mucho aquí.

4. Tema cuatro

El enlace a la pregunta de la prueba para la pregunta cuatro es el siguiente:

1. Ideas para resolver problemas

No tenemos ideas para esta pregunta en la competencia. Después de la competencia, refiriéndose a la solución del jefe de awice, se da una idea de planificación dinámica de la siguiente manera:

  • Cada vez que llene una fila, verifique el cambio de puntuación después de cada llenado legal y sepa que todas las filas están llenas.

2. Implementación del código

El código de Python se proporciona de la siguiente manera:

class Solution:
    def getMaxGridHappiness(self, m: int, n: int, introvertsCount: int, extrovertsCount: int) -> int:        
        @lru_cache(None)
        def dp(r, intro, extro, prev):
            if r >= m:
                return 0
            ans = 0
            for row in itertools.product(range(3), repeat=n):
                _intro = row.count(1)
                _extro = row.count(2)
                if _intro > intro or _extro > extro:
                    continue
                score = 0
                for i in range(n):
                    if row[i] == 0:
                        continue
                    elif row[i] == 1:
                        score += 120
                        if i-1 >= 0 and row[i-1] != 0:
                            score -= 30
                        if i+1 < n and row[i+1] != 0:
                            score -= 30
                        if prev[i] == 1:
                            score -= 60
                        elif prev[i] == 2:
                            score -= 10
                    else:
                        score += 40
                        if i-1 >= 0 and row[i-1] != 0:
                            score += 20
                        if i+1 < n and row[i+1] != 0:
                            score += 20
                        if prev[i] == 1:
                            score -= 10
                        elif prev[i] == 2:
                            score += 40
                score += dp(r+1, intro - _intro, extro - _extro, tuple(row))
                ans = max(ans, score)
            return ans

        return dp(0, introvertsCount, extrovertsCount, tuple([0] * n))

Sin embargo, el código anterior tiene un problema de tiempo de espera. Por lo tanto, tenemos que agregar con fuerza dos tratamientos especiales para situaciones complejas exactamente en la forma del jefe de awice, para que no se agote:

  1. El número de columnas es menor que el número de filas y hay menos consideraciones para cada fila en este momento;
  2. En el caso de 5 * 5, todo el mundo puede ser colocado sin conflicto, por lo que puede tratarse directamente desde el exterior;

Por lo tanto, el código revisado obtiene:

class Solution:
    def getMaxGridHappiness(self, m: int, n: int, introvertsCount: int, extrovertsCount: int) -> int:
        if m < n:
            return self.getMaxGridHappiness(n, m, introvertsCount, extrovertsCount)
        
        if n >= 5:
            bonus = {
    
    0:0, 1:0, 2:40, 3:80, 4:160, 5:200, 6:280}
            return 120 * introvertsCount + 40 * extrovertsCount + bonus[extrovertsCount]
        
        @lru_cache(None)
        def dp(r, intro, extro, prev):
            if r >= m:
                return 0
            ans = 0
            for row in itertools.product(range(3), repeat=n):
                _intro = row.count(1)
                _extro = row.count(2)
                if _intro > intro or _extro > extro:
                    continue
                score = 0
                for i in range(n):
                    if row[i] == 0:
                        continue
                    elif row[i] == 1:
                        score += 120
                        if i-1 >= 0 and row[i-1] != 0:
                            score -= 30
                        if i+1 < n and row[i+1] != 0:
                            score -= 30
                        if prev[i] == 1:
                            score -= 60
                        elif prev[i] == 2:
                            score -= 10
                    else:
                        score += 40
                        if i-1 >= 0 and row[i-1] != 0:
                            score += 20
                        if i+1 < n and row[i+1] != 0:
                            score += 20
                        if prev[i] == 1:
                            score -= 10
                        elif prev[i] == 2:
                            score += 40
                score += dp(r+1, intro - _intro, extro - _extro, tuple(row))
                ans = max(ans, score)
            return ans

        return dp(0, introvertsCount, extrovertsCount, tuple([0] * n))

Envíe el código para su evaluación y obtenga: Toma 4524 ms y ocupa 24,3 MB de memoria.

La implementación del código óptimo actual toma solo 604 ms, por lo que el código debe optimizarse aún más.

4. Optimización de algoritmos

La parte más engorrosa del código anterior es que todos los arreglos posibles se examinan para cada fila, pero de hecho, debido a las limitaciones de introCounts y extroCounts, solo una pequeña parte de ellos será legal, por lo que habrá mucha redundancia de cálculo. generado.

Mirando la solución óptima actual, adoptó directamente el método de cálculo dfs para implementar el código, es decir, considerando el posible llenado de cada punto.

Sin embargo, hay dos puntos a tener en cuenta aquí:

  1. Cuando todas las personas restantes obtienen el puntaje más alto y no pueden alcanzar el puntaje más alto en la historia, el proceso dfs puede terminarse directamente;
  2. Cada punto debe usarse tanto como sea posible, es decir, solo cuando al menos uno de los puntos anteriores y el punto anterior del punto actual no estén vacíos se puede dejar el punto actual en blanco, de lo contrario, se debe completar una persona.

A continuación, lo imitamos y le damos nuestra propia implementación de código.

class Solution:
    def getMaxGridHappiness(self, m: int, n: int, introvertsCount: int, extrovertsCount: int) -> int:
        grid = [[0 for _ in range(n)] for _ in range(m)]
        score = 0
        
        def get_score(r, c):
            nonlocal grid
            if grid[r][c] == 1:
                score = 120
                if r-1 >= 0:
                    if grid[r-1][c] == 1:
                        score -= 60
                    elif grid[r-1][c] == 2:
                        score -= 10
                if c-1 >= 0:
                    if grid[r][c-1] == 1:
                        score -= 60
                    elif grid[r][c-1] == 2:
                        score -= 10
            else:
                score = 40
                if r-1 >= 0:
                    if grid[r-1][c] == 1:
                        score -= 10
                    elif grid[r-1][c] == 2:
                        score += 40
                if c-1 >= 0:
                    if grid[r][c-1] == 1:
                        score -= 10
                    elif grid[r][c-1] == 2:
                        score += 40
            return score
        
        def dfs(r, c, intro, extro, _score):
            nonlocal grid, score
            if c >= n:
                dfs(r+1, 0, intro, extro, _score)
                return
            if r >= m or (intro == 0 and extro == 0):
                score = max(_score, score)
                return
            if _score + 120 * (intro + extro) < score:
                return
            if intro > 0:
                grid[r][c] = 1
                dfs(r, c+1, intro-1, extro, _score + get_score(r,c))
                grid[r][c] = 0
            if extro > 0:
                grid[r][c] = 2
                dfs(r, c+1, intro, extro-1, _score + get_score(r,c))
                grid[r][c] = 0
            if (r > 0 and grid[r-1][c] != 0) or (c > 0 and grid[r][c-1] != 0):
                dfs(r, c+1, intro, extro, _score)
            return
        
        dfs(0, 0, introvertsCount, extrovertsCount, 0)
        return score

Después de enviar la evaluación del código, tomó 916 ms y ocupó 14,2 MB de memoria.

Supongo que te gusta

Origin blog.csdn.net/codename_cys/article/details/109828853
Recomendado
Clasificación