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

这道题刚开始看了半天没看懂是咋样变换的,上网查了些资料,终于搞懂了,就是要把字符串摆成一个之字型的,比如有一个字符串 "0123456789ABCDEF",转为 zigzag 如下所示:

当 n = 2 时:

0 2 4 6 8 A C E

1 3 5 7 9 B D F

当 n = 3 时:

0   4    8     C

1 5 9 B D F

2    6   A     E

当 n = 4 时:

0     6        C

1   7   B  D

2   8 A    E

3      9       F

可以发现,除了第一行和最后一行没有中间形成之字型的数字外,其他都有,而首位两行中相邻两个元素的 index 之差跟行数是相关的,为  2*nRows - 2, 根据这个特点,可以按顺序找到所有的黑色元素在元字符串的位置,将他们按顺序加到新字符串里面。对于红色元素出现的位置(Github 上可能无法正常显示颜色,请参见博客园上的帖子)也是有规律的,每个红色元素的位置为 j + 2 x numRows-2 - 2 x i, 其中,j为前一个黑色元素的 index,i为当前行数。 比如当 n = 4 中的那个红色5,它的位置为 1 + 2 x 4-2 - 2 x 1 = 5,为原字符串的正确位置。知道了所有黑色元素和红色元素位置的正确算法,就可以一次性的把它们按顺序都加到新的字符串里面。代码如下:

解法一:

class Solution {
public:
string convert(string s, int numRows) {
if (numRows <= ) return s;
string res;
int size = * numRows - , n = s.size();
for (int i = ; i < numRows; ++i) {
for (int j = i; j < n; j += size) {
res += s[j];
int pos = j + size - * i;
if (i != && i != numRows - && pos < n) res += s[pos];
}
}
return res;
}
};

若上面解法中的规律不是很好想的话,我们也可以用下面这种更直接的方法来做,建立一个大小为 numRows 的字符串数组,为的就是把之字形的数组整个存进去,然后再把每一行的字符拼接起来,就是想要的结果了。顺序就是按列进行遍历,首先前 numRows 个字符就是按顺序存在每行的第一个位置,然后就是 ‘之’ 字形的连接位置了,可以发现其实都是在行数区间 [1, numRows-2] 内,只要按顺序去取字符就可以了,最后把每行都拼接起来即为所求,参见代码如下:

解法二:

class Solution {
public:
string convert(string s, int numRows) {
if (numRows <= ) return s;
string res;
int i = , n = s.size();
vector<string> vec(numRows);
while (i < n) {
for (int pos = ; pos < numRows && i < n; ++pos) {
vec[pos] += s[i++];
}
for (int pos = numRows - ; pos >= && i < n; --pos) {
vec[pos] += s[i++];
}
}
for (auto &a : vec) res += a;
return res;
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/6

类似题目:

Zigzag Iterator

Binary Tree Zigzag Level Order Traversal

参考资料:

https://leetcode.com/problems/zigzag-conversion/

https://www.cnblogs.com/springfor/p/3889414.html

https://leetcode.com/problems/zigzag-conversion/discuss/3403/Easy-to-understand-Java-solution

https://leetcode.com/problems/zigzag-conversion/discuss/3417/A-10-lines-one-pass-o(n)-time-o(1)-space-accepted-solution-with-detailed-explantation

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] 6. ZigZag Conversion 之字型转换字符串的更多相关文章

  1. [LeetCode] 6. ZigZag Converesion 之字型转换字符串

    The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like ...

  2. [LeetCode] ZigZag Converesion 之字型转换字符串

    The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like ...

  3. LeetCode OJ:ZigZag Conversion(字符串的Z字型转换)

    The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like ...

  4. Leetcode 6. ZigZag Conversion(找规律,水题)

    6. ZigZag Conversion Medium The string "PAYPALISHIRING" is written in a zigzag pattern on ...

  5. LeetCode 6. ZigZag Conversion & 字符串

    ZigZag Conversion 看了三遍题目才懂,都有点怀疑自己是不是够聪明... 就是排成这个样子啦,然后从左往右逐行读取返回. 这题看起来很简单,做起来,应该也很简单. 通过位置计算行数: P ...

  6. leetcode:ZigZag Conversion 曲线转换

    Question: The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of ...

  7. LeetCode 6 ZigZag Conversion 模拟 难度:0

    https://leetcode.com/problems/zigzag-conversion/ The string "PAYPALISHIRING" is written in ...

  8. LeetCode 6 ZigZag Conversion(规律)

    题目来源:https://leetcode.com/problems/zigzag-conversion/ The string "PAYPALISHIRING" is writt ...

  9. [LeetCode][Python]ZigZag Conversion

    # -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com'https://oj.leetcode.com/problems/zigzag- ...

随机推荐

  1. linux软链接

    这是linux中一个非常重要的命令,他的功能是为某一个文件在另一个位置建立一个同步的链接,这个命令最常用的参数是-s, 具体用法是: ln -s 源文件 目标文件 当我们需要在不同的目录,用到相同的文 ...

  2. Vue.js 源码分析(三十) 高级应用 函数式组件 详解

    函数式组件比较特殊,也非常的灵活,它可以根据传入该组件的内容动态的渲染成任意想要的节点,在一些比较复杂的高级组件里用到,比如Vue-router里的<router-view>组件就是一个函 ...

  3. Chrome 手动安装.crx插件

    在网上自己下载.crx的离线插件文件.或者通过朋友打包.crx文件.打包方式可参照Chrome 打包扩展程序 方法一: 打开Chrome浏览器,地址栏输入 chrome://extensions/ 将 ...

  4. JDBC与Druid简单介绍及Druid与MyBatis连接数据库

    序言 java程序与数据建立连接,首先要从jdbc说起,然后直接上阿里认为宇宙最好的数据库连接池druid,然后再说上层程序对象与数据源映射关联关系的orm-mybatis. JDBC介绍 JDBC( ...

  5. 使用三层架构+EF添加单元测试

    在运行测试的时候抛异常了: “System.InvalidOperationException”类型的异常在 mscorlib.dll 中发生,但未在用户代码中进行处理 The Entity Fram ...

  6. 大话区块链【Blockchain】

    最近这几天区块链又粉墨登场了,新闻媒体也一直在大量报道,宣称可能要在金融界掀起一番浪潮.甚至有人说很久之前中国就出现了区块链的产物——麻将.那么区块链到底是什么,麻将和区块链又有什么关系呢? 笔者这两 ...

  7. .NET Core RabbitMQ探索(1)

    RabbitMQ可以被比作一个邮局,当你向邮局寄一封信时,邮局会保证将这封信送达你写的收件人,而RabbitMQ与邮局最主要的区别是,RabbitMQ并不真的处理信件,它处理的是二进制的数据块,它除了 ...

  8. Python 电子邮件

    从一台计算机编写邮件到对方收到邮件.假设我们自己的电子邮件地址是me@163.com,对方的电子邮件地址是friend@sina.com 我们在本地的软件上写好邮件,点击发送,邮件就发送出去了,这些电 ...

  9. NIO你真正了解多少?

    解释一下java.io.Serializable接口 类通过实现 Java.io.Serializable 接口以启用其序列化功能.未实现此接口的类将无法使其任何状态序列化或反序列化. IO操作最佳实 ...

  10. 回忆C++

    内联函数 内联函数适用于函数较为短小的情况. 内联函数存在的意义是:提高程序运行效率. 内联函数的缺点:如果一个内联函数太长且频繁调用,会导致生成的可执行程序较大. 静态链接库会被嵌入到生成的可执行程 ...