题目区(源自于leetcode)
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下:
L C I R
E T O E S I I G
E D H N
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"LCIRETOESIIGEDHN"。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);
示例 1:
输入: s = "LEETCODEISHIRING", numRows = 3
输出: "LCIRETOESIIGEDHN"
示例 2:
输入: s = "LEETCODEISHIRING", numRows = 4
输出: "LDREOEIIECIHNTSG"
解释:
L D R
E O E I I
E C I H N
T S G
思路说明
通过题目解释可以看出规律:输入的字符串以从上到下开始排列,到最后一行后沿着对角线逐渐回到第一行(不包括第一行),循环往复。那么每一行取得数组的下标就有了规律,是一个带有周期性图形重复。那么就可以归纳如下(假设有n行):
从图形我们可以看出周期为pace = n*2-2
第一行
从下标0开始,每个周期只会取到一个字符,每次增加一个周期(n*2-2)
第二行到第n-1行
在每一个周期内只会取到最多两个字符。第一个字符从下标(当前行数j-1)开始,每次增加一个周期(n*2-2);第二个字符从下标(n*2-2-当前行数j+1)开始,每次增加一个周期(n*2-2)
第n行
从下标n-1开始,每次增加一个周期(n*2-2)
源码区
#include <string.h>
#include <stdio.h>
char * convert(char * s, int numRows);
main() {
char input[50] = {"LEETCODEISHIRING"};
int num = 4 ;
char * s = convert(input,num);
printf("%s",s);
}
char * convert(char * s, int numRows) {
if(numRows==1) {
return s;
}
int size = strlen(s);//数组的长度
char result[size];
memcpy(result,s,sizeof(char)*size);
int pace = 2*numRows-2;//一个周期数据长度
int j=0;
while(j<size) { //处理第一行
*(s++)= result[j];
j+=pace;
}
j = 1;//将行数指向第二行
for(; j<numRows-1; j++) { //默认除了第一行和第n-1行都有两个数字
int k1 = j;
int k2 = pace-k1;
while(1) {
if(k1>size-1) { //判断第一个数是否存在,不存在跳出
break;
}
*(s++) = result[k1];
if(k2>size-1) { //判断第二个数是否存在,不存在跳出
break;
}
*(s++) = result[k2];
k1+=pace;
k2+=pace;//向后移动一个周期
}
}
while(j<size) { //处理最后一行
*(s++) = result[j] ;
j+=pace;
}
return s-size;
}