LeetCode.6-Z字形变换

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_32157579/article/details/102725069

将一个给定字符串根据给定的行数,以从上往下、从左到右进行 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”
解释:
L   D  R
E O E I I
E C I H N
T  S  G

C#语言实现
方法一:二维数组
思路
例如:
L   D  R
E O E I I
E C I H N
T  S  G
那么从LEET ,C,O三个为一个周期,这个周期内有6个元素,3个数组,以此类推

public static string Convert(string s, int numRows)
{
    if (s.Length <= numRows || numRows == 1) return s;
    int cycleNumber = numRows * 2 - 2;//每周期字符个数
    int cycleArrayCount = numRows - 1;//每周期数组个数
    //总共需要多少数组
    int arrayCount = s.Length / cycleNumber * cycleArrayCount;

    if (s.Length < cycleNumber)
    {
        arrayCount = cycleArrayCount - (cycleNumber - s.Length);
    }
    if (s.Length > cycleNumber && s.Length % cycleNumber != 0)
    {
        if (s.Length % cycleNumber <= numRows)
            ++arrayCount;
        else
            arrayCount += s.Length % cycleNumber % numRows + 1;
    }
    char[][] array = new char[arrayCount][];
    int strIndex = 0;
    for (int i = 0; i < arrayCount; i++)
    {
        array[i] = new char[numRows];
        if (i % cycleArrayCount != 0)
            array[i][cycleArrayCount - i % cycleArrayCount] = s[strIndex++];
        else
        {
            for (int j = 0; j < numRows; j++)
            {
                if (strIndex < s.Length)
                    array[i][j] = s[strIndex++];
            }
        }
    }
    List<char> charList = new List<char>();
    for (int i = 0; i < numRows; i++)
    {
        for (int j = 0; j < arrayCount; j++)
        {
            if (array[j][i] != '\0')
                charList.Add(array[j][i]);
        }
    }
    return string.Join("", charList);
}

方法二 :按行排序
创建一个numRows行的字典,在字典中累加每行的字符,最后按行拼接,返回字符串

public static string Convert(string s, int numRows)
{
    if (numRows == 1) { return s; }
    Dictionary<int, List<char>> dic = new Dictionary<int, List<char>>();
    int rowIndex = 0;
    bool goingDown = false;
    for (int i = 0; i < numRows; i++)
    {
        dic.Add(i, new List<char>());
    }
    foreach (char c in s)
    {
        dic[rowIndex].Add(c);
        if (rowIndex == 0 || rowIndex == numRows - 1) { goingDown = !goingDown; }
        rowIndex += goingDown ? 1 : -1;
    }
    string[] arr = new string[numRows];
    foreach (var item in dic)
    {
        arr[item.Key] = string.Join("", item.Value);
    }
    return string.Join("", arr);
}

方法三: 按行访问
思路
按照与逐行读取 Z 字形图案相同的顺序访问字符串。

算法
首先访问 行 0 中的所有字符,接着访问 行 1,然后 行 2,依此类推…
对于所有整数 k,
行 0中的字符位于索引 k(2⋅numRows−2) 处;
行 numRows−1 中的字符位于索引 k(2⋅numRows−2)+numRows−1 处;
内部的 行 i 中的字符位于索引 k(2⋅numRows−2)+i 以及 (k+1)(2⋅numRows−2)−i 处;

public static string Convert(string s, int numRows)
{
    if (numRows == 1) return s;
    string ret="";
    int cycleLen = 2 * numRows - 2;//每周期字符个数
    for (int i = 0; i < numRows; i++)
    {
        for (int j = 0; j + i < s.Length; j += cycleLen)
        {
            ret += s[j + i];
            if (i != 0 && i != numRows - 1 && j + cycleLen - i < s.Length)
                ret += s[j + cycleLen - i];
        }
    }
    return ret;
}

猜你喜欢

转载自blog.csdn.net/qq_32157579/article/details/102725069