6. N 字形变换

题目描述


将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “PAYPALISHIRING” 行数为 3 时,排列如下:

P   A   H   N
A P L S I I G
Y   I   R

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


比如输入字符串为 **"PAYPALISHIRING"** 行数为 **4** 时,排列如下
P     I    N
A   L S  I G
Y A   H R
P     I

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,输出:"PINALSIGYAHRPI"。


若s = "A", numRows = 1,那么输出 **"A"**

解题思路

根据题意可知,我们要遍历整个字符串,然后将其“拼装”为一个Z字型。 那么,在执行拼装操作时,其实就是一个“从上向下”,当长度达到numRow的时候,在执行反方向的“从下向上”。
那么,对于每层的元素,我们可以通过StringBuilder数组进行保存,那么对应数组存储的下标index,我们需要一个boolean变量reverse,当它为false的时候,index执行加1操作,当它为true时,index执行减1操作。当所有字符串s都遍历并存储到StringBuilder数组之后,我们再执行最后结果拼装即可。具体操作如下所示:

在这里插入图片描述

Code1

public static String convert(String s, int numRows) {
    if (numRows == 1 || s.length()<=2) return s;

    StringBuilder[] str_arr = new StringBuilder[numRows];
    for (int i = 0; i < numRows; i++) {
        str_arr[i] = new StringBuilder();
    }

    boolean flag = true; // 当flag为真时,数值升序。反之则是降序
    int index = 0;
    for (int i = 0; i < s.length(); i++) {
        str_arr[index].append(s.charAt(i));
        if (index == 0) flag = true;
        if (index == numRows-1 ) flag = false;
        index = flag ? index + 1 : index - 1;
    }

    String res = "";
    for (StringBuilder a: str_arr) {
        res += a;
    }
    return res;
}

str_arr 也可以这么定义
String[] str_arr = new String[numRows];
for (int i = 0; i < numRows; i++) {
str_arr[i] = “”;
}
那么数组里字符的拼接就可以直接加 str_arr[index] += s.charAt(i);

上述代码的核心是这个下标升序和降序的过程

int[] num_arr = new int[s.length()];
boolean flag = true; // 当flag为真时,数值升序。反之则是降序
int index = 0;
for (int i = 0; i < s.length(); i++) {
    num_arr[i] = index;
    if (index == 0) flag = true;
    if (index == numRows-1 ) flag = false;
    index = flag ? index + 1 : index - 1;
}
System.out.print(num_arr);// (14) [0, 1, 2, 3, 2, 1, 0, 1, 2, 3, 2, 1, 0, 1]

Code2

下标的升降,也可以用变量n,然后求余数来控制。

int[] num_arr = new int[s.length()];
int n = 2 * numRows - 2;
int index;
for (int i = 0; i < s.length(); i++) {
    index = i % n;
    if (index >= n - index) {
        num_arr[i] = n - index;
    } else {
        num_arr[i] = index;
    }
}
System.out.print(num_arr);// (14) [0, 1, 2, 3, 2, 1, 0, 1, 2, 3, 2, 1, 0, 1]

Java代码就不写了,这回改用python。不为别的,就为简洁。

def convert(s, numRows):
    if numRows == 1: return s
    res, n = [''] * numRows, 2 * numRows - 2

    for i, c in enumerate(s):
        res[min(idx := i % n, n - idx)] += c
    
    return ''.join(res)

Code3

核心算法,还是熟悉的样子

int[] num_arr = new int[s.length()];
int index;
for(int i=0;i<s.length();i++){
    index = i % (numRows*2-2);
    if(index >= numRows) index=(numRows-1)-(index-numRows+1);
    num_arr[i] = index;
}
System.out.print(num_arr);// (14) [0, 1, 2, 3, 2, 1, 0, 1, 2, 3, 2, 1, 0, 1]
public static String convert(String s, int numRows) {
    if (numRows == 1 || s.length()<=2) return s;

    String[] str_arr = new String[numRows];
    for (int i = 0; i < numRows; i++) {
        str_arr[i] = "";
    }

    int index;
    for(int i=0;i<s.length();i++){
        index = i%(numRows*2-2);
        if(index>=numRows) index=(numRows-1)-(index-numRows+1);
        str_arr[index]+=s.charAt(i);
    }

    String res = "";
    for (String a: str_arr) {
        res += a;
    }
    return res;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值