Out of Memory错误查找产品和质数

时间:2010-11-24 17:58:32

标签: c# recursion methods out-of-memory

所以我写了一个快速应用来检查我儿子的作业,看起来工作正常。它需要一个数字,找到所有的素数,然后找到所有的产品组合。因此,例如,您将其传递给“210”,它将返回:
2 x 3 x 5 x 7
5 x 6 x 7
7 x 30
6 x 35
5 x 42
3 x 7 x 10
10 x 21
3 x 70
3 x 5 x 14
14 x 15
2 x 7 x 15
2 x 105
2 x 5 x 21
2 x 3 x 35

我遇到的问题是做大数字时。片刻犹豫之后它会处理256(2 ^ 8),但是当我做512(2 ^ 9)时,我得到一个OutOfMemoryException。有人可以推荐更好的方法来查找产品集吗?我的代码如下。

class Program
{
    private static List<List<int>> coll = new List<List<int>>();

    public static List<int> PrimeFactors(int i)
    {
        if (i < 2)
        {
            throw new ArgumentOutOfRangeException("Numbers less than 2 don't have prime factors");
        }

        List<int> result = new List<int>();

        int divisor = 2;

        while (divisor <= i)
        {
            if (i % divisor == 0)
            {
                result.Add(divisor);
                i /= divisor;
            }
            else
            {
                divisor++;
            }
        }

        return result;
    }

    private static void GetFactors(List<int> l)
    {
        for (int i = 0; i < l.Count - 1; i++)
        {
            for (int x = i + 1; x < l.Count; x++)
            {
                List<int> loopList = new List<int>(l);
                int newProd = l[i] * l[x];
                loopList.RemoveAt(i);
                loopList.RemoveAt(x-1);
                loopList.Add(newProd);
                loopList.Sort();
                coll.Add(loopList);
                if (loopList.Count > 2)
                {
                    GetFactors(loopList);
                }
            }
        }
    }

    static void Main(string[] args)
    {
        int target = Convert.ToInt16(args[0]);
        List<int> results = PrimeFactors(target);
        results.Sort();
        coll.Add(results);
        GetFactors(results);
        List<string> factors = new List<string>();
        foreach (List<int> lst in coll)
        {
            string listString = "";
            for (int i = 0; i < lst.Count; i++)
            {
                if (i == lst.Count - 1)
                {
                    listString += String.Format("{0}", lst[i]);
                }
                else
                {
                    listString += String.Format("{0} x ", lst[i]);
                }
            }
            factors.Add(listString);
        }

        foreach (String factorString in factors.Select(x => x).Distinct())
        {
            Console.WriteLine(factorString);
        }
    }
}

编辑:这是基于以下答案的新代码。适用于我投掷的任何Int16。

    class Program
{
    private static List<List<int>> coll = new List<List<int>>();

    public static List<int> PrimeFactors(int i)
    {
        if (i < 2)
        {
            throw new ArgumentOutOfRangeException("Numbers less than 2 don't have prime factors");
        }

        List<int> result = new List<int>();

        int divisor = 2;

        while (divisor <= i)
        {
            if (i % divisor == 0)
            {
                result.Add(divisor);
                i /= divisor;
            }
            else
            {
                divisor++;
            }
        }

        return result;
    }

    private static void GetFactors(List<int> l)
    {
        for (int i = 0; i < l.Count - 1; i++)
        {
            for (int x = i + 1; x < l.Count; x++)
            {
                List<int> loopList = new List<int>(l);
                int newProd = l[i] * l[x];
                loopList.RemoveAt(i);
                loopList.RemoveAt(x-1);
                loopList.Add(newProd);
                bool existsInCollection = false;
                foreach (List<int> existingList in coll)
                {
                    if (ListEquality(existingList, loopList))
                    {
                        existsInCollection = true;
                        break;
                    }
                }
                if (!existsInCollection)
                {
                    coll.Add(loopList);
                    if (loopList.Count > 2)
                    {
                        GetFactors(loopList);
                    }
                }
            }
        }
    }

    private static bool ListEquality(List<int> listA, List<int> listB)
    {
        if (listA.Count != listB.Count)
            return false;

        listA.Sort();
        listB.Sort();

        for (int idx = 0; idx < listA.Count; idx++)
        {
            if (listA[idx] != listB[idx])
                return false;
        }
        return true;
    }

    static void Main(string[] args)
    {
        int target = Convert.ToInt16(args[0]);
        List<int> results = PrimeFactors(target);
        results.Sort();
        coll.Add(results);
        GetFactors(results);
        foreach (List<int> lst in coll)
        {
            string listString = "";
            for (int i = 0; i < lst.Count; i++)
            {
                if (i == lst.Count - 1)
                {
                    listString += String.Format("{0}", lst[i]);
                }
                else
                {
                    listString += String.Format("{0} x ", lst[i]);
                }
            }
            Console.WriteLine(listString);
        }
    }
}

再次感谢大家。

1 个答案:

答案 0 :(得分:2)

这个程序有很多东西可以做得更好。

以下是一些:

  • 请勿使用全局(coll
  • 不要使用错误的变量名称(ilx
  • List<int>可以正常或更好时,请不要使用int []
  • 使用join打印列表。

使这个程序更快的一些事情

  • 不要递归,迭代。 (提示 - 抽象堆栈对象或抽象集对象会有所帮助。)
  • 不要那么多,不应该重要,事实上可能会减慢你的速度。
  • 在你去的时候修剪你的临时存储 - 等到最后做一个独特的只是意味着你已经多次完成了同样的事情 WAY TO MANY 。在将它添加到集合之前,请检查它是否已经存在。