leetcode6.Z字形变换
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 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
我的解法为:利用二维数组找出规律,我的思考是先得计算出至少多少列,然后根据规律,把字符填到二维数组中去,最后再挨个挨个读出来,这种方法比较复杂,并且耗费的内存与时间都很多,具体代码为:
class Solution {
public String convert(String s, int numRows) {
if(s == null || s.length() == 0 || numRows <= 0){
return "";
}
if(numRows == 1 || s.length() == 1)return s;
String sstr = "";
int i,j,t = 0, m, n, p, r;
char[] str = s.toCharArray();
m = s.length()/(2 * numRows - 2);
p = s.length() % (2 * numRows - 2);
if(p <= numRows){
n = m*(numRows - 1);
if(p > 0) n = n + 1;
}else{
n = m*(numRows - 1) + p - numRows + 1;
}
char[][] array = new char[numRows][n];
for (j = 0; t < s.length(); j++) {
for (i = 0; i < numRows && t < s.length(); i++) {
if (j == 0 || j%(numRows-1) == 0) {
array[i][j] = str[t];
t = t + 1;
}else{
r = t %(2*numRows - 2) == 0? t/(2*numRows - 2):t/(2*numRows - 2)+1;
if (i == r * (numRows - 1) - j) {
array[i][j] = str[t];
t = t + 1;
}
}
}
}
for( i = 0; i < numRows; i ++) {
for (j = 0; j < n; j++) {
if(array[i][j] != '\u0000')
sstr = sstr + array[i][j];
}
}
return sstr;
}
}
我在黑板墙看到一种简单的解法,他的思考是直接找出规律,利用的字符串的vector数组,可以动态存字符,并且长度可变,该方法不需要最后再对数组进行二重读取,省内存又省时间。
class Solution {
public:
string convert(string s, int numRows) {
vector<string> temp(numRows);
string res;
if(s.empty() || numRows < 1) return res;
if(numRows == 1) return s;
for(int i = 0; i < s.size(); i++){
int ans = i / (numRows-1);
int cur = i % (numRows-1);
if(ans % 2 == 0){ //结果为偶数或0
temp[cur].push_back(s[i]); //按余数正序保存
}
if(ans % 2 != 0){ //结果为奇数
temp[numRows-cur-1].push_back(s[i]); //按余数倒序保存
}
}
for(int i = 0; i < temp.size(); i++){
res += temp[i];
}
return res;
}
};