Golang学习之路 - LeetCode-Go-Learning 第六题. Z 字形变换

6. ZigZag Conversion

题目

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:

func convert(text string, nRows int) string

convert(“PAYPALISHIRING”, 3) should return “PAHNAPLSIIGYIR”.

解题思路

输入"ABCDEFGHIJKLMNOPQRSTUVWXYZ"和参数5后,得到答案"AGMSYBFHLNRTXZCEIKOQUWDJPV",
按照题目的摆放方法,可得:

A   I   Q   Y
B  HJ  PR  XZ
C G K O S W
DF  LN  TV
E   M   U

可以看到,各行字符在原字符串中的索引号为

  1. 0行,0, 8, 16, 24
  2. 1行,1, 7,9, 15,17, 23,25
  3. 2行,2, 6, 10, 14, 18, 22
  4. 3行,3,5, 11,13, 19,21
  5. 4行,4, 12, 20

令p=numRows×2-2,可以总结出以下规律

  1. 0行, 0×p,1×p,…
  2. r行, r,1×p-r,1×p+r,2×p-r,2×p+r,…
  3. 最后一行, numRow-1, numRow-1+1×p,numRow-1+2×p,…

只需编程依次处理各行即可。

解题代码

解决方案 1 按上述规律编程

func convert(s string, numRows int) string {
    if numRows == 1 || len(s) <= numRows {
        return s
    }
    
    res := bytes.Buffer{}
    // p pace 步距
    p := numRows * 2 - 2
    
    // 第一行
    for i := 0; i < len(s); i += p {
        res.WriteByte(s[i])
    }
    // 中间的行
    for r := 1; r <= numRows - 2; r++ {
        // 添加r行的第一个字符
        res.WriteByte(s[r])
        
        for k := p; k - r < len(s); k += p {
            res.WriteByte(s[k - r])
            if k + r < len(s) {
                res.WriteByte(s[k+r])
            }
        }
    }
    
    // 处理最后一行
    for i := numRows - 1; i < len(s); i += p {
		res.WriteByte(s[i])
	}

	return res.String()                          
}

解决方案 2

func convert(s string, numRows int) string {
    if numRows == 1 {
		return s
	}
	b := numRows - 1
	strArr := make([]string, numRows)
	for k, v := range s {
		if (k/b)%2 == 0 {
			strArr[k%b] += string(v)
		} else {
			strArr[b-(k%b)] += string(v)
		}
	}
	return strings.Join(strArr,"")
}

测试代码

package problem0006

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

type para struct {
	one string
	two int
}

type ans struct {
	one string
}

type question struct {
	p para
	a ans
}

func Test_OK(t *testing.T) {
	ast := assert.New(t)

	qs := []question{
		question{
			p: para{
				one: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
				two: 1,
			},
			a: ans{
				one: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
			},
		},
		question{
			p: para{
				one: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
				two: 2,
			},
			a: ans{
				one: "ACEGIKMOQSUWYBDFHJLNPRTVXZ",
			},
		},
		question{
			p: para{
				one: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
				two: 3,
			},
			a: ans{
				one: "AEIMQUYBDFHJLNPRTVXZCGKOSW",
			},
		},
		question{
			p: para{
				one: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
				two: 4,
			},
			a: ans{
				one: "AGMSYBFHLNRTXZCEIKOQUWDJPV",
			},
		},
		question{
			p: para{
				one: "ABCDEFGHIJKLMNOPQRSTUVWX",
				two: 5,
			},
			a: ans{
				one: "AIQBHJPRXCGKOSWDFLNTVEMU",
			},
		},
		question{
			p: para{
				one: "A",
				two: 3,
			},
			a: ans{
				one: "A",
			},
		},
	}

	for _, q := range qs {
		a, p := q.a, q.p
		ast.Equal(a.one, convert(p.one, p.two), "输入:%v", p)
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值