Leetcode算法第6题
题目:Z 字形变换,将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"。
/**
*示例 1:
*输入:s = "PAYPALISHIRING", numRows = 3
*输出:"PAHNAPLSIIGYIR"
*解释:
*P A H N
*A P L S I I G
*Y I R
*/
思路1:将数据存储二维数组中,列优先输入,行优先输出;
char * convert(char * s, int numRows){
int len = strlen(s); //获取s长度
int x = numRows,y = 0; //x为矩阵行数,y为列数
int count = 0,n = len; //n为未存入矩阵的字符数,count用以标记换列
if(numRows == 1||x >= len)
return s;
if(x==2)
{
if(n%2==1)
y = n/2 + 1;
else
y = n/2;
char st[x][y];
int m = 0;
for(int i = 0; i < y; ++i)
for(int j = 0; j < x; ++j)
st[j][i] = ' ';
for(int i = 0; i < y; ++i)
for(int j = 0; j < x; ++j)
{
if(m<len)
st[j][i] = s[m++];
}
m = 0;
for(int i = 0; i < x; ++i)
for(int j = 0; j < y; ++j)
if(st[i][j]!=' '&&st[i][j]!='\0')
s[m++] = st[i][j];
return s;
}
while(n>0)
{
count++;
if(count%(x-1)==1)
{
n = n-x;
y++;
}
else
{
n = n-1;
y++;
}
} //求列数
char str[x][y];
for(int i = 0; i < y; ++i)
for(int j = 0; j < x; ++j)
{
str[j][i] = ' ';
}
int num = 0;
int ret = x-1;
for(int i = 0; i < y; ++i)
{
for(int j = 0; j < x; ++j)
{
if((i+1)%(x-1) == 1)
{
if(num>len)
break;
str[j][i] = s[num++];
ret = x-1;
}
else
{
if(num>len)
break;
str[--ret][i] = s[num++];
break;
}
}
}
num = 0;
for(int i = 0; i < x; i++)
for(int j = 0; j < y; j++)
// printf("%c",str[i][j]);
if(str[i][j]!=' '&&str[i][j]!='\0')
s[num++] = str[i][j];
return s;
}
思路二直接构造:矩阵的每个非空字符会对应到s的哪个下标,从而直接构造出答案。
char * convert(char * s, int numRows){
int n = strlen(s), r = numRows;
if (r == 1 || r >= n)
{
return s;
}
int t = r * 2 - 2;
char * ans = (char *)malloc(sizeof(char) * (n + 1));
int pos = 0;
for (int i = 0; i < r; ++i)
{ // 枚举矩阵的行
for (int j = 0; j + i < n; j += t)
{ // 枚举每个周期的起始下标
ans[pos++] = s[j + i]; // 当前周期的第一个字符
if (0 < i && i < r - 1 && j + t - i < n)
{
ans[pos++] = s[j + t - i]; // 当前周期的第二个字符
}
}
}
ans[pos] = '\0';
return ans;
}