子集序列c#

时间:2015-09-15 19:44:01

标签: c# sum duplicates subset

我有一个练习有问题。任务是找到数组中所有总和等于N的子集并打印它们。此外,我需要找到所有独特的子集,这是问题所在。我使用Gray方法查找所有组合,但其中一些是重复的。这是我的代码:

    int matchSum = int.Parse(Console.ReadLine());
    int[] numbers = Console.ReadLine().Split().Select(int.Parse).ToArray();
    int combinations = (int) Math.Pow(2, numbers.Length);
    List<int> currentSequence = new List<int>();

    bool foundMatch = false;

    for (int i = 1; i < combinations; i++)
    {
        for (int bit = 0; bit < Convert.ToString(i,2).Length; bit++)
        {
            int mask = (i >> bit) & 1;
            if (mask == 1)
            {
                currentSequence.Add(numbers[numbers.Length-bit-1]);
            }
        }
        if (currentSequence.Sum() == matchSum)
        {
            Console.WriteLine("{0} = {1}", string.Join(" + ", currentSequence), matchSum);
            foundMatch = true;
        }
        currentSequence.Clear();
    }

    if (!foundMatch)
    {
        Console.WriteLine("No matching subsets.");
    }

祝你好运!

2 个答案:

答案 0 :(得分:0)

这是一个回溯算法实现。它的工作原理是首先对输入集进行排序,然后生成子集并检查总和。有3个关键点。首先,算法始终保持当前的总和,因此不需要在每一步完全计算它。其次,如果当前总和大于目标总和,则提前停止。最后,为了生成唯一的子集,后退步骤会跳过等于前一个序列的最后一个数字的数字。希望有所帮助。

using System;
using System.Collections.Generic;
using System.Linq;

namespace Samples
{
    class Sample
    {
        static void Main(string[] args)
        {
            int matchSum = 20; // int.Parse(Console.ReadLine());
            int[] numbers = { 5, 1, 3, 2, 5, 1, 8, 7, 4 }; // Console.ReadLine().Split().Select(int.Parse).ToArray();

            Array.Sort(numbers);
            var stack = new Stack<int>();
            int matchCount = 0, currentSum = 0, nextPos = 0;
            while (true)
            {
                // Next
                for (int nextSum; nextPos < numbers.Length; currentSum = nextSum, nextPos++)
                {
                    nextSum = currentSum + numbers[nextPos];
                    if (nextSum > matchSum) break;
                    stack.Push(nextPos);
                    if (nextSum < matchSum) continue;
                    matchCount++;
                    Console.WriteLine("{0} = {1}", matchSum, string.Join(" + ", stack.Reverse().Select(pos => numbers[pos])));
                    stack.Pop();
                    break;
                }
                // Back
                if (stack.Count == 0) break;
                var lastPos = stack.Pop();
                var lastNumber = numbers[lastPos];
                currentSum -= lastNumber;
                nextPos = lastPos + 1;
                while (nextPos < numbers.Length && numbers[nextPos] == lastNumber)
                    nextPos++;
            }
            if (matchCount == 0)
            {
                Console.WriteLine("No matching subsets.");
            }
            Console.ReadLine();
        }
    }
}

答案 1 :(得分:0)

我找到了另一种使用HashSet的方式(感谢@Eric J.)。     使用系统;     使用System.Collections.Generic;     使用System.Linq;

class Program
{
    static List<int> currentMatchList = new List<int>();
    static void Main()
    {
        int matchSum = int.Parse(Console.ReadLine());
        int[] numbers = Console.ReadLine().Split().Select(int.Parse).ToArray();
        int combinations = (int)Math.Pow(2, numbers.Length);
        List<int> currentSequence = new List<int>();
        HashSet<string> allResults = new HashSet<string>();

        bool foundMatch = false;

        for (int i = 1; i < combinations; i++)
        {
            for (int bit = 0; bit < Convert.ToString(i, 2).Length; bit++)
            {
                int mask = (i >> bit) & 1;
                if (mask == 1)
                {
                    currentSequence.Add(numbers[numbers.Length - bit - 1]);
                }
            }
            if (currentSequence.Sum() == matchSum)
            {
                string temp = "";
                currentSequence.OrderBy(a => a).ToList().ForEach(a => temp += a + " ");
                if (!allResults.Contains(temp))
                {
                    allResults.Add(temp);
                    Console.WriteLine("{0} = {1}", string.Join(" + ", currentSequence), matchSum);
                }
                foundMatch = true;
            }
            currentSequence.Clear();
        }

        if (!foundMatch)
        {
            Console.WriteLine("No matching subsets.");
        }
    }
}