Cómo optimizar principiante código HackerEarth

HackerMan :

He estado tratando de hacer este problema HackerEarth pero los últimos casos de prueba siempre parece que el tiempo de espera

Planteamiento del problema: https://www.hackerearth.com/practice/algorithms/searching/linear-search/practice-problems/algorithm/joker-and-thieves-53e59f4a/

Soy un estudiante de primer año, por lo que no se sabe muy bien cómo optimizar así que

Traté de mirar la solución de Java, pero sólo hay que poner los casos más grandes en el código, eliminando de forma eficaz la necesidad de optimizarlo

import java.io.*;
import java.util.*;
public class police {
    static int t,n,k;
    static char[][] test;
    static int max = 0;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        t = Integer.parseInt(st.nextToken());


        for (int i = 0; i < t; i++) {
           st = new StringTokenizer(br.readLine());
            n = Integer.parseInt(st.nextToken());
            k = Integer.parseInt(st.nextToken());
            test = new char[n][n];


            int ret = 0;

            for (int b = 0; b < n; b++) {
                st = new StringTokenizer(br.readLine());
                for (int a = 0; a < n; a++) {
                    test[b][a] = st.nextToken().charAt(0);
                }
            }

            for (int b = 0; b < n; b++) {
                ret += solve(test[b]); //calculate each row
            }

            System.out.println(ret);


        }    


    }
    static int solve(char[] a) { //given a row, calculate the maximum number of catches
        int ret = 0;
        for (int i = 0; i < n; i++) {
            if (a[i] == 'P') {

                for (int b = i - k; b <= i + k; b++) { //scan area to see if police can catch a thief
                    if (b >= 0 && b < n && a[b] == 'T') {
                        a[b] = 'C'; //caught
                        break;
                    }
                }

                a[i] = 'U'; //used
            }

        }
        for (int i = 0; i < n; i++) //count
            if (a[i] == 'C')
                ret++;

        return ret;
    }
}

Estoy bastante seguro de que tiene algo que ver con el método de resolver, si alguien me podría ayudar a que sería increíble

Mis94:

Tiene usted razón, el enfoque que está utilizando en su solvemétodo es la causa del tiempo de espera.

En primer lugar es necesario tener una idea acerca de complejidad del algoritmo y la notación O grande

Las restricciones del problema son:

1 <= N <= 1000

1 <= K <= N * N

éstos indican que la complejidad de su solución debe ser como máximo O(N * N). En otras palabras a lo más dos anidados para bucles cada uno con una complejidad O (N).

Y en su solución que está haciendo lo siguiente:

for (int b = 0; b < n; b++) {
    ret += solve(test[b]); //calculate each row
}

OK, este bucle es esencial, ya que tiene que iterar sobre todas las filas de la cuadrícula. Complejidad:O(N)

Luego, en el método de resolver:

for (int i = 0; i < n; i++) {
    if (a[i] == 'P') {

        for (int b = i - k; b <= i + k; b++) { //scan area to see if police can catch a thief
            if (b >= 0 && b < n && a[b] == 'T') {
                a[b] = 'C'; //caught
                break;
            }
        }

        a[i] = 'U'; //used
    }

}

Estos bucles for anidados son la causa real del problema, la complejidad del bucle exterior es O(N)ya la complejidad bucle interno podría ser también O(N)un alto valor de K. Por lo tanto la complejidad total de los tres bucles podría llegar a O(N * N * N)lo que sin duda tiempo de espera.

Aquí está mi solución a este problema, lo único que he modificado el solvemétodo:

static int solve(char[] a) { //given a row, calculate the maximum number of catches
        int ret = 0;
        ArrayDeque<Integer> policeMenQueue = new ArrayDeque<>(); // queue for holding positions of policemen
        ArrayDeque<Integer> thievesQueue = new ArrayDeque<>(); // queue for positions of thieves
        for (int i = 0; i < n; i++) {
            if(!policeMenQueue.isEmpty()) { // check if the leftmost policeman can catch a thief at current position (i)
                Integer mostLeftPoliceMan = policeMenQueue.getFirst();
                if(i - mostLeftPoliceMan > k) { // if he cannot then we must remove him as he will no longer be able to catch any thieves
                    policeMenQueue.removeFirst();
                }
            }
            if(!thievesQueue.isEmpty()) { // check if the leftmost thief can be caught be a policeman at current position (i)
                Integer mostLeftThief = thievesQueue.getFirst();
                if(i - mostLeftThief > k) { // if not then we must remove him as he will no longer be caught by any policemen
                    thievesQueue.removeFirst();
                }
            }
            if(a[i] == 'P') {
                if(!thievesQueue.isEmpty()) { // the leftmost thief can be caught by current policeman
                    ret++;
                    thievesQueue.removeFirst(); // ok this thief is caught, remove him
                } else {
                    policeMenQueue.addLast(i); // just add the policeman to keep his position in the queue
                }
            }
            if(a[i] == 'T') {
                if(!policeMenQueue.isEmpty()) { // the current thief can be caught by the leftmost policeman
                    ret++;
                    policeMenQueue.removeFirst(); // ok this policeman has already caught a thief (used), remove him
                } else {
                    thievesQueue.addLast(i); // just add the thief to keep his position in the queue
                }
            }
        }
        return ret;
    }

Mi idea: bucle en cada fila, de izquierda a derecha y como afirma el problema: cada policía puede coger sólo un ladrón y queremos maximizar el número de ladrones atrapados, por lo que está a nuestro favor que cada ladrón es capturado por el policía más a la izquierda (ya que estamos yendo de izquierda a derecha).

Por ejemplo, consideremos esta fila:

P P T T

e imaginar que K = 2

Es nuestro favor ese ladrón en la posición 3ser capturado por el policía en la posición 1que este policía no puede atrapar al ladrón de la posición 4y por supuesto la policía en la posición 2pueden tomar dos ladrones en este caso, pero recuerda que tenemos que maximizar el número de ladrones capturados y cada policía puede coger sólo un ladrón, por lo que queremos que cada ladrón de ser atrapado por la policía más a la izquierda que lo pueda coger.

Mi solución depende de la queueestructura de datos ( ArrayDequeen Java), si usted no sabe cómo funciona o por qué lo estoy usando echar un vistazo aquí: https://www.tutorialspoint.com/data_structures_algorithms/dsa_queue.htm

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=211809&siteId=1
Recomendado
Clasificación