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] ZigZag Converesion 之字型转换字符串的更多相关文章

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

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

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

    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/300 Z字型变换 py

    目录 题目说明 方法一:利用flag 题目说明 方法一:利用flag 简单来说就是利用flag来表示方向,真的神来之笔. class Solution: def convert(self, s: st ...

  5. 281. Zigzag Iterator z字型遍历

    [抄题]: Given two 1d vectors, implement an iterator to return their elements alternately. Example: Inp ...

  6. 剑指offer从上往下打印二叉树 、leetcode102. Binary Tree Level Order Traversal(即剑指把二叉树打印成多行、层序打印)、107. Binary Tree Level Order Traversal II 、103. Binary Tree Zigzag Level Order Traversal(剑指之字型打印)

    从上往下打印二叉树这个是不分行的,用一个队列就可以实现 class Solution { public: vector<int> PrintFromTopToBottom(TreeNode ...

  7. 算法:Z字型(Zigzag)编排

    问题:给定 n 行和 m 列的二维数组矩阵.如图所示,以 ZIG-ZAG 方式打印此矩阵. 从对称的角度来看,通过反复施加滑行反射可以从简单的图案如线段产生规则的之字形. 主要思想:算法从(0, 0) ...

  8. lintcode:Matrix Zigzag Traversal 矩阵的之字型遍历

    题目: 矩阵的之字型遍历 给你一个包含 m x n 个元素的矩阵 (m 行, n 列), 求该矩阵的之字型遍历. 样例 对于如下矩阵: [ [1, 2, 3, 4], [5, 6, 7, 8], [9 ...

  9. PHP中IP地址与整型数字互相转换详解

    这篇文章主要介绍了PHP中IP地址与整型数字互相转换详解,本文介绍了使用PHP函数ip2long与long2ip的使用,以及它们的BUG介绍,最后给出自己写的两个算法,需要的朋友可以参考下 IP转换成 ...

随机推荐

  1. Java中的泛型 (上) - 基本概念和原理

    本节我们主要来介绍泛型的基本概念和原理 后续章节我们会介绍各种容器类,容器类可以说是日常程序开发中天天用到的,没有容器类,难以想象能开发什么真正有用的程序.而容器类是基于泛型的,不理解泛型,我们就难以 ...

  2. 深入理解脚本化CSS系列第二篇——查询计算样式

    × 目录 [1]getComputedStyle [2]注意事项 [3]currentStyle[4]IE 前面的话 元素的渲染结果是多个CSS样式博弈后的最终结果,这也是CSS中的C(cascade ...

  3. 【转】基于.NET平台常用的框架整理

    自从学习.NET以来,优雅的编程风格,极度简单的可扩展性,足够强大开发工具,极小的学习曲线,让我对这个平台产生了浓厚的兴趣,在工作和学习中也积累 了一些开源的组件,就目前想到的先整理于此,如果再想到, ...

  4. Live555流媒体服务器编译(Windows下)

    最近在回顾之前做过的相关项目,其中包括live555流媒体服务器相关,今天先把live555开源框架在Windows下的编译方法记录一下. live555是一套使用使用开放的标准协议(RTP/RTCP ...

  5. 【译】Core Java Questions and Answers【1-33】

    前言 译文链接:http://www.journaldev.com/2366/core-java-interview-questions-and-answers Java 8有哪些重要的特性 Java ...

  6. 用大白话聊聊JavaSE -- 如何理解Java Bean(一)

    首先,在开始本章之前,先说一个总的概念:所谓的Java Bean,就是一个java类,编译后成为了一个后缀名是 .class的文件.这就是Java Bean,很多初学者,包括当年的我自己,总是被这些专 ...

  7. Android 手机卫士3--设置中心

    1.要点击九宫格中的条目,需要注册点击事件 // 注册九宫格单个条目的点击事件 gv_home.setOnItemClickListener(new OnItemClickListener() { / ...

  8. querySelectorAll 方法相比 getElementsBy 系列方法区别

    最近有人问到querySelectorAll 方法相比 getElementsBy 系列方法区别,一时没想起来说些什么,今天查下文档,总结一下它们的区别,以便自己理解. 1. W3C 标准queryS ...

  9. Sqlite 存储自定义对象

    在iOS中如果想保存自定义对象,要让自定义对象实现NSCoding接口并实现方法-(id)initWithCoder:(NSCoder *)coder和-(void)encodeWithCoder:( ...

  10. 整理分享原生态mac AndroidStudio的快捷键

    使用AndroidStudio开发半年了,一路爬坑至今,刚由Windows转mac一个星期.通过查些资料和自己摸索,记录一些常用的快捷键,犹豫个人不喜欢改快捷键,所以都是原生的.特此分享给大家!欢迎补 ...