题目
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “LEETCODEISHIRING” 行数为 3 时,排列如下:
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“LCIRETOESIIGEDHN”。
思路
虽然题目说是Z字形,但我理解为N字形。看到题目时,第一时间想到的是递归,经过计算可发现规律,即每次递归时,第一个字符和第二个字符之间的相隔 2n - 3 个字符(n >=2),后来发现提取数组比较麻烦,作罢。
之后很快地想到了桶排序,故用了桶排序。
解法:桶排序解题
- 算法较为简单易懂,代码有注释。
public class Main {
public static void main(String[] args) {
// write your code here
String s = "Apalindromeisaword,phrase,number,orothersequenceofunitsthatcanbereadthesamewayineitherdirection,withgeneralallowancesforadjustmentstopunctuationandworddividers.";
int numRows = 3;
s = convert(s,numRows);
System.out.println(s);
}
public static String convert(String s, int numRows)
{
if(s == null || s.length() == 0 || numRows == 1)//排除一些临界取值
{
return s;
}
char [] arr = s.toCharArray();//存储转化后的字符数组
char [] arr_sorted = new char [arr.length];//存储整理后的字符数组
char [][] bucket = new char [numRows][arr.length/(numRows - 1) + 5];//建立一个二维数组作为桶,这里注意,桶的个数易求,
// 但桶的长度较难,容易越界,经过证明可得长度为多少时合适,这里取了一个较为合理的值
int [] point = new int [numRows];//用于作为每个桶的指针
int mark = 0;//用于后面的往复标记
for(int i = 0,j = 0 ;i < arr.length; i ++)//开始将数据倒入桶内
{
bucket[j][point[j]] = arr[i];
point[j] ++;//此处为桶指针的移动
if(mark == 0){//此处为每个桶的移动,符合N字形规律
j++;
}
else {
j--;
}
if (j == -1) {
j=1;
mark = 0;
}
else if(j == numRows) {
j = numRows - 2;
mark = 1;
}
}
int p = 0;
for(int j = 0,i = 0;j < numRows ; j ++)//这里将每个桶中的数据倒回数组
{
i = 0;
while (bucket [j][i] != '\u0000')
{
arr_sorted[p] = bucket [j][i];
p ++;
i ++;
}
}
s = String.valueOf(arr_sorted);
return s;
}
}