打表法

158 阅读2分钟

打表法

题目:有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时重摇