【算法题】寻找最少完全平方数

问题:

给出一个正整数n,寻找最少的完全平方数,使他们的和为n
完全平方数:1,4,9,16 …
12 = 4+4+4
13 = 4+9

解法一:动态规划

状态转移方程:F(n) = min{ F(n-ai) + 1 } 其中ai为小于等于n的完全平方数

int a[100005];
int func(int n)
{
    if (n <= 0)
        return -1;
    for (auto i = 1; i <= n;++i)
    {
        a[i] = 99999;
    }

    int min_tmp;
    int tmp;
    for (auto i = 1; i <= n;++i)
    {
        min_tmp = 99999;
        for (auto j = 1; j*j <= i;++j)
        {
            tmp = a[i - j*j] + 1;
            if (tmp<min_tmp)
            {
                min_tmp = tmp;
            }
        }
        a[i] = min_tmp;
    }
    return a[n];
}
解法二:最短路径算法

问题转化为搜索节点n到节点0的最短路径,当两个节点差值为完全平方数时,节点间存在一条路径,路径长度均为1。

int BFSfunc(int n)
{
    if (n<=0)
        return -1;
    queue<pair<int, int>> q;
    q.push(make_pair(n, 0));

    while (!q.empty())
    {
        int num = q.front().first;
        int step = q.front().second;
        q.pop();

        if (num == 0)
        {
            return step;
        }
        for (auto i = 1; i*i <= num;++i)
        {
            q.push(make_pair(num - i*i, step + 1));
        }
    }
    return -1;
}

改进:使用记录表,避免重复的入队

int BFSfunc(int n)
{
    if (n<=0)
        return -1;
    queue<pair<int, int>> q;
    q.push(make_pair(n, 0));
    vector<char> visited(n+1, 0);
    visited[n] = 1;
    int tmp;
    while (!q.empty())
    {
        int num = q.front().first;
        int step = q.front().second;
        q.pop();

        if (num == 0)
        {
            return step;
        }
        for (auto i = 1; i*i <= num;++i)
        {
            tmp = num - i*i;
            if (visited[tmp])
            {
                continue;
            }
            q.push(make_pair( tmp, step + 1));
            visited[tmp] = 1;
        }
    }
    return -1;
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值