leetcode之Z-字形变换Golang

我解这道题的时候时间效率和空间效率感觉都不高,因为我用的是一个二维数组

二维数组的行数就是函数的入口参数numRows

二维数组的列数是通过一系列的计算得到的,我认为就是在这个地方浪费了空间,因为这个二维数组并没有全部存满,当numRows越大的时候,流出来的空闲的地方就越多:

  设Z字形中竖着的一共有n列,待处理字符串长度length,那么有:

  n*p+(p-2)*n>=length

  从而可以得到一个n,

  那么二维数组的列数为:column=n+n*(numRows-2)=n*(numRows-1)

然后就是这事行列两个坐标row和col

  当填充z字形的竖着的地方的时候,行列坐标的变化为row++,而col不变,当row==numRows的时候开始填充斜着的地方

  当填充z字形斜着的地方的时候,行列坐标的变化为row--,col++,当row==0的时候,开始填充竖着的地方

  最后读取二维数组中不是\x00的值,注意这里不能空格,因为\x00!=空格

最后附上代码:

func convert(s string, numRows int) string {
	if numRows == 1 {
		return s
	}
	twoDimensionalResult := make([][]byte, numRows)
	length := len(s)
	n := 1
	for {
		if 2*n*(numRows-1) > length {
			break
		}
		n++
	}
	n = n * (numRows - 1)
	for i := 0; i < numRows; i++ {
		twoDimensionalResult[i] = make([]byte, n)
	}
	row, col := 0, 0
	flag := true
	for i := 0; i < length; i++ {
		twoDimensionalResult[row][col] = s[i]
		if row == numRows-1 {
			flag = false
		} else if row == 0 {
			flag = true
		}
		if flag {
			row++
		} else {
			row--
			col++
		}
	}
	//在这里,因为已经为切片开辟了空间了,也就是说此时切片中有值,只不过全部是0值
	// 所以下面不能用append,因为如果用append,那么新加入的数据是从所有的0值后面追加的,所以造成的结果就是输出的结果的字符串里面前面一大截是空格
	resultSlice := make([]string, numRows)
	for i := 0; i < numRows; i++ {
		tmpStr := strings.ReplaceAll(string(twoDimensionalResult[i]), "\x00", "")
		resultSlice[i] = tmpStr
	}
	return strings.Join(resultSlice, "")
}

  另一种优化的解法

通过找规律可以快速的知道每一个位置的每个元素位于哪一行

 

 

 上面两组数据分别是numRows等于4和5的情况,会排成4行或者5行

然后我们找规律,例如对于第一组数据

排在第一行的数据分别为0,6,12

排在第一列的数据分别为0,1,2,3

所以我们可以用求余的方式获取他们的位置,我的第一反应是用3来求余,但是用3不能区分第一行第一行和最后一行,而其他行都能一下求出来,所以就尝试用6来求余

当用6求余的时候,竖着排列的数据能够正确定位到位置,斜着排列的数据就要多处理一次:

  例如对于编号为5的数据:

    余数:5%6=5

    行号:3-(5-3)=1

    所以成功解决了斜着排列数据的位置

综上所述:

  求余的数是n=2*numRows-2

  对编号为k的数据:

  p=k%n

    if p<=numRows-1

      那么p就是这个数据所在的行号

    else:

      p=numRows-1-(p-(numRows-1))=2*numRows-2-p

知道了每个数据所在的行号,我们就可以创建对应行的数组,然后将他们依次存入这些数组中,最后按行号读取每个数组的数据,组成最后的字符串输出

代码如下:

func convert(s string, numRows int) string {
	if numRows == 1 {
		return s
	}
	var retStr string
	twoDimensionalResult := make([][]byte, numRows)
	length := len(s)
	n := 2*numRows - 2
	for i := 0; i < length; i++ {
		index := i % n
		if index >= numRows {
			// index=numRows-1-(index-(numRows-1))
			// index=2*numRows-2-index
			// 经过化简,上面两个式子等于下面这个式子,n=2*numRows-2
			index = n - index
		}
		twoDimensionalResult[index] = append(twoDimensionalResult[index], s[i])
	}
	for i := 0; i < numRows; i++ {
		retStr = retStr + string(twoDimensionalResult[i])
	}
	return retStr
}

  

posted @ 2020-06-05 22:35  胖胖咩  阅读(314)  评论(0)    收藏  举报