找到号码

本文关键字:号码 | 更新日期: 2023-09-27 18:18:15

这是一个问题陈述。

假设一个数字2345。如果把它的数字相乘,就得到120。现在,如果你再乘以120,你会得到数字0,这是一个一位数。如果我把2345的数字加起来,就得到14。如果我把14的数字加起来,就会得到5,这是一个一位数。

因此,任何数都可以在一定步数内转换为两个个位数。你可以看到2345通过两步的数字乘法被转换为0,通过两步的数字加法被转换为5。现在考虑任意数字n,假设它可以通过n1步将数字乘以一个数字d1,并通过n2步将数字加到一个数字d2来转换。

你的任务是找到大于N且小于1000000000的最小数字,该数字可以在小于或等于n1步的时间内乘以d1,并在小于或等于n2步的时间内将其数字与d2相加。

找到号码

我认为你只是错误地处理/解释了这个问题;这是暗箱操作:

using System;
using System.Diagnostics;
static class Program
{
    static void Main()
    {
        // check our math first!
        // You can see 2345 is converted to 0 by using multiplication of digits in 2 steps
        int value, steps;
        value = MultiplyToOneDigit(2345, out steps);
        Debug.Assert(value == 0);
        Debug.Assert(steps == 2);
        // and it is converted to 5 by using addition of digits in 2 steps
        value = SumToOneDigit(2345, out steps);
        Debug.Assert(value == 5);
        Debug.Assert(steps == 2);
        // this bit is any random number
        var rand = new Random();
        for (int i = 0; i < 10; i++)
        {
            int N = rand.Next(0, MAX);
            int result = Execute(N);
            Console.WriteLine("For N={0}, our answer is {1}", N, result);
        }
    }
    const int MAX = 1000000000;
    //Now consider any number N.
    static int Execute(int N)
    {
        // Let us say that it can be converted by multiplying digits to a one digit number d1 in n1
        // steps and by adding digits to one digit number d2 in n2 steps.
        int n1, n2;
        int d1 = MultiplyToOneDigit(N, out n1),
            d2 = SumToOneDigit(N, out n2);
        // Your task is to find smallest number greater than N and less than 1000000000 
        for (int i = N + 1; i < MAX; i++)
        {
            int value, steps;
            // which can be converted by multiplying its digits to d1 in less than or equal to n1 steps
            value = MultiplyToOneDigit(i, out steps);
            if (value != d1 || steps > n1) continue; // no good
            // and by adding its digits to d2 in less than or equal to n2 steps.
            value = SumToOneDigit(i, out steps);
            if(value != d2 || steps > n2) continue; // no good
            return i;
        }
        return -1; // no answer
    }
    static int MultiplyToOneDigit(int value, out int steps)
    {
        steps = 0;
        while (value > 10)
        {
            value = MultiplyDigits(value);
            steps++;
        }
        return value;
    }
    static int SumToOneDigit(int value, out int steps)
    {
        steps = 0;
        while (value > 10)
        {
            value = SumDigits(value);
            steps++;
        }
        return value;
    }
    static int MultiplyDigits(int value)
    {
        int acc = 1;
        while (value > 0)
        {
            acc *= value % 10;
            value /= 10;
        }
        return acc;
    }
    static int SumDigits(int value)
    {
        int total = 0;
        while (value > 0)
        {
            total += value % 10;
            value /= 10;
        }
        return total;
    }
}

我可以看到两个内存问题;第一个是生成大量字符串——你可能想这样处理:

static int SumDigits(int value)
{
    int total = 0;
    while (value > 0)
    {
        total += value % 10;
        value /= 10;
    }
    return total;
}

(即完全未测试)

第二个问题是庞大的列表;你不需要存储(在lstString中)每个值只是为了找到最小值。记录下你到目前为止做得最好的。或者,如果需要每个值的数据,那么:不要将它们存储为string。实际上,i无论如何都可以隐含(从列表/数组中的位置),因此您真正需要的是每个值的cnt值的int[]int[1000000000]本身是4GB,所以在最近的。net版本(<gcAllowVeryLargeObjects>)中需要大数组支持。但更好的做法是:不要存储它。

但是它抛出了System.OutOfMemoryException

这仅仅意味着内存不足。您的限制是1,000,000,000或大约1G。对于32位系统来说已经太大的字符串引用乘以4字节。即使没有实际的字符串。

你可以将答案更紧凑地存储在int[]数组中,但这仍然会显示相同的问题。

所以,降低你的限制或者编译并在64位PC上运行

A for effort:)

现在一起做。你当然可以做重构。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _17082903_smallest_greatest_number
{
    class Program
    {
        static void Main(string[] args)
        {
            int N = 2344;
            int n1 = 0;
            int n2 = 0;
            int d1 = SumDigits(N, ref n1);
            int d2 = ProductDigits(N, ref n2);
            bool sumFound = false, productFound = false;
            for (int i = N + 1; i < 1000000000; i++)
            {
                if (!sumFound)
                {
                    int stepsForSum = 0;
                    var res = SumDigits(i, ref stepsForSum);
                    if (res == d1 && stepsForSum <= n1)
                    {
                        Console.WriteLine("the smallest number for sum is: " + i);
                        Console.WriteLine(string.Format("sum result is {0} in {1} steps only", res, stepsForSum));
                        sumFound = true;
                    }
                    stepsForSum = 0;
                }
                if (!productFound)
                {
                    int stepsForProduct = 0;
                    var res2 = ProductDigits(i, ref stepsForProduct);
                    if (res2 == d2 && stepsForProduct <= n2)
                    {
                        Console.WriteLine("the smallest number for product is: " + i);
                        Console.WriteLine(string.Format("product result is {0} in {1} steps only", res2, stepsForProduct));
                        productFound = true;
                    }
                    stepsForProduct = 0;
                }
                if (productFound && sumFound)
                {
                    break;
                }
            }
        }
        static int SumDigits(int value, ref int numOfSteps)
        {
            int total = 0;
            while (value > 0)
            {
                total += value % 10;
                value /= 10;
            }
            numOfSteps++;
            if (total < 10)
            {
                return total;
            }
            else
            {
                return SumDigits(total, ref numOfSteps);
            }
        }
        static int ProductDigits(int value, ref int numOfSteps)
        {
            int total = 1;
            while (value > 0)
            {
                total *= value % 10;
                value /= 10;
            }
            numOfSteps++;
            if (total < 10)
            {
                return total;
            }
            else
            {
                return ProductDigits(total, ref numOfSteps);
            }
        }
    }
}