leetcode 6 Z 字形变换 c代码

题目如下:

将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。

比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下:
L   C   I   R
E T O E S I I G
E   D   H   N
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"LCIRETOESIIGEDHN"

刚看到这道题的时候,动手在纸上画了下,发现第一行字符出现的下标在原始字符串中是有规律的,ai = i(2 * row - 2),紧接着找下面的行,找了几分钟无果。本着先解决问题的态度,打算暴力解下,使用二维数组,遍历字符串,逐个字符读取到数组中,最后再从数组中读取出来。这个想法阔以,点提交的时候提示超出时间限制.......暴力无果,卒。

重新找规律,其实规律也不是那么难找,第一行和最后一行规律基本上都是i(2*row - 2),中间行的字符规律看似不好找,不是。

每个字符与下一个字符是对称的。例如题目中的第二行,前两个字符ET和第一行终点E对称,距离为n - i,n为总行数,i为第i行。

此外就是第一个数和第二数是对称的,第二个数和第三个数也是对称的,只不过对称的距离不同,稍稍总结下可得每行字符下标规律:

设行数为i,那么第i行第k个元素下标右下列式子可得:
当i为首行或者尾行时,Ak = (i - 1) + 2(row - 2);
当i为中间行时,A1 = i - 1;
              Ak = Ak-1 + (k%2 ? (row - i) : (i - 1));

知道了规律,就可以按行从原始字符串中读取字符了。

看了官方给的按行读取方法,顺序读取字符串,添加到行中,每读取一个字符,添加到一行中,同时指向下一行,当到了行尾或者行首则改变行的方向。方法是不错,不过如果用c语言实现的话,不是还得为每一行申请一块内存吗?这块内存大小又不能确定,这和数组法有啥区别。

下面是找规律的c代码:

char * convert(char * s, int numRows){
    int len = 0, row = 0, i = 0, j = 0, k = 0;
    char *pstr;
    pstr = s;
    
    if (!s || numRows < 2)
        return s;
    
    while (*pstr++ != '\0')len++;
    
    if (len < 2)
        return s;
    
    pstr = (char *)malloc(sizeof(char) * (len + 1));
    if (!pstr)
        return NULL;
    
    i = 0;
    for (row = 1; row <= numRows; row++)
    {
        //按行读取每个字符下标
        j = row - 1;
        if (row == 1 || row == numRows)
        {            
            while (j < len)
            {
                pstr[i++] = s[j];
                j += (2 * numRows - 2);
            }
        }
        else
        {
            k = 1;
            while(j < len)
            {
				pstr[i++] = s[j];
                j = j + ((k++ % 2) ? 2 * (numRows - row) : 2 * (row - 1));
            }
        }   
    }
    pstr[i] = '\0';
    return pstr;
} 

编码的时候挖了一个坑," ?: "三目运算符的优先级低于加号,导致运算有问题!!!

参考资料:

1. 数据结构 : C语言版/ 严蔚敏,吴伟民编著

=============================================================================================

Linux应用程序、内核、驱动开发交流讨论群(745510310),感兴趣的同学可以加群讨论、交流、资料查找等,前进的道路上,你不是一个人奥^_^。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值