题目
6. ZigZag Conversion
The string "PAYPALISHIRING"
is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)
P A H N
A P L S I I G
Y I R
And then read line by line: "PAHNAPLSIIGYIR"
Write the code that will take a string and make this conversion given a number of rows:
string convert(string s, int numRows);
Example 1:
Input: s = "PAYPALISHIRING", numRows = 3
Output: "PAHNAPLSIIGYIR"
Example 2:
Input: s = "PAYPALISHIRING", numRows = 4
Output: "PINALSIGYAHRPI"
Explanation:
P I N
A L S I G
Y A H R
P I
题意:
给定一个字符串,按照N字形重新排列,numRows表示重新排列的行数,对重新排列过的字符串行数由上往下重组一个字符串并返回。
分析:
大致可分以下两种思路:
- 按照题目要求把所给字符串s按照题目要求排列 得到结果输出,方法比较简单。见Code1
- 由于题目要求是按照N字形排列,因此可以发现其中存在一些规律,所以可以直接按照此规律一次性把排列后应在同一行的所有字符找出。例如Example2 中 P I N就可以一次性全部找出。见 Code2
Code1 & Python
class Solution:
def convert(self, s: 'str', numRows: 'int') -> 'str':
if numRows==1:return s
ans=["" for i in range(numRows)]
count, tmp = 0, -1
for ch in s:
ans[count] += ch
if count == 0 or count == numRows-1:
tmp *= -1
count += tmp
return ''.join(ans)
首先初始化numRows个空字符串,然后遍历字符串s,按照规则把当前遍历到的字符放到相应的位置。tmp每当遇到“转角”时取反,用来表示向上还是向下排列,最后直接连接ans所有元素并返回。
结果
Runtime: 76 ms, faster than 96.54% of Python3 online submissions for ZigZag Conversion.
Memory Usage: 12.6 MB, less than 100.00% of Python3 online submissions for ZigZag Conversion.
由结果可以看出,这种方法在python解法中已经接近最优解。那么下面使用C++实现。
Code1 & C++
class Solution {
public:
string convert(string s, int numRows) {
if(numRows==1)return s;
vector<string> ans(numRows,"");
string res;
int len = s.size();
int tmp=-1, current=0;
for(char ch:s){
if(current==0 || current==numRows-1){
tmp*=-1;
}
ans[current].push_back(ch);
current +=tmp;
}
for(int i=0;i<numRows;++i){
res += ans[i];
}
return res;
}
};
结果:
Runtime: 32 ms, faster than 53.70% of C++ online submissions for ZigZag Conversion.
Memory Usage: 19.2 MB, less than 100.00% of C++ online submissions for ZigZag Conversion.
可以发现相同的思路,C++比python执行速度快倒很正常,但总不是C++的最优解。
Code2 & Python
class Solution:
def convert(self, s: 'str', numRows: 'int') -> 'str':
if numRows==1: return s
ans = ['' for i in range(numRows)]
c = numRows*2-2 #这里c 用来表示一个循环周期
slen = len(s)
for i in range(numRows):
tmp = i
if i==0 or i==numRows-1:
while(i<slen):
ans[tmp] += s[i]
i+=c
else:
# 这里t2是因为在N的两个端点以外,还有一个字符需要单独添加进来
t2 = c-i
while(i<slen):
ans[tmp] += s[i]
if t2<slen:
ans[tmp] += s[t2]
t2+=c
i+=c
return ''.join(ans)
结果:
Runtime: 84 ms, faster than 83.07% of Python3 online submissions for ZigZag Conversion.
Memory Usage: 12.8 MB, less than 100.00% of Python3 online submissions for ZigZag Conversion.
Code2 & C++
class Solution {
public:
string convert(string s, int numRows) {
int len = s.size();
if( len<=numRows || len<=2 || numRows<2) return s;
int iter = numRows*2-2; // 循环周期
string res;
for(int i=0;i<numRows;++i){
string str2="";
if(i==0 || i==numRows-1){
int tmp = i;
while(tmp<len){
str2 += s[tmp];
tmp+=iter;
}
}else{
int tmp1=i, tmp2=iter-i;
while(tmp1<len){
str2 += s[tmp1];
if(tmp2<len){
str2 += s[tmp2];
tmp2 += iter;
}
tmp1+=iter;
}
}
res += str2;
}
return res;
}
};
结果:
Runtime: 28 ms, faster than 85.45% of C++ online submissions for ZigZag Conversion.
Memory Usage: 16.8 MB, less than 100.00% of C++ online submissions for ZigZag Conversion.
分析上面的两种方法,初步判定性能的差异是因为字符串重新排列并输出,时间复杂度均为O(n),但是第二种方法可能由于是多种循环的嵌套原因导致性能有所下降。
Status:Accepted