版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址

http://blog.csdn.net/lzuacm

C#版 - Leetcode 6. Z字形变换 - 题解

Leetcode 6. ZigZag Conversion

在线提交: https://leetcode-cn.com/problems/zigzag-conversion/

题目描述


将字符串 “PAYPALISHIRING”以Z字形(Zigzag pattern)排列成给定的行数:

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


  ●  Difficulty: Medium
  • Total Accepted: 216.3K

  • Total Submissions: 779.4K

  • 相关话题 字符串


分析:

<”PAYPALISHIRING”, 3> 的返回结果中的各字符在原字符串中的位置(下标index)具体如下:

  1. s[0],s[4],s[8],s[12]           // 第1行,间隔为4 = 2⋅(3−1)" role="presentation">2⋅(3−1)2⋅(3−1)
  2. s[1],s[3],s[5],s[7],s[9],s[11],s[13]    // 第2行,间隔为2/2
  3. s[2],s[6],s[10]              // 第3行,间隔为4

numRows=4时,所返回的字符串中各字符原来的index的规律为:

第1行,间隔为6 = 2⋅(4−1)" role="presentation">2⋅(4−1)2⋅(4−1)

第2行,间隔为4/2交替

第3行,间隔为2/4交替

第4行,间隔为6

当numRows=5时,所返回的字符串中各字符原来的index规律为:



第1行,间隔为8 = 2⋅(5−1)" role="presentation">2⋅(5−1)2⋅(5−1)

第2行,间隔为6/2交替

第3行,间隔为4/4

第4行,间隔为2/6交替

第5行,间隔为8



如果觉得不够直观,可以看看另一个例子<”THISPROBLEMISAWESOME”, 4>(位置重排):

根据重排的图,有一种较直观的思路:

用一个字符串str来存储每一行中字符拼接成的字符串,最后将每行得到的字符串拼接到一起即为所求结果。另外,用booldown表示方向 - 先下后上将其记为true,否则记为false。

using System;
using System.Text;

namespace Leetcode6_Zigzag
{
    public class Solution
    {
        public string Convert(string s, int numRows)
        {
            StringBuilder sb = new StringBuilder();
            // base case
            if (s.Length == 0 || numRows <= 1)
                return s;

            // handle first row
            for (int i = 0; i < s.Length; i += (numRows - 1) * 2)
                sb.Append(s[i]);

            // handle middle rows
            for (int j = 1; j < numRows - 1; j++)
            {
                bool down = true;
                for (int i = j; i < s.Length;)  // Since the step has two possible values, so not add increase logic here.
                {
                    sb.Append(s[i]); // Add first element of current row, then add others
                    if (down) // going down
                        i += (numRows - 1 - j) * 2;
                    else // going up
                        i += 2*j;

                    down = !down; // switch direction
                }
            }

            // handle last row
            for (int i = numRows - 1; i < s.Length; i += (numRows - 1) * 2)
                sb.Append(s[i]);

            return sb.ToString();
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
                Solution sol = new Solution();
                String str = "PAYPALISHIRING";
                int numRows = 4;

                var res = sol.Convert(str, numRows);
                Console.WriteLine(res);
        }
    }
}

不过此方法的需要另外考虑方向,并对首末两行进行特殊处理(运行时间: 112 ms),我们可以考虑找更优的解法。

如果要找到更通用的下标 Index 的规律,可用下图来表示 ,分析知从蓝色格子走到绿色格子,需要 2⋅[(n−1)−(2)]" role="presentation">2⋅[(n−1)−(2)]2⋅[(n−1)−(2)]步,而从绿色格子到红色格子需要的步数是 2⋅(2)" role="presentation">2⋅(2)2⋅(2):

观察可知,假设目前在第 k行,则该行的字符在原字符串中的数字下标依次为:

  • k" role="presentation">kk
  • k+2⋅(n−1−k)" role="presentation">k+2⋅(n−1−k)k+2⋅(n−1−k)
  • k+2⋅(n−1−k)+2⋅k" role="presentation">k+2⋅(n−1−k)+2⋅kk+2⋅(n−1−k)+2⋅k
  • k+2⋅(n−1−k)+2⋅k+2⋅(n−1−k)" role="presentation">k+2⋅(n−1−k)+2⋅k+2⋅(n−1−k)k+2⋅(n−1−k)+2⋅k+2⋅(n−1−k)
  • k+2⋅(n−1−k)+2⋅k+2⋅(n−1−k)+2⋅k" role="presentation">k+2⋅(n−1−k)+2⋅k+2⋅(n−1−k)+2⋅kk+2⋅(n−1−k)+2⋅k+2⋅(n−1−k)+2⋅k

因此,通用的规律如下:

  • 当numRows=1或原字符串长度为0时,直接返回原字符串s即可,因为此时无需展开。
  • 第k行的第一个字符在原字符串中的index就是k
  • 第1行和最后1行的间隔相等,都是整个过程中最大的,取名为maxGap,其值为2⋅" role="presentation">⋅⋅numRow-2。
  • 中间的行相邻两个index的间隔数有2个,互相交替,但其和为maxGap(也可将maxGap看作每一行的周期),分别取名为gap1和gap2。对于第k行,gap1 = maxGap-2⋅k" role="presentation">2⋅k2⋅k = 2 ⋅" role="presentation">⋅⋅ (numRows - 1 - k),gap2 = maxGap-gap1 = 2⋅k" role="presentation">2⋅k2⋅k。

已AC的代码:

using System;

