【问题标题】:Find all possible combinations of paired elements between two arrays, without repeating any of the elements from either array?找出两个数组之间所有可能的配对元素组合,而不重复任一数组中的任何元素?
【发布时间】:2021-06-14 02:27:29
【问题描述】:

我正在尝试找出一个函数的逻辑,该函数将找到两个源数组之间元素的所有可能组合,而不重复任一数组中的任何元素。

换句话说,每个源数组中的元素都被视为有限资源。由此,构建对的组合,直到任一源数组的元素用完,然后是下一个对的组合,然后是下一个,直到所有排列都被考虑在内。

例如,

get_combinations( [1, 2, 3], ["a", "b", "c"] );

应该返回

    [ [1, "a"], [2, "b"], [3, "c"] ],
    [ [1, "a"], [2, "c"], [3, "b"] ],
    [ [1, "b"], [2, "a"], [3, "c"] ],
    [ [1, "b"], [2, "c"], [3, "a"] ],
    [ [1, "c"], [2, "a"], [3, "b"] ],
    [ [1, "c"], [2, "b"], [3, "a"] ]
]

(为清晰起见格式化)

我将把它用于一个基于 PHP 的项目,但我主要是在寻找一种算法,而不是一种特定于语言的实现。


以大小不等的数组为例,

get_combinations( [1, 2, 3, 4] and ["a", "b"] );

会回来

    [ [1, "a"], [2, "b"] ], [ [1, "a"], [3, "b"] ], [ [1, "a"], [4, "b"] ],
    [ [2, "a"], [1, "b"] ], [ [2, "a"], [3, "b"] ], [ [2, "a"], [4, "b"] ],
    [ [3, "a"], [1, "b"] ], [ [3, "a"], [2, "b"] ], [ [3, "a"], [4, "b"] ],
    [ [4, "a"], [1, "b"] ], [ [4, "a"], [2, "b"] ], [ [4, "a"], [3, "b"] ]
]

【问题讨论】:

  • 所以结果只是第二个数组的所有排列,结合第一个数组的初始序列。很容易找到数组排列的 PHP 实现(对于相当小的数组是递归的,对于迭代方式的 next_permutation 方法)。还是你的问题真的更难?
  • 如果两个数组的大小相同,就会这样。否则,它不会成立。
  • @Malkalypse,不需要相同的大小,也可以使用可变长度的数组。查看我给出的代码。
  • @Malkalypse 值得为不同大小的数组显示所需的结果。
  • 我添加了一个不等大小数组的示例。

标签: arrays algorithm logic


【解决方案1】:

您可以使用此算法来查找组合。这也适用于两个以上的数组。

static void print(List<string>[] arr)
{
    int[] indices = new int[arr.Length];

    for (int i = 0; i < arr.Length; i++)
        indices[i] = 0;

    while (true)
    {
        // Print current combination
        for (int i = 0; i < arr.Length; i++)
            Console.Write(arr[i][indices[i]] + " ");

        Console.WriteLine();
        int next = arr.Length - 1;
        while (next >= 0 &&
              (indices[next] + 1 >=
               arr[next].Count))
            next--;
        if (next < 0)
            return;
        indices[next]++;
        for (int i = next + 1; i < arr.Length; i++)
            indices[i] = 0;
    }
}

从 main 调用上述方法

static void Main(string[] args)
{
    List<string>[] arr = new List<string>[2];
    for (int i = 0; i < arr.Length; i++)
        arr[i] = new List<string>();

    // Now entering data
    // [["1", "2", "3"], ["a", "b", "c"]]
    arr[0].Add("1");
    arr[0].Add("2");
    arr[0].Add("3");
    arr[1].Add("a");
    arr[1].Add("b");
    arr[1].Add("c");

    print(arr);
}

// 输入 => [["1", "2", "3"], ["a", "b", "c"]]

// 输出

1个

1b

1 杯

2个

2b

2 杯

3个

3b

3 杯

// 输入 => [["1", "2", "3"], ["a", "b", "c"], ["x", " y", "z"]]

List<string>[] arr = new List<string>[3];
for (int i = 0; i < arr.Length; i++)
    arr[i] = new List<string>();

// Now entering data
// [["1", "2", "3"], ["a", "b", "c"], ["x", "y", "z"]]
arr[0].Add("1");
arr[0].Add("2");
arr[0].Add("3");
arr[1].Add("a");
arr[1].Add("b");
arr[1].Add("c");
arr[2].Add("x");
arr[2].Add("y");
arr[2].Add("z");

//输出

1 个 x

1 年

1个z

1 b x

1 年

1 b z

1 c x

1 年

