将一个给定字符串 s
根据给定的行数 numRows
,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 "PAYPALISHIRING"
行数为 3
时,排列如下:
P A H N A P L S I I G Y I R
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"
。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);
示例 1:
输入:s = "PAYPALISHIRING", numRows = 3 输出:"PAHNAPLSIIGYIR"
示例 2:
输入:s = "PAYPALISHIRING", numRows = 4 输出:"PINALSIGYAHRPI" 解释: P I N A L S I G Y A H R P I
示例 3:
输入:s = "A", numRows = 1 输出:"A"
提示:
1 <= s.length <= 1000
s
由英文字母(小写和大写)、','
和'.'
组成1 <= numRows <= 1000
解法
方法一:模拟
我们用一个二维数组 g来模拟 Z 字形排列的过程,其中 g[i][j]表示第 i行第 j 列的字符。初始时 i=0,另外我们定义一个方向变量 k,初始时 k=−1,表示向上走。
我们从左到右遍历字符串 s,每次遍历到一个字符 c,将其追加到 g[i]中,如果此时 i=0 或者 i=numRows−1,说明当前字符位于 Z字形排列的拐点,我们将 k 的值反转,即 k=−k。接下来,我们将 i的值更新为 i+k,即向上或向下移动一行。继续遍历下一个字符,直到遍历完字符串 s,我们返回 g中所有行拼接后的字符串即可。
时间复杂度 O(n),空间复杂度 O(n)。其中 n为字符串 s的长度。
c++
#include <string>
#include <iostream>
#include <vector>
using namespace std;
// 定义一个名为Solution的类
class Solution {
public:
// 定义成员函数convert,将输入的字符串按照指定的行数进行Z字形变换
string convert(string s, int numRows) {
// 当指定的行数为1时,直接返回原字符串
if (numRows == 1) {
return s;
}
// 创建一个长度为numRows的字符串数组g,用于存储变换后的字符
vector<string> g(numRows);
int i = 0, k = -1; // 初始化变量i和k
// 遍历输入字符串s的每个字符,按照Z字形规则将字符放入对应的行中
for (char c : s) {
g[i] += c; // 将当前字符追加到第i行中
if (i == 0 || i == numRows - 1) { // 判断是否到达折返点
k = -k; // 切换折返方向
}
i += k; // 更新当前行数
}
string ans; // 初始化结果字符串
// 将数组g中的每一行按顺序拼接到结果字符串ans中
for (auto& t : g) {
ans += t;
}
return ans; // 返回Z字形变换后的结果字符串
}
};
int main() {
Solution sol; // 创建Solution类的实例
string input_str = "PAYPALISHIRING"; // 输入字符串
int numRows = 3; // 指定的行数
string result = sol.convert(input_str, numRows); // 调用convert函数进行Z字形变换
cout << "Converted String: " << result << endl; // 打印结果
return 0;
}
C#
using System.Text;
public class Solution
{
public string Convert(string s, int numRows)
{
if (numRows == 1)
{
return s;
}
int n = s.Length;
StringBuilder[] g = new StringBuilder[numRows];
for (int j = 0; j < numRows; ++j)
{
g[j] = new StringBuilder();
}
int i = 0, k = -1;
foreach (char c in s.ToCharArray())
{
g[i].Append(c);
if (i == 0 || i == numRows - 1)
{
k = -k;
}
i += k;
}
StringBuilder ans = new StringBuilder();
foreach (StringBuilder t in g)
{
ans.Append(t);
}
return ans.ToString();
}
public static void Main()
{
Solution solution= new Solution();
string input = "PAYPALISHIRING";
string result = solution.Convert(input, 3);
Console.WriteLine("Converted String: {0}",result);
}
}
Python
from typing import ChainMap
class Solution:
def convert(self, s: str, numRows: int) -> str:
if numRows == 1:
return s
group = 2 * numRows - 2
ans = []
for i in range(1, numRows + 1):
interval = group if i == numRows else 2 * numRows - 2 * i
idx = i - 1
while idx < len(s):
ans.append(s[idx])
idx += interval
interval = group - interval
if interval == 0:
interval = group
return ''.join(ans)
solution = Solution()
result = solution.convert("PAYPALISHIRING", 3)
print("Converted String:", result)
Java
import java.util.Arrays;
class Solution {
public String convert(String s, int numRows) {
if (numRows == 1) {
return s;
}
StringBuilder[] g = new StringBuilder[numRows];
Arrays.setAll(g, k -> new StringBuilder());
int i = 0, k = -1;
for (char c : s.toCharArray()) {
g[i].append(c);
if (i == 0 || i == numRows - 1) {
k = -k;
}
i += k;
}
return String.join("", g);
}
public static void main(String[] args) {
Solution sol = new Solution(); // 创建Solution类的实例
String input_str = "PAYPALISHIRING"; // 输入字符串
String result = sol.convert(input_str,3);
System.out.println("Converted String: " + result); // 打印结果
}
}