LeetCode6. 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)
这里写图片描述
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”.


二、思路

  1. 感觉是个数学问题,罗列几个例子,便于查看。
  2. 一开始自己理解错了,理解成如下的方式了。
    错误的理解
  3. 正确的理解应该是如下:
    正确的ZigZag
  4. 计算了每个模式的个数Rows+(Rows-2)

  5. 计算了每一行的列数,即每一行的元素个数。不过看了其他人的,貌似不需要计算。。。


三、程序示例

C#版本

  1. 正确ZigZag
class Program
{
    //正确的zigzag
    public static string Convert(string s, int numRows)
    {
        if (s.Length < 2 || numRows==1)
        {
            return s;
        }

        char[] result = new char[s.Length];
        //一组元素个数
        int pattern = numRows + (numRows - 2);

        //完整的组数
        int num = s.Length / pattern;
        //剩余字符个数,小于pattern
        int remain = s.Length % pattern;

        //计算zigzag结构每行元素个数
        int[] numsOfRow = new int[numRows];
        for (int i = 0; i < numRows; i++)
        {
            //考虑两种情况
            //1.当剩余数量小于等于行数时
            if (remain <= numRows)
            {
                if (i < remain)
                {
                    if (i==0 || i==numRows-1)
                    {
                        numsOfRow[i] = num + 1;
                    }
                    else
                    {
                        numsOfRow[i] = 2 * num + 1; 
                    }

                }
                else
                {
                    if (i == 0 || i == numRows - 1)
                    {
                        numsOfRow[i] = num;
                    }
                    else
                    {
                        numsOfRow[i] = 2 * num;
                    }
                }
            }
            //2.当剩余数量大于行数时
            else
            {
                if (i == 0 || i == numRows-1)
                {
                    numsOfRow[i] = num + 1;                        
                }
                else
                {
                    if (i >= pattern - (remain-1))
                    {
                        numsOfRow[i] = 2 * (num + 1);                            
                    }
                    else
                    {
                        numsOfRow[i] = 2 * num + 1;
                    }
                }
            }   
        }

        //最后逐行输出,得到结果
        int pos = 0;
        for (int row = 0; row < numRows; row++)
        {
            for (int col = 0; col < numsOfRow[row]; col++)
            {
                if (row == 0 || row == numRows-1)
                {
                    result[pos++] = s[row + col * pattern];
                }
                else
                {
                    //当前行偶数列
                    if (col % 2==0)
                    {
                        result[pos++] = s[row + (col / 2) * pattern];
                    }
                    //当前行奇数列
                    else if (col % 2 == 1)
                    {
                        result[pos++] = s[pattern - row + (col / 2) * pattern];                            
                    }
                }
            }
        }
        return new string(result);
    }


    static void Main(string[] args)
    {
        string str = "ABCDE";
        int rows = 4;
        string result = Convert(str, rows);
    }
}
  1. 错误的个人理解方式对应的程序示例。
class Program
{
    public static string Convert(string s, int numRows)
    {
        if (s.Length < 2 || numRows==1)
        {
            return s;
        }

        char[] result = new char[s.Length];
        //一组元素个数
        int pattern = numRows + (numRows - 2);

        //完整的组数
        int num = s.Length / pattern;
        //剩余字符个数,小于pattern
        int remain = s.Length % pattern;

        //计算zigzag结构每行元素个数
        int[] numsOfRow = new int[numRows];
        for (int i = 0; i < numRows; i++)
        {
            //考虑两种情况
            //1.当剩余数量小于等于行数时
            if (remain <= numRows)
            {
                if (i < remain)
                {
                    if (i==0 || i==numRows-1)
                    {
                        numsOfRow[i] = num + 1;
                    }
                    else
                    {
                        numsOfRow[i] = 2 * num + 1; 
                    }

                }
                else
                {
                    if (i == 0 || i == numRows - 1)
                    {
                        numsOfRow[i] = num;
                    }
                    else
                    {
                        numsOfRow[i] = 2 * num;
                    }
                }
            }
            //2.当剩余数量大于行数时
            else
            {
                if (i == 0 || i == numRows-1)
                {
                    numsOfRow[i] = num + 1;                        
                }
                else
                {
                    if (i <= remain - numRows)
                    {
                        numsOfRow[i] = 2 * (num + 1);                            
                    }
                    else
                    {
                        numsOfRow[i] = 2 * num + 1;
                    }
                }
            }
        }

        //最后逐行输出,得到结果
        int pos = 0;
        for (int row = 0; row < numRows; row++)
        {
            for (int col = 0; col < numsOfRow[row]; col++)
            {
                if (row == 0 || row == numRows-1)
                {
                    result[pos++] = s[row + col * pattern];
                }
                else
                {
                    result[pos++] = s[row + col * (pattern / 2)];
                }
            }
        }
        return new string(result);
    }


    static void Main(string[] args)
    {
        string str = "ABCDE";
        int rows = 4;
        string result = Convert(str, rows);
    }
}

END,


2018.03.15更新简便方法

上面的方法太笨拙,不忍。于是参考博客,学习了更加简便的方法。
感谢博友分享。
http://blog.csdn.net/chilseasai/article/details/47209565

思路如下

  1. 计算循环结构,即V字形,大小: pattern = numRows + (numRows - 2);
  2. 每个V型的起始地址=c-r,其中c每次内循环自增pattern
    对于首行、末行元素都是r + pattern*n
    对于中间行,r行,V型组第一个元素对应的是s[r + pattern*n]
    对于中间行,r行,V型组第二个元素对应的是s[(c-r)+(pattern-r)]=s[起始元素+循环结构内相对于起始元素偏移量]
  3. 判断元素是否超出s的最长长度范围。

程序示例:
C#版本,简洁了许多。

class Program
{
    //Z字型
    public static string Convert(string s, int numRows)
    {
        if (s.Length < 2 || numRows == 1)
        {
            return s;
        }

        char[] result = new char[s.Length];
        //一组V型元素个数
        int pattern = numRows + (numRows - 2);
        //每个V型的起始地址=c-r
        //对于首行、末行元素都是r + pattern*n
        //对于中间行,r行,V型组第一个元素对应的是s[r + pattern*n]
        //对于中间行,r行,V型组第二个元素对应的是s[(c-r)+(pattern-r)]=s[起始元素+偏移量]

        int pos = 0;
        for (int r = 0; r < numRows; r++)
        {
            for (int c = r; c < s.Length; c+=pattern)
            {
                result[pos++] = s[c];

                if (r!=0 && r!=numRows-1 && ((c-r)+(pattern-r)<s.Length))
                {
                    result[pos++] = s[(c - r) + (pattern - r)];
                }
            }
        }

        return new string(result);
    }

    static void Main(string[] args)
    {
        string str = "ABCDE";
        int rows = 4;
        string result = Convert(str, rows);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值