Leetcode Algorithm 006. ZigZag Conversion

本文介绍了一种特殊的字符串转换方法——ZigZag走法,并提供了详细的解析及实现代码。ZigZag走法是指将字符串按照指定行数进行Z形排列后,再按行读取形成新的字符串。文章通过实例清晰展示了不同行数下的ZigZag走法,总结出了字符在新字符串中的位置规律,并给出了高效的算法实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Leetcode Algorithm 006. ZigZag Conversion

ZigZag Conversion
给定一个字符串,按照规定的zigzag走法排列之后,按行取出字符形成一个新的字符串

解题思路

首先要明白zigzag走法是什么意思。
题目给了我们一个例子:"PAYPALISHIRING"用了3行的zigzag走法会是:

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

看起来还是不太懂?现在画一个4行的zigzag走法:

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

5行的zigzag走法:

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

这样是不是清楚多了?Zigzag走法其实就是先走满一列,再沿着斜线方向往回走,走到第一行再次往下走。

其实我们可以找到其中原本字符串在zigzag走法中规律:

0       8
1     7 9
2   6   10    ...
3 5     11 13
4       12
0              2n-2
1         2n-3 2n-1
...   ...      ...       ...
n-2 n          3n-4 3n-2
n-1            3n-3

假设原本的字符串是s,经过n行的zigzag走法之后,某行的行号是i,那么行首的元素将会是s[i]。第i行的下一个元素通过两个间隔来决定,一个是step1 = 2*n - 2 - 2*i,另外一个是step2 = 2*i。知道这条数学规律之后,我们可以很容易地处理它了。

要注意的是当step1或者step2为0的时候恰好是第0行和第n-1行,要做特殊处理。
另外,当n==1或者n>=s.size()的时候无需进行zigzag处理,直接返回原来的字符串即可。

代码

#include<iostream>

using namespace std;

class Solution {
public:
    string convert(string s, int numRows) {
        int length = s.size();

        if (numRows == 1 || numRows >= length)
            return s;

        string result = "";

        for (int i = 0; i < numRows; i++) {
            int index = i;

            int step1 = 2 * numRows - 2 - 2 * i;
            int step2 = 2 * i;

            if (index >= length)
                break;

            result += s[index];

            while (true) {
                if (step1 != 0) {
                    index += step1;
                    if (index < length)
                        result += s[index];
                    else
                        break;
                }

                if (step2 != 0) {
                    index += step2;
                    if (index < length)
                        result += s[index];
                    else
                        break;
                }
            }
        }
        return result;
    }
};

测试样例

int main() {
    Solution s;

    cout << s.convert("AB", 3) << endl;

    cout << s.convert("PAYPALISHIRING", 5) << endl;
    cout << s.convert("PAYPALISHIRING", 4) << endl;
    cout << s.convert("PAYPALISHIRING", 3) << endl;
    cout << s.convert("PAYPALISHIRING", 2) << endl;
    cout << s.convert("PAYPALISHIRING", 1) << endl;

    return 0;
}

输出

AB
PHASIYIRPLIGAN
PINALSIGYAHRPI
PAHNAPLSIIGYIR
PYAIHRNAPLSIIG
PAYPALISHIRING
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值