找到与数字相加的所有组合

时间:2017-07-23 18:51:34

标签: c# .net recursion

给定正整数n find和所有正整数集合总和为n

so 4 would be 
1 1 1 1 
2 1 1
3 1
2 2

我认为这产生了正确的数字,但我无法弄清楚如何打包结果。

public static IEnumerable<List<int>> BreakMeDown(int n)
{
    for (int i = 1, j = n - 1; i <= j; i++, j--)
    {
        List<int> breakMeDown = new List<int>();
        breakMeDown.Add(i);
        breakMeDown.Add(j);
        yield return breakMeDown;
        //Debug.WriteLine($"{i} {j}"); 
        foreach (List<int> li in BreakMeDown(i))
            yield return li;
        foreach (List<int> li in BreakMeDown(j))
            yield return li;                               
    }
}

// test
foreach (List<int> li in BreakMeDown(7))
    Debug.WriteLine(string.Join(", ", li));

2 个答案:

答案 0 :(得分:1)

我们走了:

static void Main(string[] args)
{
    foreach (var li in BreakMeDown(7))
        Console.WriteLine(string.Join(", ", li));
}

public static IEnumerable<IReadOnlyCollection<int>> BreakMeDown(int n)
{
    for (int i = 1, j = n - 1; i <= j; i++, j--)
    {
        foreach (var li in BreakMeDown(j).Select(bd => bd.Concat(new[] {i}).ToList()))
            yield return li;
        foreach (var li in BreakMeDown(i).Select(bd => bd.Concat(new[] {j}).ToList()))
            yield return li;
        yield return new[] {i, j};
    }
}

编辑:

好的,基于您想要对结果序列进行重复数据删除的注释。在这种情况下,要使用的正确数据结构是将整数映射到出现次数的字典。例如。 { 1: 5 }表示可能的细分为5,其中数字1重复5次。

这是代码(我依赖于MoreLinq和Json.NET,因为我不想为Dictionary实现DistinctBy和IEqualityComparer,但如果你愿意,你可以自己做这些:)

    static void Main(string[] args)
    {
        foreach (var li in BreakMeDown(5).DistinctBy(JsonConvert.SerializeObject))
            Console.WriteLine(string.Join(", ", li));
    }

    static IImmutableDictionary<int, int> Increment(this IImmutableDictionary<int, int> dict, int i)
    {
        return dict.SetItem(i, dict.TryGetValue(i, out int iCount) ? iCount + 1 : 1);
    }

    public static IEnumerable<IImmutableDictionary<int, int>> BreakMeDown(int n)
    {
        for (int i = 1, j = n - 1; i <= j; i++, j--)
        {
            var iAndJ = ImmutableSortedDictionary.Create<int, int>().Increment(i).Increment(j);
            var bdJ = BreakMeDown(j).Select(bd => bd.Increment(i));
            var bdI = BreakMeDown(i).Select(bd => bd.Increment(j));

            var list = bdI.Concat(bdJ).Concat(new[] { iAndJ });
            foreach (var li in list)
            {
                yield return li;
            }
        }
    }

答案 1 :(得分:1)

我认为你正在寻找这个(现在不能对它进行测试,所以我不会100%肯定会按预期工作):

public static IEnumerable<List<int>> BreakMeDown(int n)
{
    for (int i = 1, j = n - 1; i <= j; i++, j--)
    {
        List<int> breakMeDown = new List<int>();
        breakMeDown.Add(i);
        breakMeDown.Add(j);
        yield return breakMeDown;

        foreach (List<int> li in BreakMeDown(i))
            yield return breakMeDown.Skip(1)
                                    .Concat(li)
                                    .ToList();

        if (i != j)
        {
            foreach (List<int> li in BreakMeDown(j))
                yield return breakMeDown.Take(1)
                                        .Concat(li)
                                        .ToList();
        }
    }
}

当您构建递归细分时,您需要将结果连接到已构建的2因子细分,忽略您正在进一步细分的因素。