leetcode_zigzag conversion

来源:互联网 发布:java 解压war包 编辑:程序博客网 时间:2024/06/06 03:29

题目:
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”
我的答案:
版本一:

string convert(string s, int numRows){    if (numRows == 1)        return s;    int L = s.length();    const char *p = s.c_str();    vector<vector<char> > A;    vector<char> a;    int N = 0;    while (N < L){        if (N > L)            break;        for (int i = 0; i < numRows; i++){            if (N < L)            {                a.push_back(*(p + N));                N++;            }            else                break;        }        A.push_back(a);        a.clear();        for (int i = numRows - 2; i > 0; i--)        {            if (N < L){                for (int j = 0; j < numRows; j++)                {                    if (N < L)                    {                        if (j != i)                            a.push_back('\0');                        else                        {                            a.push_back(*(p + N));                            N++;                        }                    }                    else                        break;                }                A.push_back(a);                a.clear();            }            else                break;        }    }    //对最后一列的数据进行完善,因为字符串长度是随机的,所以最后一列可能在没有装满之前,字符串已经被分配完毕,所以采用这种方式补全,以进行下面每行的链接    int last_size = A[A.size() - 1].size();        if (last_size != numRows)    {        for (int i = 0; i < numRows - last_size; i++)            A[A.size() - 1].push_back('\0');    }    //数据已经存好    for (int i = 0; i < A.size(); i++)    {        for (int j = 0; j < A[i].size(); j++)            cout << A[i][j] << " ";        cout << endl;    }    stringstream ss;    for (int i = 0; i < numRows; i++)    {        for (int j = 0; j < A.size(); j++)        {            if (A[j][i] == '\0')                continue;            else                ss << A[j][i];        }    }    return ss.str();}

思路解析:遍历整个字符串,将其按照之字形的结构,按列存储,显然除了部分列的元素个数是numRows之外,其他列的元素个数都是1,为了后续字符重新排序的方便,将每列不含有字符串字符的地方用结束符代替,使得每列数据在存储中占用相同的空间,在后续数据重新排序的时候,只需要循环遍历所有的列并依次输出各列的元素(遇到结束符的时候,不输出该字符),在利用该方法的时候关键是保证一开始在遍历存储字符串的时候要保证每列都占用相同的空间,并且所有列中的非结束符字符的存放结构满足之字形结构。所以如果最后在遍历字符串结束后,要判断最后一列的元素是否为numRows个,如不是需要利用结束符补全。整个算法的思想就是不用费力去观察之字形结构的规律并建模,只需要按列存储之后并循环遍历输出即可,比较好理解,但是运行时间较长。
版本二(进阶版):

string zigzag_convert(string s, int numRows){    if (numRows == 1)        return s;    if (numRows < 1)        return "";    int gap = 2 * numRows - 2;    int val = 0;    int L = s.length();    string res = "";    for (int i = 0; i < numRows; i++,val += 2)    {        res += s[i];        for (int j = i; j<L;)        {            if ((gap - val) != 0)            {                j += (gap - val);                if (j < L)                    res += s[j];                else                    break;            }            if (val != 0)            {                j += val;                if (j < L)                    res += s[j];                else                    break;            }        }    }    return res;}

思路解析:该版本的思想是观察之字形结构并进行建模。举例说明:
假设输入字符串为S,
S=”abcdefghijklmnopqrstuvwxyz”;
numRows=5;
以下是之字形中每行元素在字符串中的下标(为了方便表述,从数据存储的角度出发,引入第0行):
第0行:0 8 16 24
第1行:1 7 9 15 17 23 25
第2行:2 6 10 14 18 22
第3行:3 5 11 13 19 21
第4行:4 12 20
观察以上下标,可以得到结论,除了第0行与最后一行,每相隔的两个下标之间的距离都是:gap=2*numRows-2,每行的第一个元素的下标都与行号相同;第0行与最后一行的各元素相邻下标的距离为gap;根据这个规律写出以上代码。显然,利用这种方法不会消耗多余的空间,而且只需要遍历一次字符串即可,算法高效。

原创粉丝点击