LeetCode06, the strongest analysis of zigzag transformation

Title description

Insert picture description here

1.1, direct thinking

Seeing the topic, the way to think of:

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();
    }
}

Insert picture description here

1.2, direct thinking for the first time optimization

Remove some unnecessary amounts:

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();
    }
}

Insert picture description here

The above algorithm is mainly due to the addition of a two-dimensional array, which has a lot of null values ​​and leads to a time complexity of O(N 2 ). So we still simulate the direction of the string and add it.

1.3, the second optimization, change the type of use

We will change the two-dimensional array. Become a List<StringBuilder>type.
Each StringBuilder represents a row of data, so there are n StringBuilders. The direction is indicated by a flag. We know that only in the first and last lines, the value of flag changes and the trend changes. The following code is available:

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();
    }
}

Insert picture description here
In terms of time complexity, it should be estimated as O(N); space complexity is: O(N);

2.1, find the law to achieve

Finally, from the percentage of submission defeats, we can know that it should be optimized. It should be that the distribution of data is regular. The result can be faster. So find the following rule:
Insert picture description here
From the line, the first line is understood as 8, 0; 8-2*1,0+2*1the interval index of the second line is the index of the last line 8-2*(n-1),0+2*(n-1). So you can write the code:

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();
    }
}

Insert picture description here

2.2, find the optimization in the law

In the above application, we found that the elements we added were added in line. So we don't need the final merge operation. So it can be achieved with only one 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();
        }
}



Finally, the efficiency is improved perfectly:
Insert picture description here

Guess you like

Origin blog.csdn.net/qq_44861675/article/details/108053833