检查几组对是否覆盖给定的一对对

时间:2015-05-09 22:57:29

标签: javascript arrays algorithm data-structures

假设我们有N个数组,例如N=3

1 = [ [3,2], [4,1], [5,1], [7,1], [7,2], [7,3] ]

2 = [ [3,1], [3,2], [4,1], [4,2], [4,3], [5,3], [7,2] ]

3 = [ [4,1], [5,1], [5,2], [7,1] ]

我们可以假设每个数组中的对按第一个数字排序,然后按第二个数字排序。此外,同一对不会多次出现在同一个数组中(同一对可以出现在多个数组中,如上所示)。

每对中的数字是任意整数> = 1.

我怎样才能找到满足的所有k

enter image description here

(简单来说,[k,1], [k,2], ... , [k,N]存在于不同的数组中)

上述示例的预期结果是:[5, 7]

注意:速度是算法最关键的因素,然后是内存。如果它有助于优化速度/内存,请假设N <= 10。数组中的对数可以是~50000。

1 个答案:

答案 0 :(得分:0)

<强>计划

制作一个如下所示的数据对象(称之为datadata={}):

对象中的每个键都是 k 候选者,也就是说,它是所有对中的每个唯一的第一个坐标值。在上面的示例中,键为[3, 4, 5, 7]。键的值是一个元素为1..N的数组,表示A 1 .. A n 。每个阵列中的元素都是第二个坐标值,它出现在与第一个坐标值匹配的数组中。对于上面的例子,data[3][1]=[2]因为坐标[3,1]∈A 2 data[3][2]=[1,2]因为[3,2]∈A 1 和A <子> 2

从那里,查看每个找到的k值。如果data[k]中包含任何少于N个数组,请丢弃它,因为它显然不起作用。

从那里检测P 1 ... P n 是否成立,我的想法是:在data[k]中生成数组的所有排列,每个置换集AP 1 ... AP n (AP = A置换),看看1是否在AP 1 中,2在AP中 2 ......等等。如果找到每个n,我们找到了k!我必须实际编码以确定它是否有效,因此,下面的实际代码。我借用了this函数来生成permations。

    var permArr, usedChars, found;
    //found ks go here
    found = [];

    //needed later
    function permute(input, start) {
        if (start === true) {
            permArr = [];
            usedChars = [];
        }
        var i, ch;
        for (i = 0; i < input.length; i++) {
            ch = input.splice(i, 1)[0];
            usedChars.push(ch);
            if (input.length === 0) {
                permArr.push(usedChars.slice());
            }
            permute(input);
            input.splice(i, 0, ch);
            usedChars.pop();
        }
        return permArr;
    }

    //the main event
    function findK(arrays) {

        //ok, first make an object that looks like this:
        //each key in the object is a k candidate, that is, its every unique first coordinate 
        //value in a pair. the value in array with elements 1..N, which represents A_1..A_n.
        //The elements in that array are each 2nd coordinate value that appears in that array 
        //matched with the first coordinate value, ie, data[3][1] has the array [2] 
        //because coordinate [3,1] is found in A_2.

        data = {};
        var N = arrays.length;
        for (var k = 0; k < N; k++) {
            //0/1 indexing
            var n = k + 1;
            for (var i = 0; i < arrays[k].length; i++) {
                var c1 = arrays[k][i][0];
                var c2 = arrays[k][i][1];
                if (!(c1 in data)) {
                    data[c1] = [];
                }
                if (!(c2 in data[c1])) {
                    data[c1][c2] = [];
                }
                data[c1][c2].push(n);
            }
        }
        data2 = [];


        //next, look at what we have. If any data[k] has less than n elements, disregard it
        //because not all of 1..N is represented. if it does, we need to test that it works,
        //that is, for each n in 1..N, you can find each value in a different array.
        //how do we do that? idea: go through every permutation of the N arrays, then 
        //count up from 1 to n and see if each n is in subarray_n

        //get all permutations
        //make an array from 1 to n
        var arr = [];
        for (var n = 1; n <= N; n++) {
            arr.push(n);
        }
        perms = permute(arr, true);

        for (k in data) {

            if (Object.keys(data[k]).length < N) {
                //not all 3 arrays are represented
                continue;
            }
            else {

                //permute them
                for (i in perms) {
                    if (found.indexOf(k) > -1) {
                        continue;
                    }
                    //permuations
                    //permutated array
                    var permuted = [undefined];
                    for (var j in perms[i]) {
                        permuted.push(data[k][perms[i][j]]);
                    }
                    //we have the permuted array, check for the existence of 1..N
                    var timesFound = 0;
                    console.log(permuted);
                    for (var n = 1; n <= N; n++) {
                        if (permuted[n].indexOf(n) > -1) {
                            timesFound++;
                        }
                    }
                    //if timesFound=N, it worked!
                    if (timesFound === N) {
                        found.push(k);
                    }

                }

                if (found.indexOf(k) > -1) {
                    continue;
                }
            }

        }

        //found is stringy, make it have ints
        for (i = 0; i < found.length; i++) {
            found[i] = parseInt(found[i]);
        }
        return found;
    }

<强>结果

findK( [
            [[3, 2], [4, 1], [5, 1], [7, 1], [7, 2], [7, 3]]
                    , [[3, 1], [3, 2], [4, 1], [4, 2], [4, 3], [5, 3], [7, 2]]
                    , [[4, 1], [5, 1], [5, 2], [7, 1]]
        ] ); //[5,7]