LeetCode | ZigZag Conversion(锯齿形转换)


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"
.

字符串按照锯齿形分布,然后按照行序列输出。


题目解析:

思路一:

由于题目给的例子相对简单,我们应该尝试更一般性的数组,比如nRows为6,例子中不以字符表示,而是以数组下标的形式给出:

0                  10

1              9  11

2          8      12

3      7          13         17

4  6              14  16

5                  15

除了第一行和最后一行,在一个循环0–9之间,中间的序列都出现了两次。我们可以得到一个循环的个数onelen = 2*nRows – 2;那么第0行两个之间的间距为onelen,第一行间距为onelen – 1 – 1;….第i行间距为onelen – 2*i;我们也尝试将第0行和最后一行统一到一个循环中,但是有些复杂,所以就另外做了判断,单独处理;同时在输出一行时,将中间的每一行再分成onelen为个数的循环,每次输出两个。

这样实现起来很容易,但是我们必须要考虑多种可能情况,包括无效的输入等等。

有了以上的公式,我们就可以写出代码了。但需要注意几点:
1.判断所求出的下标是不是越界了,即不能超出原字串的长度;
2.注意处理nRows=1的情况,因为它会使差值2 * nRows – 2的值为0,这样下标值会一直不变,进入死循环,产生
    Memory Limit Exceeded 或者 Output Limit Exceeded之类的错误。
3.还有一些其他的边界情况,如:nRows > s.length,s.length = 0等需要处理。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void ConvertStr(char *str,int nRows)
{
    int onelen = 2*nRows - 2;
    int index;
    int n = strlen(str);

    if(nRows<0 || nRows > n){   //处理一些非法输入!
        printf("the rows doesn't correct!");
        return;
    }
    if(nRows == 1){ //当nRows为1的时候,onelen就为0,不再增加,会陷入死循环!
        printf("%s",str);
        return;
    }

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

        if(i == 0 || i == nRows-1){
            while(index < n){
                printf("%c",str[index]);
                index = index+onelen;
            }
        }else{
            while(index < n){
                printf("%c",str[index]);
                int temp = index + onelen - 2*i;
                if(temp > n)
                    break;
                printf("%c",str[temp]);
                index = index + onelen;
            }
        }
    }
}


int main(void)
{
    char *str = "PAYPALISHIRING";
    ConvertStr(str,-1);

    return 0;
}

思路二:

还有另外一种考虑,我们设char arr[nRows][strlen(str)]数组。我们将str指向的字符串按照列从上到下再从下到上,依次循环给每一行分配一个元素。这个也好实现,不过有些复杂,需要为每一行都在设置个lenth,表示存储了多少元素,以便下一个元素能很快存储。最后再给每一行末尾添加空字符,最后再输出即可。

但是利用C++的话,就很好实现了,给容器添加元素,直接加即可。没有过多的考虑。

代码如下:

class Solution {

public:

    string convert(string s, int nRows) 
    {
        string ret;
        int n=s.size();
        vector<string>v(nRows);

        for(int i=0;i<n;)
        {
            for(int j=0;j<nRows&&i<n;j++,i++)
            v[j]+=s[i];

            for(int j=nRows-2;j>0&&i<n;j--,i++)
            v[j]+=s[i];
        }

        for(int i=0;i<nRows;i++)
        {
            for(int j=0;j<v[i].size();j++)
            ret+=v[i][j];
        }
        return ret;
    }
};


点赞