LeetCode06, el análisis más sólido de la transformación en zigzag

Descripción del Título

Inserte la descripción de la imagen aquí

1.1, pensamiento directo

Viendo el tema, la forma de pensar:

class Solution {
    
    
    public String convert(String s, int numRows) {
    
    
       char[]str = s.toCharArray();
       if(numRows<=1){
    
    
           return s;
       }
        char[][]res = new char[numRows][s.length()/2+1];
        int k=0;
        int j=0;
        int l=0;//列索引
        int i=0;//行索引
        while(j<str.length){
    
    

            if(k==0){
    
    //向下走
             for(i=0;i<numRows&&j<str.length;i++){
    
    
                res[i][l] = str[j];
                j++;
            }
            k=1;//改变方向
            l++;//走到了尽头,列加1
            }
            if(k==1){
    
    //开始向上走
                int row = numRows-2;
                for(i=l;row>0&&j<str.length;i++){
    
    
                    res[row][i]= str[j];
                    row--;
                    j++;
                }
                l=i;
                k=0;
            }
        }  
        StringBuilder sb = new StringBuilder();
        for(int b=0;b<res.length;b++){
    
    
            for(int t=0;t<res[b].length;t++){
    
    
                if('\u0000'!=res[b][t]){
    
    //char数组默认值为0的字符值'\u000'
                    sb.append(res[b][t]);//遍历组合输出
                }
            }

        }
        return sb.toString();
    }
}

Inserte la descripción de la imagen aquí

1.2, pensamiento directo por primera vez optimización

Elimina algunas cantidades innecesarias:

class Solution {
    
    
    public String convert(String s, int numRows) {
    
    
        char[]str = s.toCharArray();
            if(numRows<=1){
    
    
                return s;
            }
            char[][]res = new char[numRows][s.length()/2+1];
            int j=0;
            int l=0;//列索引
            int i;//行索引
            while(j<str.length){
    
    

                //向下走
                for(i=0;i<numRows&&j<str.length;i++){
    
    
                    res[i][l] = str[j];
                    j++;
                }
                l++;
                int row = numRows-2;
                for(i=l;row>0&&j<str.length;i++){
    
    //斜向上走
                    res[row][i]= str[j];
                    row--;
                    j++;
                }
                l=i;
            }
            StringBuilder sb = new StringBuilder();//提取数据
            for (char[] re : res) {
    
    
                for (char c : re) {
    
    
                    if ('\u0000' != c) {
    
    
                        sb.append(c);
                    }
                }

            }
            return sb.toString();
    }
}

Inserte la descripción de la imagen aquí

El algoritmo anterior se debe principalmente a la adición de una matriz bidimensional, que tiene muchos valores nulos y conduce a una complejidad temporal de O (N 2 ). Entonces todavía simulamos la dirección de la cuerda y la agregamos.

1.3, la segunda optimización, cambia el tipo de uso

Cambiaremos la matriz bidimensional. Conviértete en un List<StringBuilder>tipo.
Cada StringBuilder representa una fila de datos, por lo que hay n StringBuilders. La dirección está indicada por una bandera. Sabemos que solo en la primera y última línea, el valor de la bandera cambia y la tendencia cambia. El siguiente código está disponible:

class Solution {
    
    
    public String convert(String s, int numRows) {
    
    
       if(numRows<2){
    
    
           return s;
       }
        //模拟走向
        List<StringBuilder> resRow = new ArrayList<>();
        for(int i=0;i<numRows;i++){
    
    
            resRow.add(new StringBuilder());//创建n行空字符串
        }
        
        int index=0,flag=1;//1表示向下走
        for(char k:s.toCharArray()){
    
    
            resRow.get(index).append(k);//刚开始是想下走
            index+=flag;//开始走,向下则索引加1
            if(index==0||index==numRows-1){
    
    
                //遇到末行就要向上走,遇到首行方向重新向下走。
                flag=-flag;
            }
            //这样,在模拟走的过程中我们不需要添加'\u0000';加大空间利用率

        }
        StringBuilder res =new StringBuilder();//将每行的字符串进行组合输出
        for(StringBuilder k:resRow){
    
    
             res.append(k.toString());
        }
         return res.toString();
    }
}

