c#中与递归相关的问题

时间:2013-08-14 11:02:49

标签: c# algorithm loops

这是这个问题的背景:

背景 取任何大于1的整数n并应用以下算法

  1. 如果n为奇数,则n = n×3 + 1,否则n = n / 2

  2. 如果n等于1则停止,否则转到步骤1

  3. 以下说明使用6的起始n

    时会发生什么

    6 - 3 - 10 - 5 - 16 - 8 - 4 - 2 - 1

    经过8代算法后,我们得到1。 据推测,对于大于1的每个数,该算法的重复应用将会 最终得到1。

    问题是如何找到一个需要500代才能减少到1?的数字?

    下面的代码是我的版本,但似乎有一些错误的逻辑。你能帮我纠正一下吗?提前谢谢。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Sequence1
    {
        class Program
        {
            static void Main(string[] args)
            {
                int start = 1;
                int flag = 0;
                int value;
                while(true){
                    int temp = (start - 1) / 3;
                    string sta = temp.ToString();
                        if (Int32.TryParse(sta, out value) )
                        {
                            if (((start - 1) / 3) % 2 == 1)
                            {
                                start = (start - 1) / 3;
                                flag++;
                                if (flag == 500)
                                {
                                    break;
                                }
                            }
                            else
                            {
                                start = start * 2;
                                flag++;
                                if (flag == 500)
                                {
                                    break;
                                }
                            }
                        }
                        else 
                        {
                            start = start * 2;
                            flag++;
                            if (flag == 500)
                            {
                                break;
                            }
                        }
    
                    }
    
    
                Console.WriteLine("result is {0}", start);
                Console.ReadLine();
            }
        }
    }
    

4 个答案:

答案 0 :(得分:9)

由于您的问题的标题是递归相关问题”,我将为您提供递归解决方案。

int Process(int input, int maxRecursionDepth)
{
    // condition to break recursion
    if (maxRecursionDepth == 0 || input == 1)
        return input;

    if (input % 2 == 1) // odd case
        return Process(input * 3 + 1, maxRecursionDepth - 1);
    else // even case
        return Process(input / 2, maxRecursionDepth - 1);
}

现在找到指定范围内的所有数字,在恰好500次递归后返回1:

int startRange = 1, endRange = 1000;
int maxDepth = 500;

List<int> resultList = new List<int>();
for (int i = startRange; i <= endRange; i++)
{
    if (Process(i, maxDepth) == 1)
        resultList.Add(i);
}

答案 1 :(得分:4)

你的问题是Collat​​z猜想的一部分(关于递归定义的函数)尚未解决:

http://en.wikipedia.org/wiki/Collatz_conjecture

所以我认为蛮力是一个很好的出路:

public static int GetMinNumber(int generations) {
  if (generations < 0)
    throw new ArgumentOutOfRangeException("generations");

  // Memoization will be quite good here
  // but since it takes about 1 second (on my computer) to solve the problem
  // and it's a throwaway code (all you need is a number "1979515")
  // I haven't done the memoization

  for (int result = 1; ; ++result) {
    int n = result;
    int itterations = 0;

    while (n != 1) {
      n = (n % 2) == 0 ? n / 2 : 3 * n + 1;
      itterations += 1;

      if (itterations > generations)
        break;
    }

    if (itterations == generations)
      return result;
  }
}

...

int test1 = GetMinNumber(8);   // <- 6
int test2 = GetMinNumber(500); // <- 1979515

答案 2 :(得分:3)

观察问题,

  

13→40→20→10→5→16→8→4→2→1

     

在第三次迭代中,我们命中数字10,小于13

因此,每次我们都可以使用缓存时,不要计算序列计数。

    static int GetMinCollatz(int maxChain)
    {
        const long number = 1000000;

        int minNumber = 0;
        // Temporary values
        int tempCount = 0;
        long temp = 0;
        // Cache 
        int[] sequenceCache = new int[number + 1];
        // Fill the array with -1
        for (int index = 0; index < sequenceCache.Length; index++)
        {
            sequenceCache[index] = -1;
        }
        sequenceCache[1] = 1;

        for (int index = 2; index <= number; index++)
        {
            tempCount = 0;
            temp = index;
            // If the number is repeated then we can find 
            // sequence count from cache
            while (temp != 1 && temp >= index)
            {
                if (temp % 2 == 0)
                    temp = temp / 2;
                else
                    temp = temp * 3 + 1;
                tempCount++;
            }
            sequenceCache[index] = tempCount + sequenceCache[temp];
            if (sequenceCache[index] == maxChain)
            {
                minNumber = index;
            }
        }

        return minNumber;
    }

有关详细信息,请参阅project eulerthis

答案 3 :(得分:1)

递归解决方案

private void ReduceTo1(int input, ref int totalCount)
        {
            totalCount++;
            if (input % 2 == 0)
            {
                input = input / 2;
            }
            else
            {
                input = input * 3 + 1;
            }
            if (input != 1)
                ReduceTo1(input, ref totalCount);               

        }

测试

int desireValue = 0;
            for (int i = 1; i < 100000; i++)
            {
                int totalCount = 0;
                ReduceTo1(i, ref totalCount);
                if (totalCount >= 500)
                {
                    desireValue = i;
                    break;
                }
            }
相关问题