namespace LeetCode_6ZigZagConversion
{
    public class Solution
    {
        public string Convert(string s, int numRows)
        {
            char[] res = new char[s.Length];
            // string res = new string(' ', s.Length);
            if (s.Length == 0 || numRows <= 1)
                return s;

            int pos = 0;
            for (int i = 0; i < numRows; i++)
            {
                int gap1 = 2 * (numRows - 1 - i);
                int gap2 = 2 * i;

                int index = i;
                while (pos < s.Length)
                {
                    if (gap1 > 0)
                    {
                        if (index >= s.Length)
                            break;
                        res[pos++] = s[index];  // Add char row by row
                        index += gap1;
                    }

                    if (gap2 > 0)
                    {
                        if (index >= s.Length)
                            break;
                        res[pos++] = s[index];
                        index += gap2;
                    }
                }
            }

            return new string(res);
        }
    }

    // Testing below
    class Program
    {
        static void Main(string[] args)
        {
            Solution sol = new Solution();
            string res = sol.Convert("PAYPALISHIRING", 3);
            Console.WriteLine(res);
        }
    }
}

此方法不需记录方向,只需保证gap1在自减和gap2在自增的过程中均>0即可,且不需对首尾两行进行特殊处理。

Rank:

运行时间: 102 ms.

You are here!

Your runtime beats 100.00% of csharp submissions.

C#版[击败100.00%的提交] - Leetcode 6. Z字形变换 - 题解的更多相关文章

  1. C#版(击败100.00%的提交) - Leetcode 151. 翻转字符串里的单词 - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...

  2. C#版(击败100.00%的提交) - Leetcode 744. 寻找比目标字母大的最小字母 - 题解

    C#版 - Leetcode 744. 寻找比目标字母大的最小字母 - 题解 744.Find Smallest Letter Greater Than Target 在线提交: https://le ...

  3. C#版(击败100.00%的提交) - Leetcode 372. 超级次方 - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. Leetcod ...

  4. Java实现 LeetCode 6 Z字形变换

    6. Z 字形变换 将一个给定字符串根据给定的行数,以从上往下.从左到右进行 Z 字形排列. 比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下: L ...

  5. C#版[击败99.69%的提交] - Leetcode 242. 有效的同构异形词 - 题解

    C#版 - Leetcode 242. 有效的同构异形词 - 题解 Leetcode 242.Valid Anagram 在线提交: https://leetcode.com/problems/val ...

  6. C#版(击败97.76%的提交) - Leetcode 557. 反转字符串中的单词 III - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. Leetcod ...

  7. [LeetCode] 6. Z 字形变换

    题目链接:(https://leetcode-cn.com/problems/zigzag-conversion/) 题目描述: 将一个给定字符串根据给定的行数,以从上往下.从左到右进行 Z 字形排列 ...

  8. LeetCode 6. Z字形变换(ZigZag Conversion)

    题目描述 将字符串 "PAYPALISHIRING" 以Z字形排列成给定的行数: P A H N A P L S I I G Y I R 之后从左往右,逐行读取字符:"P ...

  9. Leetcode(6)Z字形变换

    Leetcode(6)Z字形变换 [题目表述]: 将一个给定字符串根据给定的行数,以从上往下.从左到右进行 Z 字形排列. 比如输入字符串为 "LEETCODEISHIRING" ...

随机推荐

  1. call_user_func 与call_user_func_array 的使用与区别

    1 call_user_func 的使用 1)使用方法直接传递值 function nowamagic($a,$b){ echo $a; echo $b; } call_user_func('nowa ...

  2. Linux-day1-pdf课件

    1.掌握Linux目录结构  2.掌握基础文件操作指令 3.vim常用操作命令 4.Linux用户和组

  3. Linux-网络综合实验

    题目要求:财务部门有俩台机器acc-1和acc-2,it部门有俩台机器it-2和it-2,要求acc机器互通,it机器互通,财务部和it部机器通过路由器互通

  4. PBRT笔记(14)——光线传播2:体积渲染

    传输公式 传输方程是控制光线在吸收.发射和散射辐射的介质中的行为的基本方程.它解释了第11章中描述的所有体积散射过程--吸收.发射和内.外散射.并给出了一个描述环境中辐射分布的方程.光传输方程实际上是 ...

  5. SpringCloud教程 | 第八篇: 消息总线(Spring Cloud Bus)

    一.安装rabbitmq 二.pom父文件 <?xml version="1.0" encoding="UTF-8"?> <project x ...

  6. Linux网络文件系统的实现与调试

    NFS协议 NFS (网络文件系统)不是传统意义上的文件系统,而是访问远程文件系统的网络协议.整个NFS服务的TCP/IP协议栈如下图所示,NFS是应用层协议,表示层是XDR,会话层是RPC,传输层同 ...

  7. Do-Now—团队冲刺博客一(领航篇)

    Do Now -- 团队冲刺博客一(领航篇) 团队博客总目录:团队作业第一周 团队作业第二周 Do Now -- 团队冲刺博客一 领航目标 ① 各个成员在 Alpha 阶段认领的任务 ② 明日各个成员 ...

  8. html2canvas在Vue项目踩坑-生成图片偏移不完整

    背景 最近做一个Vue项目需求是用户长按保存图片,页面的数据是根据不同id动态生成的,页面渲染完生成内容图片让用户长按保存的时候,把整个页面都保存起来. 在项目遇到的坑是图片能生成,可是生成的图片总是 ...

  9. java的3大特性

    java的3大特性 1.继承: * 继承是从已有类得到继承信息创建新类的过程. * 提供继承信息的类被称为父类(超类.基类):得到继承信息的类被称为子类(派生类). * 继承让变化中的软件系统有定的延 ...

  10. 旧项目Makefile 迁移CMake的一种方法:include Makefile

    有些c++旧项目用Makefile,要迁移CMake的时候非常痛苦,有些像static pattern的语法和make自带命令 cmake要重写一套非常的麻烦. 因此这里用trick的方法实现了一种i ...