Find unique sums from 2d array where each array contributes one value which must be unique in sum

◇◆丶佛笑我妖孽 提交于 2020-06-29 03:35:42

问题


The target is to find all unique sums that can be created by adding one int of each array with the restriction that each integer value may only be used once within each final sum. e.g.:

int[][] data = { [ 1, 2, 3], [ 1, 2, 3, 4], [ 4, 5, 6] }

turns to // int[] path = [ int in data[0] , int in data[1], int in data[2] ]

int[][] paths {
[ 1, 2, 4 ] , [ 1, 2, 5 ] , [ 1, 2, 6 ] , 
[ 1, 3, 4 ] , [ 1, 3, 5 ] , [ 1, 3, 6 ] , 
[ 1, 4, 5 ] , [ 1, 4, 6 ] ,
[ 2, 1, 4 ] , [ 2, 1, 5 ] , [ 2, 1, 6 ] ,
[ 2, 3, 4 ] , [ 2, 3, 5 ] , [ 2, 3, 6 ] ,
...
[ 3, 4, 5 ] , [ 3, 4, 6 ]
}

i have visually ordered these to make the process a little clearer, hope that helps. paths is not required at all but ive used this approach in both my attempts to solve this problem and it illustrates how I think about that problem.

finally the result should look like this:

int[] sums = [ 7, 8, 9, 10, 11 .... , 13 ]

where 7 = 1 + 2 + 4 (and duplicates), 8 = 1 + 2 + 5, 9 = 1 + 2 + 6, ..., 13 = 3 + 4 + 6

I hope that my explanation of the problem is clear to you and this is somewhat of a new problem for you aswell.

I've tried an approach with TreeNodes which works well but I think I should be able to improve on speed complexity since e.g. I get the branches : 1-2-4 and 2-1-4 as described above. Ultimately for the solution the second branch is not necessary at all. Basically its just a tree where having the same value for children and parents is not allowed.

I'll leave my code out for the moment since I don't feel its necessarly helpful, please tell me if I'm wrong.

If you find a second to think about the problem and give me feedback in any way that would be greatly appreciated.

I feel like iterating over all possible branches before placing a number to check if it contains the same numbers is a huge timesink. So i fiddled around with something like this which at least improves on space complexity a little bit. Unfortunatley removing duplicate elements is still very time consuming and whilst adding speed when having similar elements in the arrays it is a huge bottleneck when those elements are different.

public static ArrayList<Integer[]> createMultiples(int[][] input) {
            if (input.length == 0) return null;
            int count = 0;
            ArrayList<Integer[]> multiples = new ArrayList<Integer[]>();
            for (int val : input[count]) {
                Integer[] thisvals = new Integer[input.length];
                thisvals[count] = Integer.valueOf(val);
                multiples.add(thisvals);
            }
            if (count + 1 == input.length) return multiples;
            return createMultiples(multiples ,input, ++count);
        }

        public static ArrayList<Integer[]> createMultiples(
ArrayList<Integer[]> multiples, int[][] input, int count) {
            ArrayList<Integer[]> newBranches = new ArrayList<Integer[]>();
            for (int val : input[count]) {
                for (int i = 0; i < multiples.size(); i++) {
                    Integer[] trunk = multiples.get(i);
                    if (!arrContains(trunk, Integer.valueOf(val))) {
                        if (trunk[count] == null) trunk[count] = Integer.valueOf(val);
                        else {
                            Integer[] newBranch = trunk.clone();
                            newBranch[count] = Integer.valueOf(val);
                            newBranches.add(newBranch);
                        }
                    }
                }
            }
            for (Integer[] branch : newBranches) multiples.add(branch);
            multiples = removeDuplicatePaths(multiples);
            if (count + 1 == input.length) return multiples;
            return createMultiples(multiples, input, ++count);
        }

public static ArrayList<Integer[]> removeDuplicatePaths(ArrayList<Integer[]> arrList) {
    ArrayList<Integer[]> retList = new ArrayList<Integer[]>();
    loop: for ( int i = 0; i < arrList.size(); i++ ) {
        //get element
        Integer[] toEval = arrList.get(i);
        //sort element
        Arrays.sort(toEval, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                if (o1 == null && o2 == null) {
                    return 0;
                }
                if (o1 == null) {
                    return 1;
                }
                if (o2 == null) {
                    return -1;
                }
                return o1.compareTo(o2);
            }});
        //check if element is in new list
        for ( int j = 0; j < retList.size(); j++ ) {
            if (Arrays.equals(retList.get(j), toEval)) continue loop;
        }
        retList.add(toEval);
    }
    return retList;
}

回答1:


You are right, saving all the branches is going to take a lot of space and is complicated. You really only need the sums at the end. Could you save something besides all the branches?



来源:https://stackoverflow.com/questions/62325030/find-unique-sums-from-2d-array-where-each-array-contributes-one-value-which-must

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!