LeetCode: ZigZag Conversion

本文介绍了一种将字符串按Z字形排列并按行重新组合的算法,提供了两种解决方案:一种使用额外的字符串数组,另一种利用周期性规律进行优化。

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

题目
这里写图片描述
ZigZag指的是将字符串按Z字形(锯齿形)排列,如字符串“123456789”,当numRows为3时,排列顺序如下图:
这里写图片描述
题目要求我们将字符串按锯齿形排列后按行重新组合,如上面的例子,新组合的字符串为“0481357926”。

解法一:
为每一行申请一个字符串保存重新排列后的字符,数字按Z字形铺排时有两个方向,数值向下和斜向上,用布尔变量forth来保存当前方向:向下时字符串数组的下标加一,斜向上时字符串数组的下标减一。最后将每个字符串逐序想加即得到结果。需要遍历一遍给出字符串的字符,时间复杂度为o(n)。需要考虑numRow=1时的特殊情况。Accepted的代码如下:

class Solution {
public:
    string convert(string s, int numRows) {
        string results;
        string temp[10000]="";
        int currentRow=0;
        bool forth=1;//延伸的方向,1为向下

        if(numRows==1) results=s;

        else
        {
            for(int i=0;i<s.size();i++)
            {
                //向下
                if(forth)
                {
                    temp[currentRow]+=s[i];
                    currentRow++;
                    if(currentRow==numRows)
                    {
                        currentRow=currentRow-2;
                        forth=0;
                    }
                }
                //斜向上
                else
                {
                    temp[currentRow]+=s[i];
                    currentRow--;
                    if(currentRow==-1)
                    {
                        currentRow=currentRow+2;
                        forth=1;
                    }
                }
            }
            for(int i=0;i<numRows;i++)
            {
                results+=temp[i];
            }
        }
        return results;
    }
};

解法二:
解法一的效率很低,在网上看到这一题其实是有规律可循的:所有行的重复周期都为numRows*2-2,而除首行和末行外,中间的行每经一个重复周期,中间多重复一个数,重复数距本周期起始字符的距离为2*numRows-2-2* i。如:
这里写图片描述
第一行和最后一行的两个数之间相差2*3-2=4,中间一行1和5之间还插入了一个与1相差2*3-2-2*1=2的3。按这个规律,可以根据给定字符串的下标得到重排的字符串。虽然算法的时间复杂度为o(n^2),但这里的n为numRows,大大小于字符串长度,同时节省了空间复杂度。Accepted的代码如下:

class Solution {
public:
    string convert(string s, int numRows) {
        string results="";
        if (numRows==1) return s;

        int t=2*numRows-2; //循环周期  
        for(int i=0; i<numRows;i++) 
        {  
            int j=i;
            //首行和末行
            if(i==numRows-1||i==0)
            {
                while(j<s.size())
                {
                    results+=s[j];
                    j=j+t;
                }
            }
            //中间行
            else
            {
                while(j<s.size())
                {
                    results+=s[j];
                    if(j+t-2*i<s.size()) results+=s[j+t-2*i];
                    j=j+t;
                }
            }
        }  
        return results;
    }
};

可以看到效率大大提高:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值