【LeetCode】6. ZigZag Conversion 字符串处理

本文探讨了一道字符串处理题目,即如何将输入的字符串以Z形方式输出。作者分享了自己的解题思路,并对比了一种更简洁高效的方法。通过本题的学习,读者可以更好地理解字符串处理技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概述

给出一个字符串,按格式输出。

模拟题,我的思路出现了错误,对于字符串的处理一直不能很好掌握。

虽然最后做出来了,但是时间和空间复杂度惨不忍睹。要哭出来。

看了别人的代码之后觉得自己就是一个傻逼。简直气死。

二、分析

1、我的思路

简直没得看,但是自己写的,还是说说吧。

第一眼看到这个题,以为是找规律,所以把字符串编号然后去看,规律很容易看出来,但是很难实现。因此这条路不通。

之前做PAT的时候有类似的题,把二叉树按Z字输出,那时候我用了队列和栈,因此在本题中我也尝试使用。

观察可知:

若将整个图形看做numRows层,那么偶数层使用队列,奇数层使用栈,然后组合。

因为使用队列和栈有点麻烦,因此我选择使用双端队列。

举例如下,以编号为例:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25  numRows=5

则图形如下:

1...........9..............17

2......8..10.......16.18......24

3....7....11.....15...19....23

4..6......12..14......20..22

5..........13.............21

我们将第一列存在双端队列数组t的第一行;

第二三四列存在第二行;

第五列存在第三行;

第六七八列存在第四行;

第九列存在第五行;

第十十一十二存在第六行;

如下:

12345

678

910111213

141516

1718192021

222324

第一行和最后一行,选择奇数行的头输出;

其他行,选择奇数行的头和偶数行的尾输出。

如下:

1 9 17 // 2 8 10 16 18 24......

有一点要注意,如果最后一行是奇数,则一定要让其元素个数保证是numRows-2,否则会出错。

很麻烦也很不直观,但是能做出来,也仅止于此了。

2、较好的思路

与我的恰好相反,我是按列储存,人家是按行储存。

开一个string数组,共numRows行。

类似打印的方法,一个一个往里打印,模拟整个过程。

遍历s,按列一个一个存入数组,先正着存,再反着存,很是直观,如下:

abcdefghijklmn,numRows=5;

则a存在第一行,b在第二行......e在第五行,这时正着存;

然后f在第四行,g在第三行......i在第一行,这时反着存;

最后会发现,每一行就是对应的行的顺序。

然后接在一起输出即可。

没有想到这个方法主要是由于我没有想到可以一点一点接在后面,先加后减的方法,以为很复杂就放弃了。

三、总结

字符串处理,对于这种有正有反的情况,要熟练使用加加减减,确定正确的加减转换点,问题就容易许多。

PS:代码如下:

1、我的代码

#include<deque>
class Solution {
public:
	string convert(string s, int numRows) {
        if(numRows==1)
            return s;
		deque<char> q[1000];
		int flag = 1;
		int j = 0;
		//string temp=s;
		//cout<<temp<<"\n";
		//s.erase(s.begin());
		//s.erase(s.end());
		//cout << s << "\n";
		for (int i = 0; i<s.length(); i++)
		{
			if (flag == 1)
				q[j].push_back(s[i]);
			else
				q[j].push_back(s[i]);
			if (q[j].size() == numRows&&j % 2 == 0)
			{
				j++;
				flag = 0;
			}
			if ((q[j].size() == numRows - 2) && j % 2 == 1)
			{
				j++;
				flag = 1;
			}
		}
        while(q[j].size()<numRows-2&&j%2==1)
        {
            q[j].push_back('#');
        }
		string ans;
		int _j = 0;
		while (ans.size() != s.size())
		{
			if (_j != 0 && _j != numRows)
			{
				for (int k = 0; k<=j; k++)
				{
					if (q[k].size() != 0)
					{
						if (k % 2 == 0)
						{
							ans = ans + (q[k].front());
							q[k].pop_front();
							//cout << ans << "\n";
						}
						else
						{
                            if(q[k].back()!='#')
							    ans = ans + (q[k].back());
							q[k].pop_back();
							//cout << ans << "\n";
						}
					}
					if (ans.size() == s.size())
						return ans;
				}
				_j++;
			}
			else
			{
				for (int k = 0; k<=j; k++)
				{
					if (q[k].size() != 0)
					{
						if (k % 2 == 0)
						{
							ans = ans + (q[k].front());
							q[k].pop_front();
							//cout << ans << "\n";
						}
					}
					if (ans.size() == s.size())
						return ans;
				}
				_j++;
			}
		}
		return ans;
	}
};

2、较好的代码

class Solution {
public:
	string convert(string s, int numRows) {
        if(numRows==1)
            return s;
		string t[numRows];
        for(int i=0;i<numRows;i++)
            t[i]="";
        int loc=0;
        int flag=0;
        for(int i=0;i<s.size();i++)
        {
            t[loc]+=s[i];
            if(loc==0)
                flag=0;
            if(loc==numRows-1)
                flag=1;
            if(flag==0)
                loc++;
            if(flag==1)
                loc--;
        }
        string ans="";
        for(int i=0;i<numRows;i++)
            ans+=t[i];
        return ans;
	}
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值