LeetCode系列之【6.Z字形变换】C++ 每天一道leetcode!

目录(快速导航)

题目描述

视频讲解  https://www.bilibili.com/video/av65798417/

思路

代码


题目描述:

题目链接:https://leetcode-cn.com/problems/zigzag-conversion/

将一个给定字符串根据给定的行数,以从上往下、从左到右进行 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);

 

视频讲解

https://www.bilibili.com/video/av65798417/

 

思路:

看到这道题,首先想到的就是找规律,只要从每一个行的角度出发,找到每一行中连接字符在字符串中出现的位置的规律,那么就可以解决这个问题。

首先使用数字标示字符串的下标如下,按照从上到下,从左到右标示:

0     6       12
1   5 7    11 13
2 4   8 10    14
3     9       15    

可以发现如下规律:

  1. z字形的行数已知,并且第i行的开头字符为s[i];(ps:i从0开始,即第0行为S[0]) =》 所以我们从每一行出发,把每一行的字符拼成该行的字符串,之后再把所有行的字符串连接起来,不就ok了,现在找每一行内字符下标的规律。
  2. 第0行与最后一行的规律一致;以第一行为例子,我们称0到6,6到12为一个gap,并且0为gap头,6为gap尾,那么第0行了最后一行的gap大小都为6,所以这两行,就特别简单,若行数为numRows,那么gap大小为:2*(numRows-1),为什么是这个呢?观察从0到6的过程中,1和4在第1行,2和5在第二行,3独自在最后一行,但是加上6本身的位置,就看成3和6一个组,所以说从第0行开始往下,都是以2个字符为一组的形式出现了行高numRows-1次,那就是这个规律了;
  3. 中间行的规律一致;中间行对比第0行与最后一行,在gap大小上都一致,如1到7,gap为6。只是说他们在gap间多了一个字符,计为middle,如4。并且这个字符下标的规律和所在行高有关,如果在第i 行,其middle的下标为:gap头+2*(numRows-i-1)。这个类似的,只是将视角放过来,从上往下看,如第1行的1和5的gap之间有一个middle为5,那么此时1为gap头,向下2和4为一组,3和5为一组,共2组,4个元素,符合2*(numRows-i-1) = 2*(4-1-1)=4,那么niddle为1+4=5。

好了,每一个gap的规律都一致,所以我们只需要一个for循环,遍历每一行,对于第0行和最后一行,使用规律2,不停的迭代gap,直到超过S的size;对于中间行,同样使用规律2迭代gap,只是在每一个gap中,使用规律3计算middle即可。

 

代码:

class Solution {
public:
    string convert(string s, int numRows) {
    // 特殊情况
    if(numRows == 1)
        return s;
    int gap = 2*(numRows-1);
    string out = "";
    int i=0;
    // 迭代每一行 获得每一行的拼接字符串tmp
    for (i = 0; i < numRows; ++i) {
        int j=i;
        string tmp = "";
        // 迭代直到下标超限
        while(j<s.size()){
            // 在tmp上加上这次gap的gap头
            tmp += s[j];
            // 检查是否有midlle 如果有就在tmp上加上
            int middle = j+ 2*(numRows-i-1);
            if(i!=0 && i!=(numRows-1) && middle<s.size()){
                tmp += s[middle];
            }
            // 将本次gap的gap尾 当作下次gap的gap头
            j+=gap;
        }
        // 拼接所有行的tmp
        out += tmp;
    }
      return out;
    }
};

一起加油!!刷题!!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值