279. Perfect Squares(最少完全平方数)C++描述

博客围绕给定正整数n,找出和为n的最少完全平方数个数的问题展开。将题目转化为图的问题,通过每次减去一个完全平方数找到达零点的最短路径来解题。还给出扩展思路,若想得到最少完全平方数构成的数组,可修改代码存储方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0. 题目描述

Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, …) which sum to n.
给定一个正整数n,找出最少个完全平方数,它们的和为n,返回个数
[点击此处跳转题目原地址](https://leetcode.com/problems/perfect-squares/description/

示例:
Input: n = 12
Output: 3 
Explanation: 12 = 4 + 4 + 4.

1.解题思路

将题目转化成图的广度优先遍历,每次减去一个完全平方数到下一步,查找到达零点的最短路径。通俗来讲,就是每次走一步,看怎样走先到达0点;代码示例:

  int numSquares(int n) {
        vector<bool> visited(unsigned (n+1), false);
        queue<pair<int, int>> queue1; //构建一个队列进行搜索
        queue1.push(make_pair(n, 0));  //pair的first是节点, second是步数
        while(not queue1.empty()){
            int node = queue1.front().first;
            int step = queue1.front().second;
            queue1.pop();

            for (int i = 1; i * i <= node; i ++){
                int nextNode = node - i * i;
                if (nextNode == 0) //找到率先到达0点的,返回当前步数
                    return step + 1;
                if (not visited[nextNode]){
                    queue1.push(make_pair(nextNode, step + 1));
                    visited[nextNode] = true;
                }
            }
        }
        return 0;
    }

2. 扩展

如果想得到由这样最少个完全平方数构成的数组,该怎么办?一个很简单的想法就是,将上述代码中pairfirst由存储当前节点改为存储所经过的所有节点构成的数组即可:
vector<int> numSquaresRes(int n) {
        vector<int> resRoute;
        bool end = false;
        vector<bool> visited(unsigned (n+1), false);
        queue<pair<vector<int>, int>> queue1;
        queue1.push(make_pair(vector<int>(1,n), 0));
        while(not queue1.empty()){
            vector<int> route = queue1.front().first;
            int node = route.back();
            int step = queue1.front().second;
            queue1.pop();

            for (int i = 1; i * i <= node; i ++){
                int nextNode = node - i * i;

                if (nextNode == 0) { //由于队列前端存储的路径肯定比之后的路径要短或者至少相当,所以第一次到达0点,这一定是最短路径
                    resRoute = route;
                    resRoute.push_back(nextNode);
                    end = true;
                }//找到率先到达0点的

                if (not visited[nextNode]){
                    vector<int> nextRoute = route;
                    nextRoute.push_back(nextNode); //将上一次的路径加上当前节点构成当前路径
                    queue1.push(make_pair(nextRoute, step + 1));  //路径连同步数压入队列
                    visited[nextNode] = true;
                }
            }
            if(end)
                break;
        }
        vector<int> res;
        res.reserve(resRoute.size()-1);
        for (int i = 0; i < resRoute.size()-1; i++){
            res.push_back(resRoute[i] - resRoute[i+1]);
        }
        return res;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值