LeetCode006——Z字形变换

版权声明:版权所有,转载请注明原网址链接。 https://blog.csdn.net/qq_41231926/article/details/81901208

原题链接:https://leetcode-cn.com/problems/zigzag-conversion/description/

题目描述:

知识点:字符串

思路一:用一个二维char型数组来存储各字符,再从数组中按一定顺序取出字符拼接出结果

这个思路模拟的就是我们手工排列字符得出结果的一个过程。我们把排列出的Z字形图按列存储,每一列都是一个长度为numRows的数组。最后我们取出结果时,先取出每一列中的第一个元素,再取出每一列中的第二个元素,依次类推,直至取完所有的元素。

这个思路的时间复杂度是O(m * numRows),其中m为排列出的Z字形的列数,由于该列数与字符串的长度成正比,我们也可以把时间复杂度写成O(n * numRows),其中n为字符串s的长度。对于空间复杂度,我们需要一个二维数组来存储字符串s中所有的字符,和时间复杂度一样,是O(m * numRows)级别的,同理我们可以写成是O(n * numRows)级别的。

JAVA代码:

public class Solution {

	public String convert(String s, int numRows) {
		int n = s.length();
		if(n <= numRows || numRows == 1 || numRows == 0) {
			return s;
		}
		int quotient =  (n - numRows) / (2 * (numRows - 2) + 2);
		int mod = (n - numRows) % (2 * (numRows - 2) + 2);
		int cols = 1;
		if(mod <= numRows - 2) {
			cols += quotient * (numRows - 1) + mod; 
		}else {
			cols += (quotient + 1) * (numRows - 1);
		}
		char[][] array = new char[cols][numRows];
		int k = 0;
		for (int i = 0; i < cols; i++) {
			if(k < n) {
				if(i % (numRows - 1) == 0) {
					for (int j = 0; j < numRows; j++) {
						array[i][j] = s.charAt(k++);
						if(k >= n) {
							break;
						}
					}
				}else {
					array[i][numRows - i % (numRows - 1) - 1] = s.charAt(k++);
				}
			}
		}
		StringBuilder stringBuilder = new StringBuilder();
		for (int i = 0; i < numRows; i++) {
			for (int j = 0; j < cols; j++) {
				if(array[j][i] != 0) {
					stringBuilder.append(array[j][i]);
				}
			}
		}
		return stringBuilder.toString();
	}
}

LeetCode解题报告:

思路二:按顺序遍历字符串s,模拟ZigZag的全过程

在思路一中,我们保存了每一个字符之外还保存了大量的0,而这些0的位置其实是没必要保存的。因此我们对于每一行都设立一个StringBuilder型的变量来保存结果,自动忽略了0的位置。

设立一个int型变量zigZag来模拟我们指针的走向,当row为0时我们设置zigZag为1,当row为numsRow - 1时我们设置zigZag为-1。其实看代码很好理解这个过程。

我们只遍历了一遍字符串s,显然时间复杂度是O(n)级别的,其中n为字符串s的长度。而对于空间复杂度,我们没有保存任何额外的0,我们的空间复杂度也是O(n)级别的。

JAVA代码:

public class Solution {
	
	public String convert(String s, int numRows) {
		int n = s.length();
		if(n <= numRows || numRows == 1 || numRows == 0) {
			return s;
		}
		StringBuilder[] stringBuilders = new StringBuilder[numRows];
		for (int i = 0; i < numRows; i++) {
			stringBuilders[i] = new StringBuilder();
		}
		int row = 0;
		int zigZag = 1;
		for (int i = 0; i < n; i++) {
			stringBuilders[row].append(s.charAt(i));
			row += zigZag;
			if(row == numRows - 1) {
				zigZag = -1;
			}
			if(row == 0) {
				zigZag = 1;
			}
		}
		StringBuilder result = new StringBuilder();
		for (int i = 0; i < stringBuilders.length; i++) {
			result.append(stringBuilders[i]);
		}
		return result.toString();
	}
}

LeetCode解题报告:

思路三:寻找数学规律

用小数据进行测试,很容易得到本题每一行字符在原字符串s中的索引的规律,比如第一行字符和最后一行字符的索引间隔是2 * numRows - 2,其余各行的规律也可以依次得出,只要我们在草稿纸上仔细推导一遍即可,这里我就不详细证明了。

此思路的时间复杂度是O(numRows * n),其中n为字符串s的长度。而空间复杂度,由于这个方法也没有存储多余的0字符,故空间复杂度是O(n)级别的。

JAVA代码:

public class Solution {

	public String convert(String s, int numRows) {
		int n = s.length();
		if(n <= numRows || numRows == 1 || numRows == 0) {
			return s;
		}
		StringBuilder[] stringBuilders = new StringBuilder[numRows];
		for (int i = 0; i < numRows; i++) {
			stringBuilders[i] = new StringBuilder();
		}
		int interval = 2 * numRows - 2;
		int row = 0;
		//处理第一行
		for (int i = 0; i < n; i += interval) {
			stringBuilders[row].append(s.charAt(i));
		}
		//处理剩下的所有行
		for (row = 1; row < numRows; row++) {
			for (int i = row; i < n; i++) {
				if(row != numRows - 1) {
					if((i - row + 2 * row) % interval == 0) {
						stringBuilders[row].append(s.charAt(i));
					}
					if((i - row) % interval == 0) {
						stringBuilders[row].append(s.charAt(i));
					}
				}else {
					if((i - row) % interval == 0) {
						stringBuilders[row].append(s.charAt(i));
					}
				}
			}
		}
		StringBuilder result = new StringBuilder();
		for (int i = 0; i < stringBuilders.length; i++) {
			result.append(stringBuilders[i]);
		}
		return result.toString();
	}
}

LeetCode解题报告:

猜你喜欢

转载自blog.csdn.net/qq_41231926/article/details/81901208