【力扣刷题记6】——《Z 字形变换》

183 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一、题目描述:

  1. Z 字形变换-难度中等

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

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

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 示例 3:

输入:s = "A", numRows = 1 输出:"A"

提示:

1 <= s.length <= 1000 s 由英文字母(小写和大写)、',' 和 '.' 组成 1 <= numRows <= 1000

二、题目和思路分析:

这个题目我反反复复看三遍才看懂,竖形的Z,要先由上到下,再由下向上排,最后横着取。

题目是看懂了,但是做法想来想去是毫无思路啊!

再想想,规律肯定是有的,每一列的长度是numRows,在理想长度下,奇数列长度是numRows,偶数列的长度是numRows-2,奇数行是s[0],s[6],s[12],s[18],每一行的长度是s[(4-n)*n] ......

越想越乱,我还是把下标列出来试试,于是我打了半天字,终于把下标打出来了:

image.png

看着下标我又开始了分析:

第一行的下标规律是 (n+n-2) * (row-1), 第二行的下标规律是 ....

啊啊啊啊啊啊,为什么会有这种题!

IMG_20220319_194010.jpg

我还在纸上列了一页纸来分析,好难!

大概是我的思路不对,虽然知道是有规律的,但是就这么看着找规律总是困难的,我还是换个想法吧。

如果顺着题目来列,把每一行当成一个数组,那么就需要三步:

  1. 声明numRows个空数组

  2. 按顺序往数组添加值

  3. 数组合并,转字符串

能不能根据这三步来实现呢?

能!

首先把numRows个空数组放到一个对象中,然后遍历字符串,判断正序or倒序,向对应数组内添加元素,最后遍历存放数组的对象,合并数组,转字符串即可。

为了避免出错,我每一行都写了注释,一遍通过,大功告成!

三、代码:

代码实现如下:

/**
 * @param {string} s
 * @param {number} numRows
 * @return {string}
 */
var convert = function(s, numRows) {
    // 声明numRows个空数组
    // 按顺序往数组添加值
    // 数组合并
    let obj = {
        arr1: []
    }
    let i = 1
    while(i <= numRows){
        obj['arr'+i] = []
        i++
    }
    let j = 1 // 当前轮候到的数组
    let sort = true // 正序
    for(let i = 0; i < s.length; i++){
        obj['arr'+j].push(s[i]) // 向当前轮候到的数组添加值
        if(j == 1) sort = true // 当前操作的数组是第一个,则继续向下
        if(j == numRows) sort = false // 当前操作的数组是最后一个,则向上操作
        if(sort){ // 向下操作
            if(++j>numRows) { // 如果向下操作时,下次轮候的数组超出最后一个数组外,则将轮候数组改为倒数第二个,且改为向上操作
                j = j-2
                sort = false
            }
        }else{ // 向上操作
            if(--j<1){ // 如果向上操作时,下次轮候的数组超出第一个数组外,则将轮候的数组改为第二个,且改为向下操作
                j = 1
                sort = true
            }
        }
    }
    let arr = []
    for(key in obj){
        arr = arr.concat(obj[key])
    }
    return arr.join('')
};

四、总结:

这道题看起来比较奇怪,对就是奇怪,因为我一开始怎么也没想起来该怎么做才好,最开始的找规律做法翻来覆去也不对,最后才发现可以让代码顺着题目意思去跑,不必非要去想它的规律。

不过这种做法应该没有找规律来的简单快捷,能看出规律的大概都是些比较聪明的人吧!

加油吧!

image.png