leetcode6-ZigZagConversion

題目:

將一個給定字符串根據給定的行數,以從上往下、從左到右進行 Z 字形排列。算法

好比輸入字符串爲 "LEETCODEISHIRING" 行數爲 3 時,排列以下:數組

L C I R E T O E S I I G E D H N 以後,你的輸出須要從左往右逐行讀取,產生出一個新的字符串,好比:"LCIRETOESIIGEDHN"。bash

請你實現這個將字符串進行指定行數變換的函數:app

string convert(string s, int numRows); 示例 1:函數

輸入: s = "LEETCODEISHIRING", numRows = 3 輸出: "LCIRETOESIIGEDHN" 示例 2:ui

輸入: s = "LEETCODEISHIRING", numRows = 4 輸出: "LDREOEIIECIHNTSG" 解釋:spa

L D R E O E I I E C I H N T S Gcode

思路:
思路一: 一開始最初的想法就是構造一個二維數據而後按照題目的順序將字符存放進去,最後在按照行數組拼接起來輸出,構造完之後發現構建這個二維的Z字浪費了不少時間,題目能夠作出來就是比較耗時
思路二:
第二種思路是直接從源字符串中找到每個屬於各行數組的字符,而後拼接輸出
我們用數字下標來代替字符看下每行的字符有什麼規律
3行:字符串

0   4
1 3 5
2   6
複製代碼

4行:get

0     6
1   5 7
2 4   8
3     9
複製代碼

5行:

0       8
1     7 9
2   6   10
3 5     11
4       12(第4行第1列)
複製代碼

咱們能夠發現下標i和總行數n,行號r([0~n]),間距step = 2n -2,之間的規律大體是這樣:
1.第一行的數組下標和最後一個行數組下標相差是n
2.對於間距最大的行的數據規律,行間距最大是2n-2,以3行爲例,第一行的數據就是0,4,8,12,每一個下標值間距都是step = 2n -2
3.中間行的間距,以5行爲例第二行1,7,9間隔是6,2,相加等於8;第三行2,6,10,間距是4,4,相加等於8; step-2*r

// 摘自網上的算法 我本身寫的沒有這個效率高
public String convert(String s, int numRows) {
		if (numRows == 1) return s;

		int step = numRows * 2 - 2; // 間距
		int index = 0;// 記錄s的下標
		int len = s.length();
		int add = 0; // 真實的間距
		string ret;
		for (int i = 0; i < numRows; i++) // i表示行號
		{
			index = i;
			add = i * 2;
			while (index < len)//超出字符串長度計算下一層
			{
				ret += s[index]; // 當前行的第一個字母
				add = step - add;// 第一次間距是step -2*i,第二次是2*i,
				index += (i == 0 || i == numRows-1) ? step : add; // 0行和最後一行使用step間距,其他使用add間距
			}
		}
		return ret;
	}
複製代碼

思路三:
第三種想法和第一種有點像,不過不是一次構造整個Z字型的數據,而是先建立出總行數n個數組,而後遍歷字符串s,一次往每一個數組裏面放入字符
以acbcdefg,3行爲例

a   e
b d f
c   g
複製代碼

開始遍歷字符串s
a放入到第一個數組 str[0] = a
b放入到第二個數組 str[1] = b
c放入到第三個數組 str[2] = c
d放入到第二個數組 str[1] = bd
e放入到第一個數組 str[0] = ae
f放入到第二個數組 str[1] = bdf
g放入到第三個數組 str[2] = cg

關鍵就在於遍歷s的時候選擇第幾個數組去放入,從上往下的時候數組下標是遞增的,從下斜着往上是遞減的,開始換向是n-1行的字符和下標等於0的字符.

public static String convert(String s, int numRows) {
       if (numRows == 1) {
           return s;
       }
       List<StringBuilder> resultList = new ArrayList<>();
       for (int i = 0; i < numRows; i++) {
           resultList.add(new StringBuilder());
       }
       int listIndex = 0, direction = 1;
      // direction 默認是正向就是加1 若是換向就變成-1
       for (int i = 0; i < s.length(); i++) {
           resultList.get(listIndex).append(s.charAt(i));
           if (listIndex == numRows - 1 || (i != 0 && listIndex == 0)) {
               direction *= -1;
           }
           listIndex += direction;
       }

       for (int i = 0; i < resultList.size(); i++) {
           if (i != 0) {
               resultList.get(0).append(resultList.get(i));
           }
       }
       return resultList.get(0).toString();
   }
複製代碼
本站公眾號
   歡迎關注本站公眾號,獲取更多信息