LeetCode | 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 text, int nRows);

convert("PAYPALISHIRING", 3) should return "PAHNAPLSIIGYIR".

我的思路

以题目中的字符串 "PAYPALISHIRING" 为例,首先建一个 numRows x column 的矩阵 matrix(变量定义见下面的代码),并且用 '\0' 对其进行初始化。

\0 \0 \0 \0 \0 \0 \0
\0 \0 \0 \0 \0 \0 \0
\0 \0 \0 \0 \0 \0 \0

然后,将题目提供的字符串 "PAYPALISHIRING" 按照 ZigZag 的模式往上述矩阵中填字符。此时矩阵 matrix 如下:

P \0  A \0  H \0  N
A  P  L  S  I  I  G
Y \0  I \0  R \0 \0

最后,在上述的 matrix 矩阵中,从左到右、从上到下提取出非 '\0' 字符即可答案 "PAHNAPLSIIGYIR"。这种方法貌似比较笨,代码复杂。后续参考下其他人的方法后再做更新。

代码

char* convert(char* s, int numRows) {
    int i = 0, j = 0, k = 0;
    int sLen = 0;
    int column = 0;
    int divisor = 0;
    int numTmp = 0;
    char* retStr = NULL;
    char **matrix = NULL;

    while(*(s + sLen) != '\0') {
        sLen++;
    }

    if((sLen <= numRows) || (numRows <= 1)) {
        return s;
    }

    retStr = (char*)malloc((sLen + 1) * sizeof(char));
    *(retStr + sLen) = '\0';

    divisor = numRows * 2 - 2;
    column = (numRows - 1) * (sLen / divisor);
    if((sLen % divisor) <= numRows) {
        column = column + 1;
    }
    else {
        column = column + 1 + (sLen % divisor) - numRows;
    }

    // malloc a matrix.
    matrix = (char **)malloc(numRows * sizeof(char*));
    for(i = 0; i < numRows; i++) {
        *(matrix + i) = (char *)malloc(column * sizeof(char));
    }

    // Init matrix with '\0'.
    for(i = 0; i < numRows; i++) {
        for(j = 0; j < column; j++) {
            matrix[i][j] = '\0';
        }
    }

    for(j = 0; j < column; j++) {
        for(i = 0; i < numRows; i++) {
            if(j % (numRows - 1) == 0) {
                numTmp = i + divisor * (j / (numRows - 1));
                //printf("[01]i = %d, j = %d, numTmp = %d\n", i, j, numTmp);
                if(numTmp >= sLen) {
                    break;
                }
                matrix[i][j] = s[numTmp];
            }

            if(j % (numRows - 1) > 0) {
                numTmp = (numRows - 1) + j % (numRows - 1) + divisor * (j / (numRows - 1)); 
                if(numTmp >= sLen) {
                    break;
                }

                if((i + (j % (numRows - 1))) == (numRows - 1)) {
                    //printf("[02]i = %d, j = %d, numTmp = %d\n", i, j, numTmp);
                    matrix[i][j] = s[numTmp];
                }
            }
        }
    }

    for(i = 0; i < numRows; i++) {
        for(j = 0; j < column; j++) {
            if(matrix[i][j] != '\0') {
                retStr[k] = matrix[i][j];
                k++;
            }
        }
    }

    for(i = 0; i < numRows; i++) {
        free(*(matrix + i));
        *(matrix + i) = NULL;
    }
    free(matrix);
    matrix = NULL;

    return retStr;
}

优化代码

下面的优化代码参照 leetcode.com 网站上别人的 submission 所写。

此题主要需要找到规律。按照下图列出 3 行和 4 行的情况,然后将字符替换为该字符在原字符串 s 的索引。就可以得出每行中相邻两个字符索引的差值(diff)的规律。规律找到之后,问题就迎刃而解。

char* convert(char* s, int numRows) {
    if(numRows<2)
        return s;    
    int len = strlen(s), num = 0, diff;
    int width = (numRows - 1) * 2;
    char* ans = (char*)malloc(sizeof(char) * (len + 1));

    for(int k = 0; k < numRows; k++){
        diff = k * 2;

        for(int h = k; h < len; h = h + diff, num++){
            *(ans + num) = *(s + h);
            diff = (diff == k * 2 ? width - k * 2 : k * 2);

            if(diff == 0)
                diff = width;
        }
    }
    *(ans+len) = '\0';

    return ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值