子集序列c#
我有一个练习有问题。任务是找到数组中所有和等于N的子集并打印它们。我还需要找到所有唯一的子集,这就是问题所在。我使用灰色方法来寻找所有的组合,但其中一些是重复的。这是我的密码:子集序列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
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我可能没有很好地解释它。该算法不会停止整个过程,只是“向前”一步。请注意,集合已排序,因此保证下一个数字更大,因此总和也更大。