打表法
题目:有N份草,两只羊每次只能吃4的m次方份草,谁先吃完谁赢。返回先吃的赢还是后吃的赢
示例:N=9,
羊1:吃4份
剩5份
羊2:吃1份
剩4份
羊1:吃4份
吃完得胜
把吃1 4 16 64的结果都算一遍,看自己能不能赢
func eat(n int) string {
if n < 5 {
if n == 0 || n == 2 {
return "后"
}
return "先"
}
base := 1
for base <= n {
if eat(n-base) == "后" {
return "先"
}
base *= 4
}
return "后"
}
优化:输入是一个整形,输出是一个字符串,我们用0~100输入,查看规律
for i := 0; i < 100; i++ {
fmt.Println(eat(i))
}
后 先 后 先 先 后 先 后 先 先 后 先 后 先 先 后 先 后 先 先 后 先 后 先 先 后 先 后 先 先 后 先 后 先 先 后 先 后 先 先 后 先 后 先 先 后 先 后 先 先 后 先 后 先 先 后 先 后 先 先 后 先 后 先 先 后 先 后 先 先 后 先 后 先 先 后 先 后 先 先 后
发现都是后先后先先的循环,我们代码直接改写成
func eat1(n int)string{
if n%5==0||n%5==2{
return "后"
}else{
return "先"
}
}
这种一个整形输入,一个输出的可以尝试用打表法寻找规律,再用代码重写。原理是什么,可以不关心。
预处理法
题目: 将字符串RGRGR染色,每个红色R都比每个绿色G的距离最左侧近。变成RRRGG满足要求,需要涂染两次。有没有更好的涂染方案?
遍历:涂染后,左侧R的个数分别为0 1 2 3 4 5时,需要涂染的次数,最小的为最优解
遍历到i的时候,需要统计0i G的数量,i+1n-1中R的数量
时间复杂度是N的平方
我们预处理先定义一个数据A,统计0~i中G的数量[0,1,1,2,2]
定义数组B,统计i+1~n-1中R的数量[3,2,2,1,1]
遍历到i时直接拿到0iG的数量,i+1n-1中R的数量
时间复杂度是N
0 1 发生器
题目:给定一个函数f,可以15的数字等概率返回一个。请加工出17的数字等概率返回一个的函数g
先定义0 1 发生器函数m
当f返回小于3时,返回0
当f大于3时,返回1
当f的3时,重新执行一次
1~7是7个数字,用三位二进制可以代替
func g(){
res:=m()<<2+m()<<1+m()+1
if res==8{
//重摇
res=g()
}
return res
}
题目:给定一个函数f,以p概率返回0,以1-p概率返回1请加工出等概率返回0和1的函数g
返回01的概率是p*(1-p)
返回10的概率是(1-p)*p
他们是等概率的
当返回00 11时重摇