Inserte la descripción de la imagen aquí
En términos de complejidad temporal, debe estimarse como O (N), la complejidad espacial es: O (N);

2.1, encuentra la ley para lograr

Finalmente, a partir del porcentaje de derrotas por sumisión, podemos saber que aún debe optimizarse. Debe ser que la distribución de datos sea regular. El resultado puede ser más rápido. Entonces, encuentre la siguiente regla:
Inserte la descripción de la imagen aquí
De la línea, la primera línea se entiende como 8, 0; 8-2*1,0+2*1el índice de intervalo de la segunda línea es el índice de la última línea 8-2*(n-1),0+2*(n-1). Entonces puedes escribir el código:

class Solution {
    
    
    public String convert(String s, int numRows) {
    
    
           if(numRows<2){
    
    
                return s;
            }
            List<StringBuilder> list = new ArrayList<>();
            for(int i=0;i<numRows;i++){
    
    
                list.add(new StringBuilder());
            }//n行空字符串
            int dlter=2*(numRows-1);//找到间隔初值

            char[] chars = s.toCharArray();
            for(int i=0;i<numRows&&i<chars.length;i++){
    
    
                list.get(i).append(chars[i]);//初始化第一个值
                int col;//间隔
               if(i==0||i==numRows-1){
    
    //间隔为dlter、0
                   col = i+dlter;
                   while(col<chars.length){
    
    
                       list.get(i).append(chars[col]);
                       col+=dlter;
                   }

                }else {
    
    //间隔为d1和d2;
                   int d1 = dlter-2*i;
                   int d2 = dlter-d1;
                   col = i+d1;//d1的间隔
                   while(col<chars.length){
    
    
                       list.get(i).append(chars[col]);
                       if((col+=d2)<chars.length)
                           list.get(i).append(chars[col]);
                       col+=d1;//8-2=6,下一次就是8-6=2
                   }
               }
           }
            StringBuilder res =new StringBuilder();//将每行的字符串进行组合输出
            for(StringBuilder k:list){
    
    
                res.append(k.toString());
            }
            return res.toString();
    }
}

Inserte la descripción de la imagen aquí

2.2, encuentra la optimización en la ley

En la aplicación anterior, encontramos que los elementos que agregamos se agregaron en línea. Entonces no necesitamos la operación de fusión final. Entonces se puede lograr con solo un StringBuilder:

class Solution {
    
    
    public String convert(String s, int numRows) {
    
    
            if(numRows<2){
    
    
                return s;
            }
            StringBuilder list = new StringBuilder();
            int dlter=2*(numRows-1);//找到间隔初值
            char[] chars = s.toCharArray();
            int n=chars.length;
            for(int i=0;i<numRows&&i<n;i++){
    
    
                list.append(chars[i]);//初始化第一个值
                int col;//间隔
               if(i==0||i==numRows-1){
    
    //间隔为dlter、0
                   col = i+dlter;
                   while(col<n){
    
    
                       list.append(chars[col]);
                       col+=dlter;
                   }
                }else {
    
    //间隔为d1和d2;都大于0
                   int d1 = dlter-2*i;
                   int d2 = dlter-d1;
                   col = i+d1;//d1的间隔
                   while(col<n){
    
    
                       list.append(chars[col]);
                       if((col+=d2)<n)
                           list.append(chars[col]);
                       col+=d1;//8-2=6,下一次就是8-6=2
                   }
               }
           }
            return list.toString();
        }
}



Finalmente, la eficiencia se mejora perfectamente:
Inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/qq_44861675/article/details/108053833
Recomendado
Clasificación