两种思路求解——ZigZag Conversion(Z 字形变换)_C++

【链接】https://leetcode-cn.com/problems/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 s, int numRows);
 

Example 1:

Input: s = "PAYPALISHIRING", numRows = 3
Output: "PAHNAPLSIIGYIR"


Example 2:

Input: s = "PAYPALISHIRING", numRows = 4
Output: "PINALSIGYAHRPI"
Explanation:
P     I    N
A   L S  I G
Y A   H R
P     I


Example 3:

Input: s = "A", numRows = 1
Output: "A"

思路

思路一:

这类题的思路是找规律,如行数为4时:

第一行:0 - 6 - 12 - 18 ... //步长6 6 6

第二行:1 - 5 - 7 - 11 - 13 ... //步长4 2 4 2

第三行:2 - 4 - 8 - 10 - 14 ... //步长2 4 2 4

第四行:3 - 9 - 15 - 21 ... //步长6 6 6

规律显而易见,当然读者可以自己多试试其他的例子来验证。其实根据"Z"字的特点我们也能直接分析出这样的规律。接下来就是将规律函数化。

  • 步长:上述例子中 无论是6 还是4,2交替还是2,4交替,都是和6相关的。那么6又是怎么和层数关联呢?根据图形"Z"来分析,每加1层就会增加2步长,那么步长即为总层数*2-2,后文称之为绝对步长。
  • 根据步长我们能很快计算第一层的所有下标。那第二层 第n层呢。第二层其实就是步长-22交替,第三层是步长步长-4,4交替。
  • 提炼公式:步长- 2*(层数-1),2*(层数-1)交替。
  • 最后一层和第一层步长一直都是绝对步长。

思路二:

设 numRows 行字符串分别为 s1 , s2,..., sn,则容易发现:按顺序遍历字符串 s 时,每个字符 c 在 ZZ 字形中对应的 行索引先从s1增大至sn,再从sn减小至s1。
​…… 如此反复。
因此,解决方案为:模拟这个行索引的变化,在遍历 s 中把每个字符填到正确的行 res[i]

算法流程: 按顺序遍历字符串 s;

  • res[i] += c: 把每个字符 c 填入对应行si;
  • i += flag: 更新当前字符 c 对应的行索引;
  • flag = - flag: 在达到 ZZ 字形转折点时,执行反向。

代码

版本一:本地运行正常,leetcode提示堆益处:

string convert(string s, int numRows) {
        int len = s.size();
        char *c  = new char[len];
        memset(c,0,len);
        //绝对步长,第一行和最后一行
        int size = numRows * 2 - 2; 
        //记算s下标
        int index; 
        //记录c下标
        int count = 0; 
        //相对步长
        int add; 
        if (numRows < 2) {
            return s;
        }
        for (int i = 0; i < numRows; i++) { //一层一层遍历
            index = i;
            add = i * 2;
            while (index < s.size()) { //超出字符串长度计算下一层
                c[count] = s[index];
                add = size - add;
                if(add == 0){
                    index +=size;
                }else{
                    index +=add;

                }
                count++;
            }
        }
        return string(c);
    }

版本二:

leetcode运行正常

    string convert(string s, int numRows) {
        if(numRows < 2) return s;
        vector<string> vec(numRows, "");
        int i = 0, flag = -1;
        for(auto c : s){
            //vec[i].append(1,c);
            vec[i] += c; 
            if(i == 0 || i == numRows-1)    flag = -flag;
            i += flag;
        }
        string res("");
        for(const auto &c : vec)   res += c;
        return res;
    }

参考

https://leetcode-cn.com/problems/zigzag-conversion/solution/zzi-xing-bian-huan-by-jyd/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

聊聊技术

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值