6.Z字形变换

将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。

比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下:

L   C   I   R
E T O E S I I G
E   D   H   N
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"LCIRETOESIIGEDHN"。

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

string convert(string s, int numRows);
示例 1:

输入: s = "LEETCODEISHIRING", numRows = 3
输出: "LCIRETOESIIGEDHN"
示例 2:

输入: s = "LEETCODEISHIRING", numRows = 4
输出: "LDREOEIIECIHNTSG"
解释:

L     D     R
E   O E   I I
E C   I H   N
T     S     G

 

这道题刚开始看了半天没看懂是咋样变换的,上网查了些资料,终于搞懂了,就是要把字符串摆成一个之字型的,参考了网上这位仁兄的解法 (http://www.cnblogs.com/springfor/p/3889414.html)。

比如有一个字符串 “0123456789ABCDEF”,转为zigzag

当 n = 2 时:

0 2 4 6 8 A C E

1 3 5 7 9 B D F

当 n = 3 时:

0   4    8     C

3 5 7 9 B D F

2    6   A     E

当 n = 4 时:

0     6        C

1   5 7    D

4   8 A    E

3      9       F

 

我们发现,除了第一行和最后一行没有中间形成之字型的数字外,其他都有,而首位两行中相邻两个元素的index之差跟行数是相关的,为 2*nRows - 2, 根据这个特点,我们可以按顺序找到所有的黑色元素在元字符串的位置,将他们按顺序加到新字符串里面。对于红色元素出现的位置也是有规律的,每个红色元素的位置为 j + 2*nRows-2 - 2*i, 其中,j为前一个黑色元素的列数,i为当前行数。 比如当n = 4中的那个红色5,它的位置为 1 + 2*4-2 - 2*1 = 5,为原字符串的正确位置。当我们知道所有黑色元素和红色元素位置的正确算法,我们就可以一次性的把它们按顺序都加到新的字符串里面。解析在代码中:

class Solution {
public:
    string convert(string s, int numRows) {
          string convert_s = "";
        int length_s = s.size();
        if(numRows <=1)//错:这句和下面这句没加,当行数<=1,只有一行时,应该直接返回s
            return s;
        int door = 2 * numRows - 2;
        //这是一道找规律的题,主要是找黑色和红色字符的位置,黑色字符的间隔是 2 * numRows - 2,而红色字符间隔是j + door - 2 * i(i是上一个黑色字符行数,j是黑色字符列数)
        //第一个for循环是控制行数,第二个for循环是控制黑色字符的列数,然后convert_s += s[j];就是向convert_s加入黑色字符
        //而当i不是第一行和最后一行时,就会包括红色字符,而红色字符间隔是j + door - 2 * i,则在黑色字符之间插入符合条件的红色字符,用黑色字符控制插入红色字符的起点convert_s += s[k];
        for (int i = 0; i < numRows;i++)//错:i < length_s改为numRows
        {
            for (int j = i; j < length_s;j+=door)
            {
                int k = j + door - 2 * i;
                convert_s += s[j];//错:(1)convert_s[i] += s[door];改为convert_s += s[door];(2)s[door]改为s[j]
                if (i!=0&&i!=numRows-1&&k<length_s)
                {
                    convert_s += s[k];
                }
            }
        }
        return convert_s;
        
    }
};

参考文章:https://www.cnblogs.com/springfor/p/3889414.html

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值