Leetcode_06_ZigZag Conversion (easy)

 

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数组

有几种方法。

  1. 使用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()返回的是一个临时指针,不能对其进行操作
  2. for循环实现

    for(i =0 ;i < string.size();i++)

            str[i] = string.at(i);

  3. 使用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("\n");

            final+="\n";

        }

      

        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

 

 
posted @ 2015-10-17 11:04  锄,禾日当午  阅读(189)  评论(0编辑  收藏  举报