题意:
长度为n的数中,找到每位上的数字之和(例:256每位上的数字之和为2+5+6=13)为m的这些数的和,并求和。

方法一
暴力枚举

思路:因为n是位数且图片说明 ,n最大也就是999999,所以可以直接暴力枚举。
找到n位数的最小值与最大值区间,并在这个区间遍历,将每位上的数字之和等于m的值相加。

class Solution {
public:

    long long sum(int n, int m) {
        long long res=0;
        int min=pow(10,n-1),max=pow(10,n);//n位数的(最小值)和(最大值-1)
        for(int i=min;i<max;i++){//遍历
            int x=i,s=0;
            while(x){//求各个位上的数字之和
                s+=x%10;
                x/=10;
            }
            if(s==m)//比较,如果等于m,则加上zheg
                res+=i;
        }
        return res;

    }
};

时间复杂度:图片说明
空间复杂度:图片说明

方法二
dfs搜索+剪枝

思路:
图片说明

递归,每一位都有0到9十种选择,最高位除外,只有1到9九种选择。
上述多叉树中,第0层是空串,第一层是最高位,可取1到9。之后的每一层都递归处理,可取0到9。
层数表示位数,例如:n位数,当到达第n层则可以判断该分支是否可取。
请在这里输入引用内容
剪枝:

if(m-i<0)//剪枝
    break;

因为m是每位上的数字之和,当图片说明 则说明该分支以下的子树不再满足条件,跳出循环。

class Solution {
public:

    long long res=0;
    int flag=0;//用于判断一个数不能含有前导0
    long long sum(int n, int m) {
        dfs(n,m,0);
        return res;

    }

    void dfs(int n,int m,int x){
        if(n==0){//凑齐n位数
            if(m==0)//如果x的各个位上的数字之和为m,则加上x
               res+=x; 
            return;
        }
        for(int i=0;i<10;i++){//每位数的范围是【0,9】
           if(flag==0&&i==0){//不能含有前导0,如果数的最高位是0,则跳过
               flag=1;
               continue;
           }
            if(m-i<0)//剪枝
                break;
            dfs(n-1,m-i,x*10+i);//n-1表示用掉一位,m-i表示减掉该位上的数,x表示形成的数
        }
    }
};

时间复杂度:图片说明
空间复杂度:图片说明