ZigZag Conversion------(String)
题目:
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 text, int nRows);
convert("PAYPALISHIRING", 3)
should return "PAHNAPLSIIGYIR"
.
解答:
首先将string字符串转化为char数组
有几种方法。
-
使用string类的c_str()函数strcpy(str,string.c_str());
strcpy原型声明:char *strcpy(char* dest, const char *src);头文件:#include <string.h> 和 #include <stdio.h>功能:把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间c_str()语法:
const char *c_str();
c_str()函数返回一个指向正规C字符串的指针, 内容与本string串相同.
这是为了与c语言兼容,在c语言中没有string类型,故必须通过string类对象的成员函数c_str()把string 对象转换成c中的字符串样式。
注意:一定要使用strcpy()函数 等来操作方法c_str()返回的指针
比如:最好不要这样:
char* c;
string s="1234";
c = s.c_str(); //c最后指向的内容是垃圾,因为s对象被析构,其内容被处理
应该这样用:
char c[20];
string s="1234";
strcpy(c,s.c_str());
这样才不会出错,c_str()返回的是一个临时指针,不能对其进行操作 -
for循环实现
for(i =0 ;i < string.size();i++)
str[i] = string.at(i);
-
使用string类的copy函数
string.copy(str,0,string.size());
规律:
第一行两个元素相差为numRow*2-2,相差空格为numRow-2
第i行相差
往下:( numRow-(i-1))*2-2,相差空格为numRow-(i-1)-2
往上:i*2-2,相差空格为i-2
判断往上还是往下:
num/(numRow*2-2)与(numRow*2-2)/2比较大小
大:往上 小:往下
除第一行和最后一行外,都是先下再上循环
//自己写的程序,新手渣渣一枚
#include <iostream>
using namespace std;
class Solution {
public:
string convert(string s, int numRows) {
if(s.length()==0||numRows<1)return s;
char str[30];
string final;
strcpy(str,s.c_str());
for(int i=0;i<numRows;i++){
int flag=1;
int keyboardNum = 0;
// if(i==numRows-1){//除了最后一个,其他一开始都是往下
// keyboardNum = i-1;
// }else{
// keyboardNum=numRows-i-2;
// }
for(int j=i;j<=sizeof(s);){
for(int a=0;a<keyboardNum;a++){
// printf(" ");//每次打印一个数和后面的空格
final+=" ";
}
final+=str[j];
if(flag&&i!=numRows-1){//除了第一行和最后一行,其他都是先往下在往上循环
j=j+(numRows-i)*2-2;
keyboardNum=numRows-i-2;
if(i!=0){
flag = 0;
}
}else{
j=j+(i+1)*2-2;
flag = 1;
keyboardNum = i-1;
}
}
// printf(" ");
final+=" ";
}
return final;
}
};
int main(int argc, const char * argv[]) {
Solution a;
cout<<a.convert("ABCDEFGHIJKIJIIONINOON", 5)<<endl;
return 0;
}
结果超时了,晕。
仔细一看原来不用输出z字型格式,只要求字母顺序对即可,同学们,一定要认真审题啊>_<
修改过后:
class Solution {
public:
string convert(string s, int numRows) {
if(s.length()==0||numRows<1)return s;
string final="";
for(int i=0;i<numRows;i++){
int flag=1;
for(int j=i;j<s.length();){
final+=s.at(j);
if(flag&&i!=numRows-1){//除了第一行和最后一行,其他都是先往下在往上循环
j=j+(numRows-i)*2-2;
if(i!=0){
flag = 0;
}
}else{
j=j+(i+1)*2-2;
flag = 1;
}
}
}
return final;
}
};
//依然超时,晕
看了网上的代码
class Solution {
public: string convert(string s, int nRows) {
unsigned long len = s.length();
if (len == 0 || nRows < 2) return s;
string ret = "";
int lag = 2*nRows - 2; //循环周期
for (int i = 0; i < nRows; i++) {
for (int j = i; j < len; j += lag) {
ret += s.at(j);
//非首行和末行时还要加一个
if (i > 0 && i < nRows-1) {
int t = j + lag - 2*i;
if (t < len) {
ret += s.at(t);
}
}
}
}
return ret;
}
};
发现所有行的重复周期都是 2 * nRows - 2
对于首行和末行之间的行,还会额外重复一次,重复的这一次距离本周期起始字符的距离是 2 * nRows - 2 - 2 * i