[C++]LeetCode 6: ZigZag Conversion(ZigZag排序)

16 篇文章 0 订阅
16 篇文章 1 订阅

Problem:

The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)

P   A   H   N
A P L S I I G
Y   I   R
And then read line by line: "PAHNAPLSIIGYIR"

Write the code that will take a string and make this conversion given a number of rows:

string convert(string text, int nRows);

convert("PAYPALISHIRING", 3) should return "PAHNAPLSIIGYIR".


分析:

先分析一下题意,将字符串按ZigZag方式排列,并按序输出。何为ZigZag,我按下标顺序表示如下,其中row = 5

0

6

12

18
1 57 1113 1719
24 810 1416  
3

9

15   
相信看完此图大家都有了一个直观的感觉。下面再来分析一下规律:

每整列(图中用红色标出)的间隔为6,

第一行:下标分别为0、6、12、18 -> 每个整列数字间隔为6

第二行:下标分别为1、5、7、11、13、17、19 ->每个整列数字间的间隔分别两部分,左半边为4,右半边为2

第三行:下标分别为2、4、8、10、14、16 -> 每个整列数字间的间隔分别两部分,左半边为2,右半边为4

第四行:下标分别为3、9、15 -> 每个整列数字间隔为6

结果按第一行至第四行分别输出。

故由上面的直观分析可知:

每整列的间隔为circule = 2*numRows - 2,即numRows + numRow - 2,numRow - 2为去除首位后的长度

第i行的输出的起始下标为i,按circule分割为一个个子部分,每部分又分为左右两半,左半长为cirLeft = circule - 2 * i,右半长为circule - cirLeft。

注意:

在提交时出现过Time Limit ExceededOutput Limit Exceeded的问题,主要原因都是未考虑边界问题。

1、numRows = 1时要另外处理,因为此时直接计算circule = 2 * numRows - 2 = 0

2、s.size() <= numRows可直接输出

3、当每次更新当前下标位置index时,如index + cirLeft,index + circule,一定要考虑是否越界,而不止是每次在while时检查。


AC Code (C++):

class Solution {
public:
    //1158 / 1158 test cases passed.
    //Runtime: 27 ms
    string convert(string s, int numRows) {
        if (s.size() <= numRows || numRows <= 1) {
            return s;
        }
        
        string output;
        int circule = (numRows << 1) - 2;//每一轮包含多少个字符
        for (int cirLeft = circule, i = 0; cirLeft >= 0; cirLeft -= 2, ++i) {
            int strIndex = i;
            output.push_back(s[strIndex]);
            cout<<output.size()<<'\t'<<output<<endl;
            while (strIndex < s.size()) {
                if (cirLeft != 0 && strIndex + cirLeft < s.size()) {
                    output.push_back(s[strIndex + cirLeft]);
                    cout<<output.size()<<'\t'<<output<<endl;
                }
                strIndex += circule;
                if(cirLeft != circule && strIndex < s.size()){
                    output.push_back(s[strIndex]);
                    cout<<output.size()<<'\t'<<output<<endl;
                }
            }
        }
        
        return output;
    }
};




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值