当前位置:首页 > 嵌入式 > 嵌入式客栈
[导读]今天是小浩算法“365刷题计划”第81天。为大家分享一道让很多人头疼过的题目 - Z字形变化。 01 PART Z 字形变换 额。。。不知道是不是我瞎,明明是N么(杠精勿扰,只是说说) 第6题:将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。


今天是小浩算法“365刷题计划”第81天。为大家分享一道让很多人头疼过的题目 - Z字形变化。



01
PART
Z 字形变换

额。。。不知道是不是我瞎,明明是N么(杠精勿扰,只是说说)

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



02
PART
题目分析

这是我比较推崇的一道“小学题目”,因为其没有任何复杂的思维逻辑,只需要按部就班,就可以顺利解答。难的是,按部就班的过程里,却极其容易出错。。

因为最终目的是变换字符串的顺序,并且题中也没有限制说不可用额外空间,所以我们秉承不重复造轮子的原则,想办法利用某种结构对原字符串做文章。


假若我们采用示例2的数据来进行分析,输入字符串 s 为  "LEETCODEISHIRING", numRows 为 4 ,画成图大概长这样:



重点来了,我们的目标是按行打印,那总得有个东西来存储每行的数据吧?因为只需要存储每行的数据,那是不是用个数组就可以了。(当然,你硬说搞个map来存也没啥毛病,就是有点闲得蛋疼)


问题来了,那数组设置多大呢?自然是有多少行我们就设置多大呗,换句话说,numRows多大,我们的数组就设置多大。画成图大概就是下面这个样子:



存储的容器有了,原字符串也列出来是啥样了,现在嘎哈?自然就是把原字符串放到容器里咯。怎么放?根据 numRows 的大小来回进行放置即可(即从0到n-1,再从n-1到0)。啥意思:


(不需要我再继续画下去了吧)


上面的图长得不得了,但是观察我们能看出来,每 2n-2 即为一个周期到了这里,应该没有人会质疑这是一道小学题目了吧。。。把所有的字符串放完之后,大概就是下面这个样子:



最后一步,咱们让这个数组排排坐,就可以开始吃果果:



如果看不清楚,不如这样:



根据分析,得出代码(好久没翻go的牌子了):


 1//GO
2func convert(s string, numRows int) string {
3    if numRows == 1{
4        return s
5    }
6    var b = []rune(s)
7    var res = make([]string, numRows)
8    var length = len(b)
9    var period = numRows * 2 - 2
10    for i := 0 ;i < length; i ++ {
11        var mod = i % period
12        if mod < numRows {
13            res[mod] += string(b[i])
14        } else {
15            res[period - mod] += string(b[i])
16        }
17    }
18    return strings.Join(res, "")
19}



上面的代码要强调两点:
第一:用了一个rune,这个其实是go里的用法,用来处理unicode或utf-8字符而已,并没有什么特别的。

第二:12-15行的意思是,在周期内,正着走 numRows-1 下,剩余的反着走。(也就是上面那个长长的图)


为了照顾Java的小伙伴,再给出一个Java版本的:


 1//java
2class Solution {
3    public static String convert(String s, int numRows) {
4        if (numRows == 1return s;
5        String[] arr = new String[numRows];
6        Arrays.fill(arr, "");
7        char[] chars = s.toCharArray();
8        int len = chars.length;
9        int period = numRows * 2 - 2;
10        for (int i = 0; i < len; i++) {
11            int mod = i % period;
12            if (mod < numRows) {
13                arr[mod] += chars[i];
14            } else {
15                arr[period - mod] += String.valueOf(chars[i]);
16            }
17        }
18        StringBuilder res = new StringBuilder();
19        for (String ch : arr) {
20            res.append(ch);
21        }
22        return res.toString();
23    }
24}


和Go语言的示例一样,代码的关键仍然是计算轨迹的过程(10-17),这里再提供另外一种计算轨迹的方式:


 1//java
2class Solution {
3    public String convert(String s, int numRows) {
4        if (numRows == 1return s;
5        String[] arr = new String[numRows];
6        Arrays.fill(arr, "");
7        int i = 0, flag = -1;
8        for (char c : s.toCharArray()) {
9            arr[i] += c;
10            if (i == 0 || i == numRows - 1) flag = -flag;
11            i += flag;
12        }
13        StringBuilder res = new StringBuilder();
14        for (String ch : arr) {
15            res.append(ch);
16        }
17        return res.toString();
18    }
19}


通过使用一个标志位,来使轨迹回移。(本质其实是一样的)

郑重申明(读我的文章必看):

  • 本系列所有教程都不会用到复杂的语言特性,大家无须担心没有学过相关语法,算法思想才是最重要的!

  • 作为学术文章,虽然风格可以风趣,但严谨,我是认真的。本文所有代码均在leetcode进行过测试运行。



03
PART
结尾

这道题目的意义在于考察coding的能力,本身的思维过程并不复杂。有的同学一看这种题目,就想通过二维数组来进行计算,殊不知已经落入了题目的陷阱(不信你试试,二维数组出错率一定远胜一维数组)。当然,本题也是可以不借助额外空间来进行实现的,核心的逻辑完全相同,建议大家下去自己动手练习一下。


今天的题目到这里就结束了,如果想看其他面试题相关内容的,可以看:


漫画:知乎面试题(旋转数组最小值Ⅰ - 基础版)

漫画:知乎面试题(旋转数组最小值Ⅱ - 进阶版)

漫画:美团面试题(TOPK:求第K个最大的元素)

漫画:腾讯面试题(面试官问我会不会修供暖器,我说没问题)

漫画:位运算技巧整理汇总+一道被嫌弃的题目


如果你问我对学习算法有什么建议,这篇文章是必看的:


漫画:呕心泣血算法指导篇(真正的干货,怒怼那些说算法没用的人)


 小浩算法,每日


关注领取《图解算法》高清版

进群的小伙伴请加右侧私人微信(备注:进群)



免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