2327. 知道秘密的人数-递归法--记忆化搜索递归法

  1. 知道秘密的人数-递归法
    在第 1 天,有一个人发现了一个秘密。

给你一个整数 delay ,表示每个人会在发现秘密后的 delay 天之后,每天 给一个新的人 分享 秘密。同时给你一个整数 forget ,表示每个人在发现秘密 forget 天之后会 忘记 这个秘密。一个人 不能 在忘记秘密那一天及之后的日子里分享秘密。

给你一个整数 n ,请你返回在第 n 天结束时,知道秘密的人数。由于答案可能会很大,请你将结果对 109 + 7 取余 后返回。

示例 1:

输入:n = 6, delay = 2, forget = 4
输出:5
解释:
第 1 天:假设第一个人叫 A 。(一个人知道秘密)
第 2 天:A 是唯一一个知道秘密的人。(一个人知道秘密)
第 3 天:A 把秘密分享给 B 。(两个人知道秘密)
第 4 天:A 把秘密分享给一个新的人 C 。(三个人知道秘密)
第 5 天:A 忘记了秘密,B 把秘密分享给一个新的人 D 。(三个人知道秘密)
第 6 天:B 把秘密分享给 E,C 把秘密分享给 F 。(五个人知道秘密)

示例 2:

输入:n = 4, delay = 1, forget = 3
输出:6
解释:
第 1 天:第一个知道秘密的人为 A 。(一个人知道秘密)
第 2 天:A 把秘密分享给 B 。(两个人知道秘密)
第 3 天:A 和 B 把秘密分享给 2 个新的人 C 和 D 。(四个人知道秘密)
第 4 天:A 忘记了秘密,B、C、D 分别分享给 3 个新的人。(六个人知道秘密)

这一题,挺有意思的,我的代码如下:

int  konw_people_num(int n,int know_day,int forget,int delay,int today){
    if(today<n){
            if(know_day<=forget&&know_day>delay){
                return konw_people_num(n,know_day+1,forget,delay,today+1)+konw_people_num(n,2,forget,delay,today+1);//这里注意从第二天开始,很关键,也是这个代码的一个细节问题
            }
            else{

                    return konw_people_num(n,know_day+1,forget,delay,today+1);

            }

    }
    else{
      //  printf("%d ",know_day);
       if(know_day>forget){
           return 0;
       }
       else{
            if(know_day>delay){
                return 2;
            }
            else{
                return 1;
            }

       }
    }




}

int peopleAwareOfSecret(int n, int delay, int forget){
        // for(int i=1;i<8;i++){
     
    return konw_people_num(n,1,forget,delay,1);

}

上面这个代码虽然易懂,但是时间开销通过不了,所以我又优化了一下,解题代码如下,有点动态规划的感觉,但本质还是递归:



int  konw_people_num2(int n,int know_day,int forget,int delay,int today,int *r,int *scell){
    if(today<n){
            if(know_day<=forget&&know_day>delay){
                if(r[n-today]==1){
                     return konw_people_num2(n,know_day+1,forget,delay,today+1,r,scell)%1000000007+scell[n-today+1]%1000000007;

                }
                else{
                      return konw_people_num2(n,know_day+1,forget,delay,today+1,r,scell)+konw_people_num2(n,2,forget,delay,today+1,r,scell);

                }
               
            }
            else{

                    return konw_people_num2(n,know_day+1,forget,delay,today+1,r,scell);



            }

    }
    else{
      //  printf("%d ",know_day);
       if(know_day>forget){
           return 0;
       }
       else{
            if(know_day>delay){
                return 2;
            }
            else{
                return 1;
            }

       }
    }




}


int peopleAwareOfSecret(int n, int delay, int forget){
        // for(int i=1;i<8;i++){
        //     printf("%d ",konw_people_num(i,1,forget,delay,1));
        // }
        //  printf("%d ",konw_people_num(5,1,forget,delay,1));
        //  printf("||");
        int *r=(int *)malloc(sizeof(int )*n);
         int *scell=(int *)malloc(sizeof(int )*n);
         for(int i=0;i<n;i++){
             r[i]=0;
         }

         for(int i=1;i<n;i++){
           
            scell[i]=konw_people_num2(i,1,forget,delay,1,r,scell)%1000000007;
              r[i]=1;
        }
    
    return konw_people_num2(n,1,forget,delay,1,r,scell)%1000000007;

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值