LeetCode第6题:将字符串 PAYPALISHIRING以Z字形排列成给定的行数

public class LeetCode6 {
    public static void main(String[] args) {
        /**
         * LeetCode 第6题:将字符串 "PAYPALISHIRING" 以Z字形排列成给定的行数:
            P   A   H   N
            A P L S I I G
            Y   I   R
                          之后从左往右,逐行读取字符:"PAHNAPLSIIGYIR"
                         样例: 输入: s = "PAYPALISHIRING", numRows = 4
                        输出: "PINALSIGYAHRPI"
                        解释:
                        P     I    N
                        A   L S  I G
                        Y A   H R
                        P     I
          *解题思路:要得到解释后的二维数组 conStr[numRows][len]; len未知?
          * 找规律, len = s.length()/ (2*numRows - 2) * (numRows - 1);
          * 解释一下将一个有完整列的如:PAYP这一列到ISHI这一列,有 numRows - 2个字符,加上完整的一列则为 2*numRows -2个字符
          * 而这种规律递进的行长为 numRows - 1, 当然 len != s.length() / 2; 计算机运算取整!!
          * 当然还有不规律的,如最后的NG这一列,其判读 otherstr = s.length()% (2*numRows - 2)
          * 判断他的列数进行相加得到最后的len
          * 那么接下来就填充再取出就好了
         */
        String s = "PAYPALISHIRING";
        System.out.println(convert(s,9));
    }
    
  public static String convert(String s, int numRows) {
       if(numRows == 1 )
           return s;
        int len = s.length() / (2*numRows - 2) * (numRows - 1);
        int otherStr = s.length() % (2*numRows - 2),otherLen = 0;
        if(otherStr != 0 ){
            if(otherStr <= numRows)
                otherLen = 1;
            else
            otherLen = otherStr - numRows + 1;
        }
        len = len + otherLen;
        char conStr[][] = new char [numRows][len];
            int k = 0 , l ,i = 0,j = 0;
            while(k < s.length()){
                //填充完整的一列
                    i = 0; l = numRows;
                    while(l > 0 && k < s.length()){
                    conStr[i][j] = s.charAt(k);
                    i++; k++; l--;
                    }
                    //像右推进一列,行数回归到非完整的起始行
                    j++; i = numRows - 2;
                    //填充非完整的列
                    for(int z = numRows - 2;z > 0;z--){
                        if(k < s.length()){
                        conStr[i][j] = s.charAt(k);
                        i--; j++; k++;
                    }
                    }
            }
            StringBuilder changedStr = new StringBuilder() ;
            for( i = 0 ; i < numRows ; i++){
            for( j = 0 ; j < len ; j++){
                if(conStr[i][j] != '\0'){
                    changedStr.append(conStr[i][j]);
                }
            }
        }
      return new String(changedStr);
    }
}

事实上,根本不需要二维数组,采用  List<StringBuilder> rows = new ArrayList<>();

将每行的字符记录,当到了最上面的行或者最下面的行才更改到下一列(假设你是看了上面二维数组排序的),那如何在List中实现呢?在List中的实现原理就是移动方向,用 boolean goingDown = false;记录方向,核心代码:

for (char c : s.toCharArray()) {
            rows.get(curRow).append(c);
            if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown;
            curRow += goingDown ? 1 : -1;
        }
《LeetCode第6题:将字符串 PAYPALISHIRING以Z字形排列成给定的行数》

行数curRow为min(s.length(),numRows);,开始curRow为0,goingDown变为true,记录到最下面的行,转变方向,直到记录完全。

具体方法:

public String convert(String s, int numRows) {

        if (numRows == 1) return s;

        List<StringBuilder> rows = new ArrayList<>();
        for (int i = 0; i < Math.min(numRows, s.length()); i++)
            rows.add(new StringBuilder());

        int curRow = 0;
        boolean goingDown = false;

        for (char c : s.toCharArray()) {
            rows.get(curRow).append(c);
            if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown;
            curRow += goingDown ? 1 : -1;
        }

        StringBuilder ret = new StringBuilder();
        for (StringBuilder row : rows) ret.append(row);
        return ret.toString();
    }

当然第一种方法是暴力的,其实可以更暴力点,就是用那种思想来直接进行字符的检索,不使用二维数组,只是不太好理解。

具体代码:

class Solution {
    public String convert(String s, int numRows) {

        if (numRows == 1) return s;

        StringBuilder ret = new StringBuilder();
        int n = s.length();
        int cycleLen = 2 * numRows - 2;

        for (int i = 0; i < numRows; i++) {
            for (int j = 0; j + i < n; j += cycleLen) {
                ret.append(s.charAt(j + i));
                if (i != 0 && i != numRows - 1 && j + cycleLen - i < n)
                    ret.append(s.charAt(j + cycleLen - i));
            }
        }
        return ret.toString();
    }
}

    

    原文作者:Z字形编排问题
    原文地址: https://blog.csdn.net/xc121566/article/details/80868877
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