[模拟|字符串] leetcode 6 Z字形变换

[模拟|字符串] leetcode 6 Z字形变换

1.题目

题目链接
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “LEETCODEISHIRING” 行数为 3 时,排列如下:

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

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“LCIRETOESIIGEDHN”。
示例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

2.分析

2.1.结果存储

输入给出的是一维的顺序字符串,而输出的字符串是建立在“Z字型”这样一个二维结构上的。因此可以首先考虑建立一个二维数组来存储这个Z字形结构。
由于字符串本质上是一个一维的字符数组,因此我们建立一个字符串数组便可以模拟这一二维结构:

string convert(string s, int numRows) {
    if (numRows == 1) {  //输出也是一行的话则直接返回原字符串
        return s;
    }
    //行数比字符串长度大的话,实际上只有一列
    vector<string> rows(min(numRows, int(s.size())));
	//......
}

2.2.遍历顺序

“Z字型”(或者看起来更像"N字型")遍历,本质上是先往下,再往上,再往下…因此我们需要判断好什么时候调整遍历的方向。
而只有在两种情况下需要调整方向:遍历到第0行(方向需调整至向下),遍历到最后一行(方向需调整至向上)。

int curRow = 0;  //当前行
bool goingDown = false;  //是否向下
for (char c : s) {
    rows[curRow] += c;  //将该字符存入对应的结果行中
    if (curRow == 0 || curRow == numRows - 1) {  //反向
        goingDown = !goingDown;
    }
    curRow += goingDown ? 1 : -1; //根据方向调整行数
}

实际上本题到这里就几乎做完了。以示例2为例,表面上我们要存储的输出为:

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

实际上存储的是:

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

按行展开后依然为LDREOEIIECIHNTSG,因为我们并不关心每行之间的空格。

3.代码

class Solution {
public:
    string convert(string s, int numRows) {
        //输出也是一行的话则直接返回原字符串
        if (numRows == 1) {  
            return s;
        }
        //行数比字符串长度大的话,实际上只有一列
        vector<string> rows(min(numRows, int(s.size())));
        int curRow = 0;//当前行
        bool goingDown = false;//是否向下
        for (char c : s) {
            rows[curRow] += c;//将该字符存入对应的结果行中
            if (curRow == 0 || curRow == numRows - 1) {//反向
                goingDown = !goingDown;
            }
            curRow += goingDown ? 1 : -1;//根据方向调整行数
        }
        string res;
        for (string row : rows) {
            res += row;
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值