Leetcode Q6

题外话:我本来准备半小时写完程序,然后跑完步早点回去睡觉的(本来是昨晚发的。。因为一直断网。。),毕竟Q6的难度是Easy,而且看了题目的确很简单,思路也很清晰,但是我还是足足花了4个小时才通过Leetcode的测试,原因是我自己作。。。下面分析一下我是怎么作,然后作的一手好死的~哭哭

先看看原题:

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

题目貌似很长,但是实际上很简单。题目要求给出任意序列(字符串)的Z型排列,所谓Z型排列,指的是将序列按纵向“之”字形放置,即先排满一列,然后向上每列依次排至第一行,再纵向,以此类推。题目给的例子不太明显(我还花了一点时间去百度Z型排列的定义),我给一个较为清楚的例子:


分析题目发现,本题考的就是找原序列与对应Z型序列之间对应元素的位置关系,或者说“之“字形排列一个序列,其横向、纵向都满足什么样的规律。显然,本题可以将原序列的Z型排列用一个字符串数组保存下来,然后再拼接即可,这样做的时间复杂度为O(n),空间复杂度为O(nRows²),代码参考:http://write.blog.csdn.net/postedit(该文还提供了一种更加清爽的算法)

下面就是我自己作的部分了。。。

出于不知道什么次元的思维考虑,我决定直接读取原序列中元素放在Z型排列的对应位置上,不借用第三方空间。。。嗯。。于是乎,关键问题就转化为Z型排列中的索引与原序列的索引存在什么样的关系。。。而弄清这个关系,首先需要知道Z型排列的规律,包括排列周期T(排列时有多少个半”之“字)和周期的长度(半”之“字包含多少数据),当然这些都要用字符串长度和nRows表示,然后需要用这两个变量表示索引与之字形放置后构成的矩阵其行、列标之间的关系以及行、列标与原序列索引的关系。。。想到这里我已经蒙圈了。。抓狂抓狂

可既然选择了这条路,无奈之下(顺便安慰自己这样可以降低空间复杂度),我只能提笔开始写写画画,对原问题分了四种情况进行分析:

1.序列长度小于nRows,此时原序列只需纵向排列,Z型排列与原序列相同;

2.序列长度超过nRows且恰好为周期长度的整数倍,此时第一行和最后一行一定排列了T个字符,中间的nRows-2行一定排列了2T个字符,在这种情况下,又分第一行、中间行、最后一行三种情况计算Z型排列每个元素下标和原序列下标间的关系,对于中间行,又分竖直部分和倾斜部分,计算过程见代码,这里不赘述了;

3.序列长度超过nRows且不为周期长度的整数倍但余数不超过nRows,此时第一行排列了T+1个字符,中间前res-1行排列了2T+1个字符,中间后nRows-res-1行排列了2T个字符,最后一行排列了T个字符,对于中间行的两种情况,同2中分竖直和倾斜讨论,索引关系见代码;

4.序列长度超过nRows且不为周期长度的整数倍但余数超过nRows,此时第一行排列了T+1个字符,中间前2*nRows-2-res行排列了2T+1个字符,中间后res-nRows行排列了2T+2个字符,最后一行排列了T+1个字符,索引关系见代码。

呼~~~至此,总算把自己挖的坑填平了,默默扇自己两巴掌。。。

代码如下:

#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>

using namespace std;

