提取公共代码
- 前言
- 一、字母版上的路径
- 二、贪心
- 1、idea
- 2、go
- 3、代码不断拆分复用的过程
- 总结
- 参考文献
前言
写代码,在提高效率的同时,要方便人看,这个人包括自己。大函数要拆分成一些小函数,让每个函数的宏观目的和步骤都显得清晰,读起来才容易懂。除此之外,拆分也有讲究,提取公共代码,尽量减少重复无意义的代码,提高复用率。
一、字母版上的路径
二、贪心
1、idea
// 根据字母的ascall码可以确定它在board中的坐标。
// a - 97 == v,<x = v / 5,y = v % 5>
// cur:<0,0> t: <x,y>
// 前5行,先x或者y都无所谓
// 前五行到第6行,只能先y再x
// 第6行到前5行,只能先x再y
2、go
func alphabetBoardPath(target string) string {
sb := &strings.Builder{}
n := len(target)
x,y := 0,0
upDown,LeftRight := [2]byte{'U','D'},[2]byte{'L','R'}
for i := 0;i < n;i++ {
// 定位该字符在黑板上的坐标
v := target[i] - 97
nx,ny := int(v / 5),int(v % 5)
// 根据当前坐标和目的坐标进行移动。
if nx == 5 {// 去z那个地方,必须先L,再D
move(y,ny,sb,LeftRight)
move(x,nx,sb,upDown)
} else {
move(x,nx,sb,upDown)
move(y,ny,sb,LeftRight)
}
// 寻找到该字符,将其加入。
sb.WriteByte('!')
x,y = nx,ny
}
return sb.String()
}
// 不断抽象,复用代码。
// 最开始是xY(int,int,int,int,*strings.Builder)函数,以及yX(int,int,int,int,*strings.Builder)函数;
// 发现对x或y的动作是一致的,所以拆解成单个x的动作moveX | moveY,
// 继续抽象,moveX | moveY代码都差不多,只是加入的ch不一样,所以将ch当作变量传入,将两函数合并成move函数。
func move(z,nz int,sb *strings.Builder,choice [2]byte){
zGap := z - nz
ch := choice[0]
if zGap < 0 {
ch = choice[1]
}
for i := 0;i < abs(zGap);i++ {
sb.WriteByte(ch)
}
}
func abs(x int) int {
if x < 0 {
return -x
}
return x
}
3、代码不断拆分复用的过程
// 不断抽象,复用代码。
// 最开始是xY(int,int,int,int,*strings.Builder)函数,以及yX(int,int,int,int,*strings.Builder)函数;
// 发现对x或y的动作是一致的,所以拆解成单个x的动作moveX | moveY,
// 继续抽象,moveX | moveY代码都差不多,只是加入的ch不一样,所以将ch当作变量传入,将两函数合并成move函数。
func move(z,nz int,sb *strings.Builder,choice [2]byte){
zGap := z - nz
ch := choice[0]
if zGap < 0 {
ch = choice[1]
}
for i := 0;i < abs(zGap);i++ {
sb.WriteByte(ch)
}
}
总结
1)每个函数拆分,做到有清晰的宏观目的和宏观步骤,这样后来的人包括自己才能更容易的看懂。
2)拆分代码,也要提取公共代码,尽量减少重复无意义的代码,提高复用率。
参考文献
[1] LeetCode 字母板上的路径