子集序列c#

子集序列c#,c#,sum,duplicates,subset,C#,Sum,Duplicates,Subset,我有一个练习有问题。任务是找到数组中所有和等于N的子集并打印它们。我还需要找到所有唯一的子集,这就是问题所在。我使用灰色方法来寻找所有的组合,但其中一些是重复的。这是我的密码: int matchSum = int.Parse(Console.ReadLine()); int[] numbers = Console.ReadLine().Split().Select(int.Parse).ToArray(); int combinations = (int) Math.P

我有一个练习有问题。任务是找到数组中所有和等于N的子集并打印它们。我还需要找到所有唯一的子集,这就是问题所在。我使用灰色方法来寻找所有的组合,但其中一些是重复的。这是我的密码:

    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.");
    }
int matchSum=int.Parse(Console.ReadLine());
int[]numbers=Console.ReadLine().Split().Select(int.Parse.ToArray();
整数组合=(int)Math.Pow(2,number.Length);
List currentSequence=新列表();
bool-foundMatch=false;
对于(int i=1;i<组合;i++)
{
for(int bit=0;bit>位)&1;
如果(掩码==1)
{
currentSequence.Add(数字[numbers.Length-bit-1]);
}
}
if(currentSequence.Sum()==matchSum)
{
Console.WriteLine(“{0}={1}”,string.Join(“+”,currentSequence),matchSum);
foundMatch=true;
}
currentSequence.Clear();
}
如果(!foundMatch)
{
Console.WriteLine(“无匹配子集”);
}

致以最良好的祝愿

这里是一个回溯算法的实现。它首先对输入集进行排序,然后生成子集并检查总和。这里有三个要点。首先,该算法始终保持当前和,因此不需要在每一步都完全计算当前和。第二,如果当前和大于目标和,它将提前停止。最后,为了生成唯一的子集,后退步骤跳过与前一序列的最后一个数字相等的数字。希望有帮助

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();
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
名称空间示例
{
类样本
{
静态void Main(字符串[]参数)
{
int matchSum=20;//int.Parse(Console.ReadLine());
int[]number={5,1,3,2,5,1,8,7,4};//Console.ReadLine().Split().Select(int.Parse.ToArray();
数组。排序(数字);
var stack=新堆栈();
int matchCount=0,currentSum=0,nextPos=0;
while(true)
{
//下一个
对于(int-nextSum;nextPosmatchSum)中断;
stack.Push(nextPos);
如果(nextSumnumbers[pos]);
stack.Pop();
打破
}
//背
如果(stack.Count==0)中断;
var lastPos=stack.Pop();
var lastNumber=编号[lastPos];
currentSum-=lastNumber;
nextPos=lastppos+1;
while(nextPos
我找到了另一种使用哈希集的方法(谢谢@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.");
        }
    }
}
类程序
{
静态列表currentMatchList=新列表();
静态void Main()
{
int matchSum=int.Parse(Console.ReadLine());
int[]numbers=Console.ReadLine().Split().Select(int.Parse.ToArray();
整数组合=(int)Math.Pow(2,number.Length);
List currentSequence=新列表();
HashSet allResults=新HashSet();
bool-foundMatch=false;
对于(int i=1;i<组合;i++)
{
for(int bit=0;bit>位)&1;
如果(掩码==1)
{
currentSequence.Add(数字[numbers.Length-位-1]);
}
}
if(currentSequence.Sum()==matchSum)
{
字符串temp=“”;
currentSequence.OrderBy(a=>a.ToList().ForEach(a=>temp+=a+);
如果(!allResults.Contains(temp))
{
所有结果。添加(温度);
Console.WriteLine(“{0}={1}”,string.Join(“+”,currentSequence),matchSum);
}
foundMatch=true;
}
currentSequence.Clear();
}
如果(!foundMatch)
{
Console.WriteLine(“无匹配子集”);
}
}
}

创建已找到子集的列表。如果将序列表示为逗号分隔的字符串,则列表将起作用。搜索列表以查看当前子集是否存在。如果子集的数量很大,您可以使用排序列表或哈希集(尽管哈希冲突的可能性很小)。您可以提供一个示例数据吗?所以我们可以理解你的问题。列表中是否只包含正数?@LasseV.Karlsen否。正数和负数可以是。@LasseV.Karlsen这就是想法。如果说输入集只包含正数,那么在开始时(排序后),我会消除排序集末尾大于目标和的所有数字。@LasseV.Karlsen我可能没有很好地解释它。该算法不会停止整个过程,只是“向前”一步。请注意,集合已排序,因此保证下一个数字更大,因此总和也更大。