1 c z

2个x

2 一年

2个z

2 b x

2 年

2 b z

2 c x

2 年

2 c z

3 个 x

3 年

3个z

3 b x

3 年

3 b z

3 c x

3 岁

3 c z

即使这也适用于可变长度的数组,例如

// 输入 => [["1", "2", "3"], ["x"], ["a", "b"]]

//输出 =>

1 x 一个

1 x b

2 x 一个

2 x b

3 x 一个

3 x b

【讨论】:

  • 恐怕这不是我想要的。这些只是单独的配对(或三倍等)值。我需要将这些对组合在一起,组合成使用至少一个源数组的所有值的组合。
【解决方案2】:

我能够找到一位过去曾帮助我解决这个问题的程序员作为 php 实现。这是她提供的代码,添加了一些小的调整和 cmets。

class GetArrayPermutations{

    public $_arrays;
    public $_order = 0;

    public $_array_combinations;
    public $_array_permutations;

    public function __construct( $arrays ){
        $this->_arrays = $arrays;
        $this->_array_combinations = $this->get_array_combinations( $arrays );
        $this->_array_permutations = $this->get_array_permutations( $this->_array_combinations );
    }


    public function get_array_combinations( $arrays ){
        
        // Order array elements to ensure larger array is second
        if( sizeof( $arrays[0] ) > sizeof( $arrays[1] ) ){
            $arrays = array_reverse($arrays);
            $this->_order = 1;
        }
        
        //$arrays = array_values( $arrays );
        $second = sizeof( $arrays[1] );     
        $size   = sizeof( $arrays[0] ) * $second;
        $result = array(); // initialize $result as an array

        // Collect all possible combinations of arrays
        for( $i = 0; $i < $size; $i++ ){

            // Initialize array for index
            $result[$i] = array(); 

            // Store one value from each array together
            for( $j = 0; $j < 2; $j++ ){        
                array_push( $result[$i], current( $arrays[$j] ) );
            }

            // Advance through combinations
            for ($j = 1; $j >= 0; $j-- ){
                if( next( $arrays[$j] ) ) break;
                if( isset( $arrays[$j] ) ) reset( $arrays[$j] );
            }

        }

        $output = [];
        $output2 = [];

        // Combine values of $result into arrays with shared first value and unique second value
        foreach( $result as $key => $value ){

            // Add key/value pair to $output subarray
            $output += [$key => $value];

            // Once each sub-array is finished
            // Add the sub-array to $output2 and start a fresh sub-array    
            if( ( $key + 1 ) % $second == 0 ){  
                array_push( $output2, $output );
                $output = [];
            }

        }

        return $output2;

    }


    public function get_array_permutations( $arrays ){

        //$arrays = array_values( $arrays );
        $sizeIn = sizeof( $arrays );
        $size   = pow( sizeof( $arrays[0] ), $sizeIn );
        $result = array();  

        // Collect all possible permutations of arrays
        for( $i = 0; $i < $size; $i++ ){

            // Initialize array for index
            $result[$i] = array();

            // Store combination of values from arrays
            for ($j = 0; $j < $sizeIn; $j ++){
                array_push( $result[$i], current( $arrays[$j] ) );
            }

            // Advance through combinations
            for ($j = $sizeIn - 1; $j >= 0; $j--){
                if( next( $arrays[$j] ) ) break;
                if( isset( $arrays[$j] ) ) reset( $arrays[$j] );
            }

        }

        $output = [];
        $output2 = [];
        
        // Iterate through values of $result array
        foreach( $result as $key => $value) {

            // Collect unique second values from each sub-array
            $tempArr = array_unique( array_column( $value, '1' ) );

            if( sizeof( $value ) == sizeof( $tempArr ) ){ // if all second sub-array values are unique

                // Restore input array value sequence, if necessary
                if( $this->_order == 1){
                    foreach( $value as $k => $val ){
                        $temp       = $val[0];
                        $val[0]     = $val[1];
                        $val[1]     = $temp;
                        $value[$k]  = $val;
                    }
                }

                // Add key/value pair to $output
                $output += [$key => $value];

            }

        }

        return $output;

    }

}

$GAP = new GetArrayPermutations( array(
    [1, 2, 3, 4],
    ["a", "b", "c", "d"]    
) );

echo '<pre>'; print_r( $GAP->_array_permutations ); echo '</pre>';

【讨论】:

    猜你喜欢
    • 2013-11-27
    • 2015-09-16
    • 2023-04-10
    • 2023-03-02
    • 2013-03-15
    • 1970-01-01
    • 2016-01-25
    • 2022-09-28
    相关资源
    最近更新 更多