The string “PAYPALISHIRING” is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)
P A H N
A P L S I I G
Y I R
And then read line by line: “PAHNAPLSIIGYIR”
Write the code that will take a string and make this conversion given a number of rows:
string convert(string s, int numRows);
Example 1:
Input: s = “PAYPALISHIRING”, numRows = 3
Output: “PAHNAPLSIIGYIR”
Example 2:
Input: s = “PAYPALISHIRING”, numRows = 4
Output: “PINALSIGYAHRPI”
Explanation:
P I N
A L S I G
Y A H R
P I
package com.zc.algorithm;
import java.util.ArrayList;
import java.util.List;
public class ZigZag {
/**
* 通过在集合中创建三个StringBuilder,将每次读取到的字符放入list集合的StringBuilder对象中
* @param s
* @param numRows
* @return
*/
public static String convert1(String s, int numRows)
{
if(numRows == 1) return s;
//创建一个List集合,保存numRows个StringBuilder对象
List<StringBuilder> list = new ArrayList<>();
for(int i = 0; i < numRows;i++)
{
list.add(new StringBuilder());
}
int currRow = 0;
boolean goingDown = false;
for(int i = 0; i < s.length(); i++)
{
list.get(currRow).append(s.charAt(i));
//当currRow = 0或者 currRow = numRows时,改变goingDown的取值
if(currRow == 0 || currRow == numRows - 1) goingDown = !goingDown;
currRow += goingDown? 1:-1;
}
StringBuilder res = new StringBuilder();
for(StringBuilder sb : list)
{
res.append(sb);
}
return res.toString();
}
在这里插入代码片
/**
* 根据字符串的索引值来读取
* 举例:L E E T C O D E I S H I R I N G
* 索引:0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
* 这个字符串的Z字形为:
* 0 4 8 12
* 1 3 5 7 9 11 13 15
* 2 6 10 14
* 根据以上结果,以及给定的输出行数可得如下规律:
* 第0行: (2 * numsRow - 2) * k (k = 0,1,2........)
* 第numsRow- 1 行: (2 * numsRow - 2) * k + numsRows - 1
* 中间行: 前一个数:(2 * numsRow - 2) * k +i 后一个数:(2 * numsRow - 2) * k - i (注意:i 表示中间第几行)
* @param s
* @param numsRow
* @return
*/
public static String convert2(String s , int numsRow)
{
if(numsRow == 1) return s;
int len = s.length();
int cycle = 2 * numsRow - 2;
StringBuilder res = new StringBuilder();
for(int i = 0; i < numsRow; i++) // 控制行数
{
for(int j = 0; j + i< len; j += cycle)
{
//当numsRow = 3 时,i = 2,即 numsRows - 1;
res.append(s.charAt(j + i));
//中间行是执行这段代码
if(i!=0 && i != numsRow - 1 && j+cycle - i < len)
{
res.append(s.charAt(j+cycle-i));
}
}
}
return res.toString();
}
public static void main(String[] args)
{
String s = "LEETCODEISHIRING";
System.out.println("使用方法1获取的结果");
System.out.println(convert1(s,3));
System.out.println("使用方法2获取的结果");
System.out.println(convert2(s,3));
}
}
/**
* 这个方法可以理解为双指针法
* @param s
* @param numRows
* @return
*/
public static String convert3(String s , int numRows)
{
if(numRows == 1) return s;
int len = s.length();
List<StringBuilder> list = new ArrayList<>();
for(int i =0 ; i < Math.min(numRows,s.length()); i++)
{
list.add(new StringBuilder());
}
int i = 0;//根据i获取字符串中的字符
while(i < len)
{
//idx控制行数
for(int idx = 0 ; i < len && idx < numRows; i++, idx++)
{
list.get(idx).append(s.charAt(i));
}
//回到中间行
for(int idx = numRows-2; idx>=1&&i<len; idx--,i++)
{
list.get(idx).append(s.charAt(i));
}
}
StringBuilder sb = new StringBuilder();
for(StringBuilder str : list)
{
sb.append(str);
}
return sb.toString();
}