2022年7月11日 星期一

6. Zigzag Conversion

給定一個字串,用鋸齒狀重新排列並重組後回傳,鋸齒可任意調整大小。

https://leetcode.com/problems/zigzag-conversion/

範例
Input: s = "PAYPALISHIRING", numRows = 4
Output: "PINALSIGYAHRPI"
Explanation:
P     I    N
A   L S  I G
Y A   H R
P     I
範例是重新排序為 4 列的鋸齒狀,
從第 1 列開始由左到右取出字元重組。最後回傳重組後的PIN + ALSIG + YAHR + PI 即為答案。

能發現鋸齒走向是一個個的循環,看範例第 1 列的 P 、 I 、 N,中間都是 6 的 loop 。
而下一個字母循環 A 、 S 、 G 也是,不過這邊要注意的是中間穿插了 L 跟 I ,
但其實 L 、 I 亦是同樣的循環,因此我們第 2 列只要抓出 A 跟 L 後再交錯循環下去即可。

寫成程式的概念大概是

第二列               
s[0+1] + s[6-1] + s[(0+1)+6] + s[(6-1)+6]  + ... 
  A        L                       

第 3 列以後也是相同的概念,直到第 4 列的轉角,又回到了單一元素的循環,至此所有的字母都重新組合完成。

我們將上述步驟用代數替換掉,即為我們的程式碼

	public static String convert(String s, int numRows) {

		//如果不轉角,值接回傳原字串
		if (numRows == 1) {
			return s;
		}
		//本次的循環的跳號數
		int loop = numRows + numRows - 2;
		
		char[] schar = s.toCharArray();
		StringBuilder ans = new StringBuilder();
		
		//首字母的循環
		for (int n = 0; n < s.length(); n = n + loop) {
			ans.append(schar[n]);
		}

		int m = 1;
		//進行中段的交錯循環,若m == loop - m表示已碰到轉角
		while (m != loop - m) {
			//交錯循環中,第一個字母各別的位置
			int i = m;
			int j = loop - m;
			
			while (i < s.length() || j < s.length()) {
				if (i < s.length()) {
					ans.append(schar[i]);
					i = i + loop;
				}
				if (j < s.length()) {
					ans.append(schar[j]);
					j = j + loop;
				}
			}
			m++;
		}

		//轉角字母的循環
		for (int n = numRows - 1; n < s.length(); n = n + loop) {
			ans.append(schar[n]);
		}

		return ans.toString();
	}

沒有留言:

張貼留言