斜杠字符串变躺平

114 阅读1分钟

力扣6:

将一个给定字符串 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"

Thinking:

我们模仿题意将原始字符串转为目标字符串时:

1、首先我们从上往下,从左到右将原始字符串展开

2、我们再从左到右,从上往下开始将展开字符串生成目标串

那我们就可以想到一个问题了

我们如果将每个字符确定在哪一行就可以了

其次明确N字形的周期T=numRows+numRows-2;

即一个|+/构成一个周期;

一个| = numRows,

一个/ = numRows-2[每次都缺少了头尾字符]


//行数和行数的每个字符映射
Map<Integer,List<Character>> map = new HashMap();

string convert(string s, int numRows){
    //numRows==1,直接返回即可
    if(numRows==1){
        return s; 
    }
    int count = 0; int T = 2*numRows-2;int maxrow = numRows-1;
    for(int i = 0;i<s.length();i++,count++){
        if(count==T){
            count=0;
            maxrow = numRows-1;
        }
        
        if(count<numRows){
            //将每一行的字符都添加到同一个集合中
            map.computeIfAbsent(count,x->new ArrayList<>()).add(s.charAt(i));
        }else if(count<T){
            map.computeIfAbsent(--maxrow,x->new ArrayList<>()).add(s.charAt(i));
        }
    }
    //遍历map,构造目标字符串
   int min = 0;
   StringBuilder res = new StringBuilder();
   //是否包含该行
    while (map.containsKey(min)){
        //获取该行的字符集合转为数组
        Character[] tempchar = map.get(min++).toArray(new Character[0]);
        for (char e:tempchar){
             res.append(e);
         }
    }
    return res.toString();
}