给定约束的java中最大大小的子集

时间:2016-07-31 05:33:03

标签: java algorithm

我有一个整数数组的arraylist如下 -

27 14 62 
15 92 15 
16 40 90 
61 23 78 
23 70 90 
25 93 98

我想找到所有最大尺寸的子集,以便

 a1[0]<a2[0] && a1[1]<a2[1] && a1[2] <a2[2] 

我做了什么 - 1)我按升序排列了arraylist的每一行。 2)然后我使用比较器对整个arraylist进行了排序 所以我明白了 -

14 27 62 
15 85 92 
16 40 90 
23 61 78 
23 70 90 
25 93 98

但现在,我被困住了。我不知道如何根据上述约束找到所有最大尺寸的子集。 例如,在上面的例子中, -

14 27 62 
15 85 92 
25 93 98

14 27 62     
23 61 78  
25 93 98

14 27 62 
23 70 90 
25 93 98

是可能的最大尺寸子集。

2 个答案:

答案 0 :(得分:1)

在检查约束之前是否真的允许对各个数组进行排序?以下算法应该以任何一种方式工作。

以下算法应该在O(n 2 )中找到一个最大集合(你需要全部吗?在这种情况下,最坏的情况是指数):

  1. 构建有向非循环图,其中各个数组是节点,并且当且仅当b可以根据约束遵循a时,节点a和b之间存在边缘。
  2. 对此图表进行拓扑排序。
  3. 以排序顺序逐步遍历节点(从&#34;最小的&#34;节点开始)并计算每个节点x最大的子集,其中x为&#34;最大的&#34;节点。这可以通过查看所有先前的节点来完成y:用仅包含x的子集初始化,然后对于所有y:如果x可以跟随y将x加到为y计算的最大子集,如果该子集大于先前的y x的子集记住它是最大的。
  4. 以线性方式通过所有节点找到整体最大的子集。
  5. 示例:

    14 27 62 
    15 85 92 
    16 40 90 
    23 61 78 
    23 70 90 
    25 93 98
    

    已经按照拓扑顺序排列。所以我们逐行计算:

    14 27 62 -> 14 27 62
    15 85 92 -> 14 27 62, 15 85 92
    16 40 90 -> 14 27 62, 16 40 90
    23 61 78 -> 14 27 62, 23 61 78
    23 70 90 -> 14 27 62, 23 70 90
    25 93 98 -> 14 27 62, 15 85 92, 25 93 98
    

答案 1 :(得分:1)

考虑这个算法:

  1. 对于每个row,请开始跟踪subset
  2. 每个后续的row2
    1. 如果row < row2,则添加到子集,然后从步骤2递归继续
  3. subset的大小与之前保存的子集进行比较:
    1. 如果更大,则删除所有以前保存的子集,然后保存此子集
    2. 如果相等,则将此子集添加到先前保存的子集列表
  4. 尽管此算法的时间复杂度是指数级的,但它实现起来相当容易,对于较小的数据集可能已经足够了。

    List<List<int[]>> findMaximumSubsets(int[][] arr) {
        List<List<int[]>> acc = new ArrayList<>();
        for (int i = 0; i < arr.length - 1; i++) {
            findMaximumSubsets(arr, i, acc, new ArrayList<>(Collections.singletonList(arr[i])));
        }
        return acc;
    }
    
    void findMaximumSubsets(int[][] arr, int row, List<List<int[]>> acc, List<int[]> current) {
        for (int i = row + 1; i < arr.length; i++) {
            if (comparator.compare(arr[row], arr[i]) < 0) {
                // ... (not spoiling for you ...)
            }
        }
    }
    
    Comparator<int[]> comparator = new Comparator<int[]>() {
        @Override
        public int compare(int[] a1, int[] a2) {
            int cmp1 = Integer.compare(a1[0], a2[0]);
            if (cmp1 > -1) {
                return 0;
            }
            int cmp2 = Integer.compare(a1[1], a2[1]);
            if (cmp2 > -1) {
                return 0;
            }
            return Integer.compare(a1[2], a2[2]);
        }
    };