Leetcode 6:ZigZag Conversion

原题链接:ZigZag Conversion

  一开始的思路是根据所给字符串及 Z 型串的行数计算出末元素所在的行列数,进而用二维数组来计算blabla…但算到后期发现不用这么复杂。。。而是直接去找Z 型串每行元素的下标关系。
原理如下图
在这里插入图片描述
对于给定的 z 型串,我们取 2*numRows-2为一个周期(除数)(图中红色箭头轨迹为一个周期),以字符串 s 的长度为被除数;z 型串的第一行元素所在位置除以除数,余数皆为 1,第二行元素所在位置除以除数余数,余数为 0 或 2,第 3~numRows-1 行,余数皆为 n 或 2*numRows-n,以此类推,最后一行余数为 numRows,每处理一行就将字符追加到串尾,最后既得结果。

代码如下:

string convert(string s, int numRows)
{
	auto len = s.length();
	string s1;

	if (1 == numRows || s.length() < 3)	// 特殊情况处理
		return s;
	else
	{
		if (2 == numRows)	// 行数等于2时,直接交叉赋值
		{
			for (int i = 0; i < len; i = i+2)
				s1.push_back(s.at(i));
			for (int i = 1; i < len; i = i+2)
				s1.push_back(s.at(i));

			return s1;
		}
		else 	// 行数大于2时
		{
			for (int j = 0; j < len; j++)	// 余数为 1 时
				if ((j+1) % (2*numRows-2) == 1)
					s1.push_back(s.at(j));

			for (int j = 0; j < len; j++)	// 余数为 0 或 2 时
				if ((j+1) % (2*numRows-2)==0 || (j+1) % (2*numRows-2)==2)
					s1.push_back(s.at(j));

			for (int i = 3; i < numRows; i++)	// 余数为 n 或 2r-n 时
				for (int j = 0; j < len; j++)
					if ((j+1) % (2*numRows-2)==i || (j+1) % (2*numRows-2)==2*numRows-i)
						s1.push_back(s.at(j));

			for (int j = 0; j < len; j++)	// 余数为 r 时
				if ((j+1) % (2*numRows-2)==numRows)
					s1.push_back(s.at(j));

			return s1;
		}
	}
}

复杂度

在这里插入图片描述
enmmmmm,,就是 Runtime 有点感人(:

考虑再进一步优化,上面的代码中,对 z 型串每一行元素位置遍历(即各个余数)时都是从串首到串尾逐个遍历的,但其实仔细观察上面的图会发现 z 型串每一行的元素前后位置(下标)是有关系的,这样我们就不用 j++了,而是更加智能的调整步长:

string convert(string s, int numRows)
{
	auto len = s.length();
	string s1;

	if (1 == numRows || len < 3 || numRows >= len)	// 特殊情况处理
		return s;
	else
	{
		if (2 == numRows)	// 行数等于2时,直接交叉赋值
		{
			for (int i = 0; i < len; i = i+2)
				s1.push_back(s.at(i));
			for (int i = 1; i < len; i = i+2)
				s1.push_back(s.at(i));

			return s1;
		}
		else 	// 行数大于2时
		{
			for (int j = 0; j < len; j = j+2*numRows-2)	// 余数为 1 时
				s1.push_back(s.at(j));

			for (int j = 1; j < len; )	// 余数为 0 或 2 时
			{
				if ((j+1) % (2*numRows-2)==0)
				{
					s1.push_back(s.at(j));
					j = j + 2;
					continue;
				}

				if((j+1)%(2*numRows-2) == 2)
				{
					s1.push_back(s.at(j));
					j = j+2*numRows-4;
				}
			}

			for (int i = 3; i < numRows; i++)	// 余数为 n 或 2r-n 时
				for (int j = i-1; j < len; )
				{
					if ((j+1) % (2*numRows-2)==i)
					{
						s1.push_back(s.at(j));
						j = j+2*(numRows-i+1)-2;
						continue;
					}
					if ((j+1)%(2*numRows-2) == 2*numRows-i)
					{
						s1.push_back(s.at(j));
						j = j+i*2-2;
					}
				}

			for (int j = numRows-1; j < len; j = j+2*numRows-2)	// 余数为 r 时
				s1.push_back(s.at(j));

			return s1;
		}
	}
}

复杂度

在这里插入图片描述
奥利给 !

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值