【Leetcode035】Z字形变换

6、Z字形变换

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

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

在这里插入图片描述

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

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

string convert(string s, int numRows);

在这里插入图片描述

方法一:按行排序

1.1 思路分析

说实话,没做出来,菜鸡一枚,看得题解,官方题解写得也不咋地,就翻了翻其他大佬的,不愧是大佬,清晰明了,通俗易懂。我再简单捋一下,然后直接上截图。

题中的意思是按照N字将字符串排开。定义一个二维数组然后保存成稀疏矩阵也是可以的,不过我们知道行数,但不知道列数。

既然没办法形成稀疏矩阵,我们只需要知道哪些字母属于哪一行也可以。从左到右遍历字符串,将每个字符向不同行分配,最后将每行的字符串起来。

在这里插入图片描述

1.2 代码实现

func convert(s string, numRows int) string {
    n := len(s)
    if numRows == 1{
        return s
    }
    rows := make([][]byte, min(numRows, n))  // 如果长度小于行数,那只需要申请n个切片即可
    for i:=0; i<len(rows); i++{
        rows[i] = make([]byte, 0)
    }

    r, flag := 0, -1
    for i:=0; i<n; i++{
        rows[r] = append(rows[r], s[i])
        if r == 0 || r == numRows-1{
            flag = -flag
        }
        r += flag
    }
    res := make([]byte, 0)
    for i:=0; i<len(rows);i++{
        res = append(res, rows[i]...)
    }
    return string(res)
}

func min(a, b int) int{
    if a < b{
        return a
    }
    return b
}

1.3 测试结果

在这里插入图片描述

1.4 复杂度

  • 时间复杂度:O(N)
  • 空间复杂度:O(N)

方法二:按行访问

2.1 思路分析

在这里插入图片描述
在这里插入图片描述

2.2 代码实现

func convert(s string, numRows int) string {
    n := len(s)
    if numRows == 1{
        return s
    }
    res := make([]byte, 0)
    step := 2*numRows-2   // 首尾两行间距
    add := 0        // 实际间距
    index := 0      // 记录s的下标
    for i:=0; i<numRows; i++{
        index = i  // 记录s的下标
        add = 2*i  // 实际间距
        for index < n{   // 如果到行尾,进入下一行
            res = append(res, s[index])
            add = step - add   // 第一次间距是step -2*i,第二次是2*i, 
            if i==0 || i==numRows-1{
                index += step
            }else{
                index += add
            }
        }
    }
    return string(res)
}

2.3 测试结果

在这里插入图片描述

2.4 复杂度

  • 时间复杂度:O(N)
  • 空间复杂度:O(N)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值