C语言仿HashMap完成记忆化搜索

至于为何用C语言来开荒算法,我不知道我不知道!!!(无尽的后悔)

但是既然你从标题进来了,那就说明你也准备用C写记忆化搜索,那么我就以下面一题为例,讲解一下C实现记忆化搜索的办法。

这是LeetCode的第70题,爬梯子:

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

示例 1:

输入:n = 2
输出:2
解释:有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶


示例 2:

输入:n = 3
输出:3
解释:有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶
 

提示:

1 <= n <= 45

我的解法:

一般看到这种题目都想先使用递归去做,因为递归最容易理解。首先我们自顶向下分析,当n=6,那么第六级阶梯可能从第五级上来,也可能是第四级。以此类推,图解如下:

叶子节点只可能是F(2)或者F(1),很明显F(1)和F(2)的值为1和2,那么我们的递推公式就很清楚了,就是

 因此,代码应该不难写出:

int climbStairs(int n){
    if(n == 1) return 1;
    if(n == 2) return 2;
    return climbStairs(n - 1) + climbStairs(n - 2);
}

但是,这个的时间复杂度很高,达到了惊人的O(n²),因此,我们需要进行优化,这里就需要用到我们所需要的记忆化搜索的方法

这里我们需要建立一个键值对,我的想法是,使用数组的下标存储其第几级时的次数,那么就可以少遍历几次,就如下图,红框里的我们算过就不用再算了。

那么我们就可以这样写出代码。

const int inf = -1;
int *data,flag = 1,Max;
int climbStairs(int n)
{
    if(n <= 2) return n;
    if(flag)
    {
        init(n);
        flag = 0;
    }
    if(data[n] != inf)
        return data[n];
    else{
        int result = climbStairs(n - 1) + climbStairs(n - 2);
        data[n] = result;
        return result;
    }
}
void init(int n)
{
    data = malloc(sizeof(int*)*n);
    memset(data,inf,sizeof(int*)*n);
}

 先给Memory数组赋初值,然后给做过的数组里塞入数据,使得第几级的数据被“记住”。因为次数不可能存在0,那么实现起来就很容易啦!这样子的缺点就是当数据规模很大的时候会占用一大片内存,那么我们还有什么方法呢?

int Memory[45 + 1] = {0,1,2};
int climbStairs(int n){
    if (Memory[n] != 0) return Memory[n];
    return Memory[n] = climbStairs(n - 1) + climbStairs(n - 2), Memory[n];
}

直接预估定长数组即可(要睡觉了摆了,有好想法的可以留言,谢谢)。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值