首页 > 其他 > 详细

Z 字形变换

时间:2020-06-05 16:29:45      阅读:26      评论:0      收藏:0      [点我收藏+]

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

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

L   C   I   R
E T O E S I I G
E   D   H   N

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

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

string convert(string s, int numRows);

示例 1:

输入: s = "LEETCODEISHIRING", numRows = 3
输出: "LCIRETOESIIGEDHN"

示例 2:

输入: s = "LEETCODEISHIRING", numRows = 4
输出: "LDREOEIIECIHNTSG"
解释:

L     D     R
E   O E   I I
E C   I H   N
T     S     G

方法一:按行排序

思路

通过从左向右迭代字符串,我们可以轻松地确定字符位于 Z 字形图案中的哪一行。

算法

我们可以使用 min(numRows,len(s))\text{min}( \text{numRows}, \text{len}(s)) 个列表来表示 Z 字形图案中的非空行。

从左到右迭代 ss,将每个字符添加到合适的行。可以使用当前行和当前方向这两个变量对合适的行进行跟踪。

只有当我们向上移动到最上面的行或向下移动到最下面的行时,当前方向才会发生改变。

class Solution {
public:
    string convert(string s, int numRows) {
    <span class="hljs-keyword">if</span> (numRows == <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> s;

    <span class="hljs-function"><span class="hljs-built_in">vector</span>&lt;<span class="hljs-built_in">string</span>&gt; <span class="hljs-title">rows</span><span class="hljs-params">(min(numRows, <span class="hljs-keyword">int</span>(s.size())))</span></span>;
    <span class="hljs-keyword">int</span> curRow = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">bool</span> goingDown = <span class="hljs-literal">false</span>;

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">char</span> c : s) {
        rows[curRow] += c;
        <span class="hljs-keyword">if</span> (curRow == <span class="hljs-number">0</span> || curRow == numRows - <span class="hljs-number">1</span>) goingDown = !goingDown;
        curRow += goingDown ? <span class="hljs-number">1</span> : <span class="hljs-number">-1</span>;
    }

    <span class="hljs-built_in">string</span> ret;
    <span class="hljs-keyword">for</span> (<span class="hljs-built_in">string</span> row : rows) ret += row;
    <span class="hljs-keyword">return</span> ret;
}

};


class Solution {
public String convert(String s, int numRows) {

    <span class="hljs-keyword">if</span> (numRows == <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> s;

    List&lt;StringBuilder&gt; rows = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; Math.min(numRows, s.length()); i++)
        rows.add(<span class="hljs-keyword">new</span> StringBuilder());

    <span class="hljs-keyword">int</span> curRow = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">boolean</span> goingDown = <span class="hljs-keyword">false</span>;

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">char</span> c : s.toCharArray()) {
        rows.get(curRow).append(c);
        <span class="hljs-keyword">if</span> (curRow == <span class="hljs-number">0</span> || curRow == numRows - <span class="hljs-number">1</span>) goingDown = !goingDown;
        curRow += goingDown ? <span class="hljs-number">1</span> : -<span class="hljs-number">1</span>;
    }

    StringBuilder ret = <span class="hljs-keyword">new</span> StringBuilder();
    <span class="hljs-keyword">for</span> (StringBuilder row : rows) ret.append(row);
    <span class="hljs-keyword">return</span> ret.toString();
}

}

复杂度分析

  • 时间复杂度:O(n)O(n),其中 n==len(s)n == \text{len}(s)
  • 空间复杂度:O(n)O(n)

方法二:按行访问

思路

按照与逐行读取 Z 字形图案相同的顺序访问字符串。

算法

首先访问 行 0 中的所有字符,接着访问 行 1,然后 行 2,依此类推...

对于所有整数 kk

  • 00 中的字符位于索引 k??(2?numRows?2)k \; (2 \cdot \text{numRows} - 2) 处;
  • numRows?1\text{numRows}-1 中的字符位于索引 k??(2?numRows?2)+numRows?1k \; (2 \cdot \text{numRows} - 2) + \text{numRows} - 1 处;
  • 内部的 行 ii 中的字符位于索引 k??(2?numRows?2)+ik \; (2 \cdot \text{numRows}-2)+i 以及 (k+1)(2?numRows?2)?i(k+1)(2 \cdot \text{numRows}-2)- i 处;
class Solution {
public:
    string convert(string s, int numRows) {
    <span class="hljs-keyword">if</span> (numRows == <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> s;

    <span class="hljs-built_in">string</span> ret;
    <span class="hljs-keyword">int</span> n = s.size();
    <span class="hljs-keyword">int</span> cycleLen = <span class="hljs-number">2</span> * numRows - <span class="hljs-number">2</span>;

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; numRows; i++) {
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>; j + i &lt; n; j += cycleLen) {
            ret += s[j + i];
            <span class="hljs-keyword">if</span> (i != <span class="hljs-number">0</span> &amp;&amp; i != numRows - <span class="hljs-number">1</span> &amp;&amp; j + cycleLen - i &lt; n)
                ret += s[j + cycleLen - i];
        }
    }
    <span class="hljs-keyword">return</span> ret;
}

};


class Solution {
public String convert(String s, int numRows) {

    <span class="hljs-keyword">if</span> (numRows == <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> s;

    StringBuilder ret = <span class="hljs-keyword">new</span> StringBuilder();
    <span class="hljs-keyword">int</span> n = s.length();
    <span class="hljs-keyword">int</span> cycleLen = <span class="hljs-number">2</span> * numRows - <span class="hljs-number">2</span>;

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; numRows; i++) {
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>; j + i &lt; n; j += cycleLen) {
            ret.append(s.charAt(j + i));
            <span class="hljs-keyword">if</span> (i != <span class="hljs-number">0</span> &amp;&amp; i != numRows - <span class="hljs-number">1</span> &amp;&amp; j + cycleLen - i &lt; n)
                ret.append(s.charAt(j + cycleLen - i));
        }
    }
    <span class="hljs-keyword">return</span> ret.toString();
}

}

复杂度分析

  • 时间复杂度:O(n)O(n),其中 n==len(s)n == \text{len}(s)。每个索引被访问一次。
  • 空间复杂度:O(n)O(n)。对于 C++ 实现,如果返回字符串不被视为额外空间,则复杂度为 O(1)O(1)

Z 字形变换

原文:https://www.cnblogs.com/leetcodetijie/p/13049800.html

(0)
(0)
   
举报
评论 一句话评论(0
分享档案
最新文章
教程昨日排行
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!