题目:
将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如给定字符串 PAYPALISHIRING 行数为4的时候排列图如下。
然后再再逐行读取拼接成 PINALSIGYAHRPI
题目分析:
通过上面的excel我们可以看出和坐标轴很像,一个是X轴,一个是Y轴。
step 1: 拆分多个单元。处理一个单元,剩余单元采用递归的形式处理。
step 2 : 每个单元的元素个数是: int eachUnitElementCount = numRows + numRows - 2
step 3 :单元总数计算: int units > = s.length() % eachUnitElementCount == 0 ? s.length() / eachUnitElementCount : s.length() /eachUnitElementCount + 1;
题目实例 14个元素, 每个单元6个元素。 得出 一共3个单元。
step 4: 现在的 Y轴是 numRows 。 X轴元素单元。 我们先循环Y轴,再逐个循环单元取到值。
step 5 : 分析每个单元,一个单元内的第一行 是 1个元素, 最后一行是1个元素,剩余的都是2个元素。
step 6 : 单元内每个元素的角标计算。 i = 行数 (从0开始) , j = 单元数(从1开始)
- 每个单元 6个元素。
- 第一行是1个元素,最后一行是 1个元素。其余行理论上是2个元素。
- 第一行,第一个单元角标 0。 第二个单元角标 6 ,第三个单元角标 12. 带入公式。eachUnitElementCount * (j - 1) + i 。 (i = 0)
- 第二行有两个元素,第一个元素角标是 i + eachUnitElementCount * (j- 1)。 每个单元内同一行的两个元素角标之和肯定等于 eachUnitElementCount。所以第二个元素的角标是
eachUnitElementCount * j - i
代码实现
public class Solution{
/** 用户存放新数据的链表, 哨兵节点 **/
private Node head = new Node();
/** 链表的末尾节点 **/
private Node tail ;
/** 每个单元的元素个数 **/
private int eachUnitElementCount;
/** 单元个数 **/
private int units;
/** 转换 **/
public String convert(String s, int numRows){
if(numRows == 1){return s;}
this.eachUnitElementCount = 2 * numRows - 2;
this.units = s.length() % eachUnitElementCount == 0? s.length()/eachUnitElementCount : s.length()/eachUnitElementCount + 1;
int i = 0;
/** 遍历 Y轴 **/
while(i < numRows){
int j = 1;
/** 遍历 X轴的单元 **/
while(j <= units){
/** 单元格内第一个待进队列角标 **/
int firstIndex = i + (j -1) * eachUnitElementCount;
/** 单元格内第二个待进队列角标 **/
int lastIndex = j * eachUnitElementCount - i;
if(i == 0 && firstIndex < s.length()){
enNode(s.charAt(firstIndex));
} else if(i == numRows - 1 && lastIndex < s.length()){
enNode(s.charAt(lastIndex));
} else {
if(firstIndex < s.length()){enNode(s.charAt(firstIndex));}
if(lastIndex < s.length()){enNode(s.charAt(lastIndex)); }
}
j ++;
}
i++;
}
return changeNodeToString(head);
}
/** 把链表内元素转成字符串的方法 **/
public String changeNodeToString(Node head){
if(head == null || head.next == null){return null;}
head = head.next;
StringBuilder sb = new StringBuilder();
while(head != null){
char ele = head.getData();
sb.append(ele);
head = head.next;
}
return sb.toString();
}
/** 把一个元素插入链表的方法 **/
public boolean enNode(char ele){
Node temp = new Node();
temp.setData(ele);
if(tail == null){
tail = temp;
head.next = tail;
} else {
tail.next = temp;
tail = temp;
}
return true;
}
/** 链表结构 **/
class Node{
private char data;
private Node next;
public char getData() {
return data;
}
public void setData(char data) {
this.data = data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
}