如何找到满足条件的确切数字?

时间:2015-03-13 02:04:18

标签: c# backtracking

我在数组中有一定数量的整数。让我们说:{1,2,3,4,5,6,7}。请注意,这只是一个例子,它们可能不是连续的数字。

我需要找到满足以下条件的数字:

  1. 这些数字有一笔固定金额。
  2. 应指定数字的计数。
  3. 所以上面给出的数字是:

    1. 如果总和为7且数量为2,则应输出{1,6}。
    2. 如果总和为7且数量为3,则应输出{1,2, 4}。
    3. 如果总和为7且数字计数为1,则应输出{7}。
    4. 我发现了类似的帖子:algorithm to find the correct set of numbers。然而,那里的算法不需要指定数量计数。这是算法归功于Lajos Arpad

      public static List<int> backtrack(List<int> currentNumbers, int[] numbers, int depth, int targetValue, int j)
          {
              for (int i = j; i < numbers.Length; i++)
              {
                  int potentialSolution = numbers[i];
                  if (currentNumbers.Sum() + potentialSolution > targetValue)
                  {
                      continue;
                  }
                  else if (currentNumbers.Sum() + potentialSolution == targetValue)
                  {
                      /*Store solution*/
                      currentNumbers.Add(potentialSolution);
      
                      return currentNumbers;
                  }
                  else
                  {
                      currentNumbers.Add(potentialSolution);
      
                      return backtrack(currentNumbers, numbers, depth + 1, targetValue, i + 1);
                  }
              }
      
              return null;
          }
      

      有人可以帮我修改它以添加额外数字计数条件吗?

1 个答案:

答案 0 :(得分:0)

感谢Rufus L和他的帖子here。这是对他的代码的简单修改。

    private static void GetSumsRecursively(
        List<int> numbers,
        int sum, 
        List<int> candidates, 
        int numbersCount,
        List<List<int>> results)
    {
        int candidateSum = candidates.Sum(x => x);

        if (candidateSum == sum && candidates.Count == numbersCount)
        {
            results.Add(candidates);
        }

        if (candidateSum >= sum)
            return;

        for (int i = 0; i < numbers.Count; i++)
        {
            var remaining = new List<int>();

            for (int j = i + 1; j < numbers.Count; j++)
            {
                remaining.Add(numbers[j]);
            }

            var filteredCandidates = new List<int>(candidates) { numbers[i] };

            GetSumsRecursively(remaining, sum, filteredCandidates,
                numbersCount, results);
        }
    }

    public static List<List<int>> GetNumbers(
        List<int> numbers,
        int numbersCount, 
        int sum)
    {
        if (numbers == null) throw new ArgumentNullException("numbers");

        var results = new List<List<int>>();

        // Fail fast argument validation
        if (numbersCount < 1 ||
            numbersCount > numbers.Count /*||
            sumDifficulty < numQuestions * Question.MinDifficulty ||
            sumDifficulty > numQuestions * Question.MaxDifficulty*/)
        {
            return results;
        }

        // If we only need single questions, no need to do any recursion
        if (numbersCount == 1)
        {
            results.AddRange(numbers.Where(q => q == sum)
                .Select(q => new List<int> { q }));

            return results;
        }

        // We can remove any questions who have a difficulty that's higher
        // than the sumDifficulty minus the number of questions plus one
        var candidateQuestions =
            numbers.Where(q => q <= sum - numbersCount + 1)
                .ToList();

        if (!candidateQuestions.Any())
        {
            return results;
        }

        GetSumsRecursively(candidateQuestions, sum, new List<int>(),
            numbersCount, results);

        return results;
    }