LeetCode 006. ZigZag Conversion

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

题意分析:

因为我本人是做视频编解码的,所以一听到zigzag扫描自然而然的想到了DCT变换里面的之字形扫描(如下图),但是这么验证一下题意发现不对。


题目意思的扫描书序其实是下图酱紫的。


思路一

如下图所示,字符串s是一行分配一个字符,然后再反过来。我的想法是建一个vector<string> strlist(nRows),扫描字符串,然后给每一个vector里面的string拼接上一个字符。

这样nRows的字符串都得到了,再将所有strlist里的字符串都拼接起来就得到我们的结果。算法复杂度为O(n),但是空间复杂度是需要建一个包含nRows个string的vector。


代码如下:

class Solution 
{
public:
    string convert(string s, int nRows) 
    {
		int i=0, j=0;
		string result = "";
		vector<string> strlist(nRows);
		vector<string>::iterator iter;
		bool flag = false;
		for(i=0;i<s.length();i++)
		{
			strlist[j] += s[i];
			if(0 != nRows-1)
			{
				if(!flag)
					j++;
				else
					j--;
				if(j%(nRows-1) == 0)
					flag = !flag;	
			}
		}
		for(iter=strlist.begin();iter<strlist.end();iter++)
		{
			result += *iter;		
		}
		return result;
    }
};

思路二

为了避免如上面思路那样开辟nRows个string,我们可以尝试找一下数字规律。

规律如下:

1、第一行和最后一行数据间隔是2*(nRows-1);

2、4 = 2+2*(nRows-1)-2*2;10=8+2*(nRows-1)-2*2;5=1+2*(nRows-1)-2*1;11=7+2*(nRows-1)-2*1;

从这里可以看出是有一定规律的,下图已经很清楚的将这个规律给展示出来了。

这个算法复杂度也是O(n)


上代码吧,看不懂图的请留言吧,我表示语言能力太弱,解释不了。

参考链接:http://www.myexception.cn/other/1676954.html

class Solution 
{
public:
    string convert(string s, int nRows) 
    {
    	if (nRows <= 1)
    		return s;
    
    	string result = "";
    	int i=0, j=0; //i表示行,j表示s下标,k表示result下标
    
    	int step = 2*(nRows-1);
    	for(i=0; i<nRows; i++)
    	{
    		for(j=i; j<s.length();j+=step)
    		{
    			result += s[j];
    			if(i==0 || i == nRows-1)
    				continue;
    			
    			//如果不是第一行或者最后一行,则还有一个斜线上的数据
    			int slash = j + step -2*i;
    			if(slash < s.length())
    				result += s[slash];			
    		}
    	}
    	return result;	
    }
};

最后附上Zig-zag打印的程序片段(程序来源: http://www.2cto.com/kf/201311/259392.html

void printZigzag(const string &s, int nRows)  
{  
    if(s.empty() || nRows < 1) return;  
    if (nRows == 1)  
    {  
        cout<<s<<endl;  
        return;  
    }  
   
    int zigSpan = nRows*2 - 2;  
    int zig = nRows - 2;  
    for (int i = 0; i < nRows; i++)  
    {  
        for (int j = i; j < s.length(); j+=zigSpan)  
        {  
            cout<<s[j];  
            //注意:推导出zigSpan+j-2i的数学公式,一点都不能错  
            if (i != 0 && i != nRows-1 && zigSpan+j-2*i<s.length())  
            {  
                for (int r1 = 0; r1 < zig-i; r1++)  
                {  
                    cout<<" ";  
                }  
                cout<<s[zigSpan+j-2*i];  
                for (int r2= 0; r2 < i-1; r2++)  
                {  
                    cout<<" ";  
                }  
            }  
            else 
            {  
                for (int r = 0; r < zig; r++)  
                {  
                    cout<<" ";
                }  
            }  
        }  
        cout<<endl;  
    }  
}  

打印结果展示



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值