string convert(string s, int numRows) {
	string z_string;
	int l = s.length();
	if(numRows <= 1)return s;
	if(l<=numRows)return s;
	else{
		//确定周期数和多余段长度
		int T = l/(numRows+numRows-2);
		int res = l%(numRows+numRows-2);

		for(int i = 1;i<=l;i++){
			if(res==0){
				if(i<=T)z_string += s[(i-1)*(numRows+numRows-2)];
				else {
					if(i<=T+(numRows-2)*2*T){
						if(((i-T-1)%(2*T))%2 == 0)z_string += s[((i-T-1)%(2*T))/2*(numRows+numRows-2)+(i-T-1)/(2*T)+1];//i-T再-1是为了避免值为2T时,余数和商分别为0和原值+1造成计算失误
						else z_string += s[((i-T-1)%(2*T))/2*(numRows+numRows-2)+numRows+numRows-2-(i-T-1)/(2*T)-1];
					}
					else z_string += s[(i+T-l-1)*(numRows+numRows-2)+numRows-1];
				}
			}
			else {
				if(res<numRows){
					if(i<=T+1)z_string += s[(i-1)*(numRows+numRows-2)];
					else {
						if(i<=T+1+(res-1)*(2*T+1)){
							if(((i-T-1-1)%(2*T+1))%2 == 0)z_string += s[((i-T-1-1)%(2*T+1))/2*(numRows+numRows-2)+(i-T-1-1)/(2*T+1)+1];
							else z_string += s[((i-T-1-1)%(2*T+1))/2*(numRows+numRows-2)+numRows+numRows-2-(i-T-1-1)/(2*T+1)-1];
						}
						else {
							if(i<=T+1+(res-1)*(2*T+1)+(numRows-2-res+1)*2*T){
								if(((i-T-1-(res-1)*(2*T+1)-1)%(2*T))%2==0)z_string += s[((i-T-1-(res-1)*(2*T+1)-1)%(2*T))/2*(numRows+numRows-2)+(i-T-1-(res-1)*(2*T+1)-1)/(2*T)+res];
								else z_string += s[((i-T-1-(res-1)*(2*T+1)-1)%(2*T))/2*(numRows+numRows-2)+numRows+numRows-2-(i-T-1-(res-1)*(2*T+1)-1)/(2*T)-(res-1)-1];
							}
							else z_string += s[(i+T-l-1)*(numRows+numRows-2)+numRows-1];
						}
					}
				}
				else {
					if(i<=T+1)z_string += s[(i-1)*(numRows+numRows-2)];
					else {
						if(i<=T+1+(numRows+numRows-2-res)*(2*T+1)){
							if(((i-T-1-1)%(2*T+1))%2 == 0)z_string += s[((i-T-1-1)%(2*T+1))/2*(numRows+numRows-2)+(i-T-1-1)/(2*T+1)+1];
							else z_string += s[((i-T-1-1)%(2*T+1))/2*(numRows+numRows-2)+numRows+numRows-2-(i-T-1-1)/(2*T+1)-1];
						}
						else {
							if(i<=T+1+(numRows+numRows-2-res)*(2*T+1)+(res-numRows)*(2*T+2)){
								if(((i-T-1-(numRows+numRows-2-res)*(2*T+1)-1)%(2*T+2))%2==0)z_string += s[((i-T-1-(numRows+numRows-2-res)*(2*T+1)-1)%(2*T+2))/2*(numRows+numRows-2)+(i-T-1-(numRows+numRows-2-res)*(2*T+1)-1)/(2*T+2)+numRows+numRows-2-res+1];
								else z_string += s[((i-T-1-(numRows+numRows-2-res)*(2*T+1)-1)%(2*T+2))/2*(numRows+numRows-2)+numRows+numRows-2-(i-T-1-(numRows+numRows-2-res)*(2*T+1)-1)/(2*T+2)-(numRows+numRows-2-res)-1];
							}
							else z_string += s[(i+T+1-l-1)*(numRows+numRows-2)+numRows-1];
						}
					}
				}
			}
		}
		return z_string;
	}
}



int _tmain(int argc, _TCHAR* argv[])
{
	string s = "ABCDE";
	string z_string = convert(s,4);
	cout<<"the zigzag pattern of"<<s.c_str()<<" is: "<<z_string.c_str()<<endl;
	return 0;
}
总结:

1.不作就不会死,简单问题不要复杂化;

2.就算要用极其隐晦的代数关系来表达,也要注意细心,不然问题都不知道出在哪。。。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值