【问题标题】:Find all combinations of values between two arrays where values from one may only be used once?查找两个数组之间的所有值组合,其中一个数组的值只能使用一次?
【发布时间】:2020-12-16 23:18:27
【问题描述】:

我有两个非常简单的数组,一个包含characters,另一个包含numbers。在不重复 numbers 数组中的任何值的情况下,我需要找到数组值的所有可能组合。给定以下两个数据集:

char[] characters = { 'a', 'b' };
int[] numbers = { 1, 2, 3 };

预期的输出是:

1a2a3
1a2b3
1b2a3
1b2b3

如果一个数字重复,它应该被计算第二次。例如,如果我们将numbers 数据集更改为1, 2, 2,则预期输出为:

1a2a2
1a2b2
1b2a2
1b2b2

我查看了许多演示使用递归的示例(在某些情况下使用了 Linq),以查找一个数组中值的所有可能组合,甚至是两个数组中的几个样本,但在所有我见过的样本,结果数据集是一对一的映射,例如a1, b1, a2, b2, a3, b3,这不是我需要的。

我尝试了几种不同的方法,但都没有奏效,它们也无法扩展,因此没有必要在此处发布这些方法,因为我一直放弃它们。按照以下思路思考:

foreach (char character in characters) {
    foreach (int number in numbers) {
        for (int i = characters.Length - 1; i > 0; i--) {
            // Not scalable, probably why recursion is used as a solution.
        }
    }
}

由于某种原因,我无法让我的大脑将其移至递归。


如何创建两个数组中值的所有可能组合,其中两个数组的长度都是未知的,并且一个数组中的值不重复(除非在数据集本身中指定)?

注意:结果应存储在List<string> 中以供以后处理。

【问题讨论】:

  • 字符是否保证唯一?只有数字可以重复吗?
  • @Idle_Mind 是的,字符总是唯一的,只能重复数字。
  • 好的。所以本质上我们是在用唯一字符{aa, ab, ba, bb}“计数”,计数序列的固定长度比数字数组的长度小一。然后我们将每个计数序列中的数字放在 numbers 数组中的每个数字之间。我相信我有一个适合你的解决方案,但大约需要一个小时我才能编写代码并对其进行测试。
  • @Idle_Mind 我很感兴趣 :)

标签: c# arrays


【解决方案1】:

下面的CountWithUniqueChars 类只是我的Revision class here 的精简版。

代码:

class Program
{
    static void Main(string[] args)
    {
        string characters = "ab";
        int[] numbers = { 1, 2, 3 };

        int sequenceLength = numbers.Length - 1;
        string startingSequence = new string(characters[0], sequenceLength);
        CountWithUniqueChars sequence = new CountWithUniqueChars(characters, startingSequence);

        StringBuilder sb = new StringBuilder();
        List<string> sequences = new List<string>();
        do
        {
            sb.Clear();
            for(int i=0; i<numbers.Length; i++)
            {
                sb.Append(numbers[i]);
                if (i < (numbers.Length - 1)) {
                    sb.Append(sequence.CurrentSequence[i]);
                }
            }
            sequences.Add(sb.ToString());
            sequence.NextSequence();
        } while (sequence.CurrentSequence.Length == sequenceLength);

        foreach (String curSequence in sequences)
        {
            Console.WriteLine(curSequence);
        }

        Console.Write("Press Enter to Quit...");
        Console.ReadLine();
    }

}

public class CountWithUniqueChars
{

    private string chars;
    private char[] values;

    private System.Text.StringBuilder curSequence;

    public CountWithUniqueChars()
    {
        this.DefaultSequnce();
    }

    public CountWithUniqueChars(string validChars)
    {
        if (validChars.Length > 0)
        {
            chars = validChars;
            values = validChars.ToCharArray();
            curSequence = new System.Text.StringBuilder(values[0]);
        }
        else
        {
            this.DefaultSequnce();
        }
    }

    public CountWithUniqueChars(string validChars, string startingSequence)
        : this(validChars)
    {
        curSequence = new System.Text.StringBuilder(startingSequence);
        int i = 0;
        for (i = 0; i <= curSequence.Length - 1; i++)
        {
            if (Array.IndexOf(values, curSequence[i]) == -1)
            {
                curSequence = new System.Text.StringBuilder(values[0]);
                break;
            }
        }
    }

    private void DefaultSequnce()
    {
        chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        values = chars.ToCharArray();
        curSequence = new System.Text.StringBuilder(values[0]);
    }

    public string ValidChars
    {
        get { return chars; }
    }

    public string CurrentSequence
    {
        get { return curSequence.ToString(); }
    }

    public string NextSequence()
    {
        this.Increment();
        return this.CurrentSequence;
    }

    private void Increment()
    {
        char curChar = curSequence[curSequence.Length - 1];
        int index = Array.IndexOf(values, curChar);
        if (index < (chars.Length - 1))
        {
            index = index + 1;
            curSequence[curSequence.Length - 1] = values[index];
        }
        else
        {
            curSequence[curSequence.Length - 1] = values[0];
            int i = 0;
            int startPosition = curSequence.Length - 2;
            for (i = startPosition; i >= 0; i += -1)
            {
                curChar = curSequence[i];
                index = Array.IndexOf(values, curChar);
                if (index < (values.Length - 1))
                {
                    index = index + 1;
                    curSequence[i] = values[index];
                    return;
                }
                else
                {
                    curSequence[i] = values[0];
                }
            }
            curSequence.Insert(0, values[0]);
        }
    }

}

输出:

1a2a3
1a2b3
1b2a3
1b2b3
Press Enter to Quit...

另一个使用不同输入的例子:

string characters = "abc";
int[] numbers = { 1, 2, 3, 4};

输出:

1a2a3a4
1a2a3b4
1a2a3c4
1a2b3a4
1a2b3b4
1a2b3c4
1a2c3a4
1a2c3b4
1a2c3c4
1b2a3a4
1b2a3b4
1b2a3c4
1b2b3a4
1b2b3b4
1b2b3c4
1b2c3a4
1b2c3b4
1b2c3c4
1c2a3a4
1c2a3b4
1c2a3c4
1c2b3a4
1c2b3b4
1c2b3c4
1c2c3a4
1c2c3b4
1c2c3c4
Press Enter to Quit...

【讨论】:

  • 我还没有机会真正深入研究这个问题,抱歉。我希望今晚能测试一下!再次感谢您帮助我们解答!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-12
  • 1970-01-01
  • 1970-01-01
  • 2016-07-24
相关资源
最近更新 更多