C++ 快速找到所有数字X的方法,这些数字和它们自己相加,去掉一个数字得到N?

C++ 快速找到所有数字X的方法,这些数字和它们自己相加,去掉一个数字得到N?,c++,optimization,mathematical-optimization,subsequence,C++,Optimization,Mathematical Optimization,Subsequence,我正在做一个赋值,它给出一个整数N,并要求我们找到X,Y的所有可能组合,这样X+Y=N和Y=X,去掉一个数字。例如,302将具有以下解决方案: 251+51=302 275+27=302 276+26=302 281+21=302 301+01=302 我完成这项工作的代码可以找到所有正确答案,但对于非常大的数字来说,它运行得太慢(最大可能的数字10^9大约需要8秒钟,而我希望在3秒钟内完成多达100个这样的情况的整个算法) 下面是一些描述我当前解决方案的代码: //Only need to c

我正在做一个赋值,它给出一个整数N,并要求我们找到X,Y的所有可能组合,这样X+Y=N和Y=X,去掉一个数字。例如,302将具有以下解决方案:

251+51=302

275+27=302

276+26=302

281+21=302

301+01=302

我完成这项工作的代码可以找到所有正确答案,但对于非常大的数字来说,它运行得太慢(最大可能的数字10^9大约需要8秒钟,而我希望在3秒钟内完成多达100个这样的情况的整个算法)

下面是一些描述我当前解决方案的代码:

//Only need to consider cases where x > y.
for(int x = n * 0.5; x <= n; x++)
{
     //Only considers cases where y's rightmost digit could align with x.
     int y = n - x,
         y_rightmost = y % 10;
     if(y_rightmost == x % 10 || y_rightmost == (x % 100) / 10)
     {
         //Determines the number of digits in x and y without division. places[] = {1, 10, 100, 1000, ... 1000000000}
         int x_numDigits = 0,
             y_numDigits = 0;
         while(x >= places[x_numDigits])
         {
             if(y >= places[x_numDigits])
                 y_numDigits++;

             x_numDigits++;
         }

         //y must have less digits than x to be a possible solution.      
         if(y_numDigits < x_numDigits)
         {
             if(func(x, y))
             {
                 //x and y are a solution.
             }
         }
}
<代码> /只需要考虑x> y的情况。 对于(int x=n*0.5;x 0) { 如果(x%10!=y%10) { //如果最右边的数字不匹配,将x向左移动一次,然后再次检查。 x/=10; diff++; 如果(差异>1) 返回false; } 其他的 { //如果匹配,两个数字都移动到下一个数字。 x/=10; y/=10; } } //如果x中的最后一个数字是唯一的差异,或者x由0和1组成,那么x,y是一个解决方案。 如果((x<10&&diff==0)| |(x%10==0)) 返回true; 其他的 返回false; }
这是迄今为止我所能找到的最快的解决方案(我尝试过的其他方法包括将X和Y转换成字符串,使用自定义子序列函数,以及将X从右到左划分为前缀和后缀,不包含每个数字,并查看是否有任何一个求和为Y,但两者都没有那么快)。然而,它仍然不能像我需要的那样扩展到更大的数字,我正在努力思考任何其他方法来优化代码或底层的数学推理。如果您有任何建议,我们将不胜感激。

首先考虑解决一个更简单的问题:

  • 求X和Y,使得X+Y=N
在伪代码中,步骤应如下所示:

  • 在数组中循环,对每个给定的项执行下一步:

    • 添加此编号以设置并检查是否有N-
这将作为唯一数组的O(n)复杂度

因此,通过首先循环一个数组并为每个数字添加重复的计数器来改进它以处理重复的数字。使用C++或扩展集的某种字典。每次你找到必要的号码,检查一下柜台


完成后,您只需编写此“数字检查”函数,并在查找集合中的值时应用它。

@SamVarshavchik您是说算法问题在学习编程中没有任何意义?不幸的是,这是我的一个课程的作业。我知道这个问题本身并没有实际意义,但我仍然需要找到一种更有效的方法来执行这些计算。我觉得我遗漏了一些更普遍的有用的东西,可以简化这里的事情。我将从X和Y的位数开始。如果X有D个数字,那么Y有(D-1)个数字。它们的和必须是N(同样,你知道数字的数目)。也许基于此,你可以大大减少你的搜索资源。如果这是一个家庭作业,你能解释一下这是一个家庭作业的特定主题吗?它是用于学习继承、操作符重载、模板或其他关键的C++的基本方面吗?你学习什么样的C++主题,这是一个合适的家庭作业?@克里斯蒂很难把它缩小,而不仅仅是扔掉X和Y有相同数量的数字。Y可能有前导零,所以如果N=100,那么X=100和Y=00是一个有效的解决方案。我不认为我完全理解你在这里的建议。我目前只是将正确的解决方案存储在一个字符串中,以便以后输出,所以除了重复的数字之外,我看不到在这里保留一个集合的好处。输入只是一个数字N,任务是查找所有可能的X+Y组合,如上所述。因为即使是相同的X也会有不同的Y,这取决于N,所以除了给出一个重复的N之外,我看不到一个简单的方法来使用过去的计算。
bool func(int x, int y)
{
    int diff = 0;
    while(y > 0)
    {
        if(x % 10 != y % 10)
        {
            //If the rightmost digits do not match, move x to the left once and check again.
            x /= 10;
            diff++;
            if(diff > 1)
                return false;
        }
        else
        {
            //If they matched, both move to the next digit.
            x /= 10;
            y /= 10;
        }
    }

    //If the last digit in x is the only difference or x is composed of 0's led by 1 number, then x, y is a solution.
    if((x < 10 && diff == 0) || (x % 10 == 0))
        return true;
    else
        return false;
}