6-Z字形变换

题目:

将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。

比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下:

L C I R
E T O E S I I G
E D H N
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"LCIRETOESIIGEDHN"。

请你实现这个将字符串进行指定行数变换的函数:

string convert(string s, int numRows);
示例 1:

输入: s = "LEETCODEISHIRING", numRows = 3
输出: "LCIRETOESIIGEDHN"
示例 2:

输入: s = "LEETCODEISHIRING", numRows = 4
输出: "LDREOEIIECIHNTSG"

解答1:

直接将string放到一个二维数组中,然后按照要求输出的顺序输出:

string convert(string s, int numRows)
{
    if (s.length() == 0 || numRows <= 1)    //如果是1行,直接返回
    {
        return s;
    }

    int length = s.length();
    char** array = new char*[numRows];
    for (int ii = 0; ii < numRows; ii++)
    {
        array[ii] = new char[length];
        for (int i = 0; i < length; i++)
        {
            array[ii][i] = 0;    //初始化
        }
    }

    int index = 0;
    int i=0, j = 0;//i表示行-numRows,j表示列-length
    while (index < length)
    {
        if (j % (numRows - 1) == 0)//表示竖列
        {
            if (i == numRows)
            {
                j++;
                i-=2;//i=numRows时,已经超过范围了,需要减2才符合要求
            }
            else
            {
                array[i++][j] = s[index];
                index++;
                continue;
            }
        }
        else//正常情况的,i-- 然后j++
        {
            array[i--][j++] = s[index++];
        }
    }

    //输出
    string result = "";
    for (int j = 0; j < numRows; j++)//
    {
        for (int i = 0; i < length; i++)//
        {
            if (array[j][i] > 0)
            {
                result+=array[j][i];
            }
        }
    }

    for (int ii = 0; ii < numRows; ii++)
    {
        delete[] array[ii];
    }

    return result;
}

 

结果:

  内存、运行时间都很差,时间复杂度为O(n^2),且创建了一个临时的二维数组,占用较多空间。

解法2 按行排序:

不用考虑字符串放置时的空格,将string中的字符放到各个行对应的容器中,然后拼接结果即可。

思路

通过从左向右迭代字符串,我们可以轻松地确定字符位于 Z 字形图案中的哪一行。

算法

我们可以使用 min(numRows,len(s)) 个列表来表示 Z 字形图案中的非空行。

从左到右迭代 ss,将每个字符添加到合适的行。可以使用当前行和当前方向这两个变量对合适的行进行跟踪。

只有当我们向上移动到最上面的行或向下移动到最下面的行时,当前方向才会发生改变。

string convert(string s, int numRows)
{
    if (numRows <= 1)
    {
        return s;
    }

    int row = min((int)s.size(), numRows);
    bool isGoingDown = false;
    int rowIdx = 0;
    vector<string> rowStrVec(row);
    for (int i = 0; i < s.size(); i++)
    {
        if (rowIdx == 0 || rowIdx == (row - 1))
        {
            isGoingDown = !isGoingDown;        //移动到第一行,最后一行时变换方向
        }
        
        rowStrVec[rowIdx] += s.at(i);
        rowIdx += (isGoingDown ? 1 : -1);    //如果到第一行,或者最后一行,改变方向
    }

    string result;
    for (auto str : rowStrVec)
    {
        result.append(str);
    }
    return result;
}

解法3 按行访问:

找输入输出字符串中,特定位置的字符之间的关系,

 https://leetcode-cn.com/problems/zigzag-conversion/solution/z-zi-xing-bian-huan-by-leetcode/

 

posted @ 2020-10-10 16:03  adfas  阅读(130)  评论(0编辑  收藏  举报