算法日常・每日刷题--<模拟>3

6. Z 字形变换 - 力扣(LeetCode)6. Z 字形变换 - 将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:P A H NA P L S I I GY I R之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"。请你实现这个将字符串进行指定行数变换的函数:string convert(string s, int numRows); 示例 1:输入:s = "PAYPALISHIRING", numRows = 3输出:"PAHNAPLSIIGYIR"示例 2:输入:s = "PAYPALISHIRING", numRows = 4输出:"PINALSIGYAHRPI"解释:P I NA L S I GY A H RP I示例 3:输入:s = "A", numRows = 1输出:"A" 提示: * 1 <= s.length <= 1000 * s 由英文字母(小写和大写)、',' 和 '.' 组成 * 1 <= numRows <= 1000https://leetcode.cn/problems/zigzag-conversion/description/

题目描述

将一个给定字符串 s 根据给定的行数 numRows,以从上往下、从左到右进行 Z 字形排列

比如输入字符串为 "PAYPALISHIRING",行数为 3 时,排列如下:

cpp 复制代码
P   A   H   N
A P L S I I G
Y   I   R

之后,你的输出需要从左到右逐行读取,产生一个新的字符串,比如:"PAHNAPLSIIGYIR"

请你实现这个将字符串进行指定行数变换的函数:

解法:模拟找规律

我们先用下标来代替具体数字,更好的找到规律

找规律 + 按行遍历

观察 Z 字形排列,可以发现一个周期

bash 复制代码
以 numRows = 4 为例:

第0行: 0     6      12     18
第1行: 1   5 7   11 13   17
第2行: 2 4   8 10   14 16
第3行: 3     9      15

周期 d = 2 * numRows - 2 = 6

第一行和最后一行

数字的变换都是再前面一个,数字的基础上加上一个公差

第一行:kd

第n-1行:(n-1)+kd;

非第一行和最后一行

将两个两个看成一组,都是每一组相对应的位置上的数加上公差d,可以发现组的两个数相加恰好为公差

{i+kd , d-i+kd}

找到规律,我们按行开始填写即可

cpp 复制代码
#include<string>
class Solution {
public:
    string convert(string s, int numRows) {
         if (numRows == 1 || s.empty()) return s;
        //计算公差d
        int d=2*numRows-2;
        int n=s.size();
        string s1;
        int k=n/numRows+1;
       
        for(int j=0;j<k;j++)
        {   if(j*d<n)
            s1+=s[j*d];
        }
        for(int i=1;i<numRows-1;i++)
            for(int j=0;j<k;j++)
        {
            if(i+j*d<n)
            s1+=s[i+j*d];
            if(d-i+j*d<n)
            s1+=s[d-i+j*d];
        }
            for(int j=0;j<k;j++)
        {
            if(numRows-1+j*d<n)
            s1+=s[numRows-1+j*d];
        }
        return s1;
    }
};