剑指Offer 6. Z 字形变换

1. 题目

将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:

P   A   H   N
A P L S I I G
Y   I   R

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"

请你实现这个将字符串进行指定行数变换的函数:

string convert(string s, int numRows);

2. 示例

示例1:

输入:s = "PAYPALISHIRING", numRows = 3
输出:"PAHNAPLSIIGYIR"

示例2:

输入:s = "PAYPALISHIRING", numRows = 4
输出:"PINALSIGYAHRPI"
解释:
P     I    N
A   L S  I G
Y A   H R
P     I

示例3:

输入:s = "A", numRows = 1
输出:"A"

提示:

1 <= s.length <= 1000
s 由英文字母(小写和大写)、',' 和 '.' 组成
1 <= numRows <= 1000

3. 题解

这个题目存在潜在规律,我们只要把index和行号的关系找到就能按照一定顺序输出字符串了。

首先我们观察第一行,第j列第一个数和第j+1列第一个数之间,第j列第一个数所在列下面有numRows - 1个数,-1就是第一个数;第在斜对角线上,除去第j列最后一个元素,剩下numRows-1;总的数为(numRows-1) + (numRows-1) = 2 * numRows - 2。所以第一行的index为:i + k * (2 * numRows -2), i = 0。

观察第i行(0<i<numRows-1),发现除了有与第一行同样的规律,即i+ k * (2 * numRows - 2);中间还有一个数,它离第i行第j+1列数中间隔了2i个数,即i + k*(2*n - 2) - 2i = k*(2*numRows - 2) -  i;

最后一行与第一行一样的。

4. 实现

public class Convert6 {
    public String convert(String s, int numRows) {
        if(numRows == 1) return s;
        StringBuilder str = 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) {
                str.append(s.charAt(j + i));
                if(i != 0 && i != numRows - 1 && j + cycleLen - i < n) {
                    str.append(s.charAt(j + cycleLen - i));
                }
            }
        }
        return str.toString();
    }

    public static void main(String[] args) {
        String str = "PAYPALISHIRING";
        int numRows = 3;
        System.out.println(new Convert6().convert(str, numRows));
    }
}

 

5. 结语

  努力去爱周围的每一个人,付出,不一定有收获,但是不付出就一定没有收获! 给街头卖艺的人零钱,不和深夜还在摆摊的小贩讨价还价。愿我的博客对你有所帮助(*^▽^*)(*^▽^*)!

  如果客官喜欢小生的园子,记得关注小生哟,小生会持续更新(#^.^#)(#^.^#)。

 

posted @ 2021-06-25 10:43  抚琴尘世客  阅读(54)  评论(0编辑  收藏  举报