查找不可分的子集

时间:2016-09-02 03:37:06

标签: java logic

给定n个不同整数的集合S,打印S的最大子集S的大小,其中S'中的任意2个数字的总和。不能被k整除。 n =数组中的项数,k =要除以的数。 S =数组

    eg: Input from STDIN
   10 5
   770528134 663501748 384261537 800309024 103668401 538539662 385488901   101262949 557792122 46058493

    eg: Input from STDIN
    4 3
    1 7 2 4

    Explanation :

    1+7 = 8 : 8 is not evenly divisible
    1+4 = 5 : 5 is not evenly divisible
    7+4 = 11: 11 is not evenly divisible

    1+2 = 3
    2+4 =6
    2+7 = 9

    Those are divisible by 3, so the subset S' = {1,7,4) of size 3.

代码:

    public static void main(String[] args) {
            Scanner in = new Scanner(System.in);

            int n = in.nextInt();

            int k = in.nextInt();

            long arr[] = new long[n];

            for (int i = 0; i < n; i++) {
                arr[i] = in.nextInt();
            }


            final Set<Long> subset = new LinkedHashSet<>();

            for (int i = 0; i < n; i++) {

                for (int j = i + 1; j < n; j++) {

                    long sum = arr[i] + arr[j];

                    if (sum % k != 0) {

                        subset.add(arr[i]);
                        subset.add(arr[j]);
                    }
                }
            }

            System.out.println(subset.size());
        }

我得到第二个输入的正确答案即。 3.但是,第一次输入我得到9,我期待吐出6。

1 个答案:

答案 0 :(得分:1)

我不能轻易按照你的算法中的想法。是什么让你认为它应该有效?

相反,这是另一个想法。规则是,如果i,基本集中的两个元素j(i + j) % k == 0都不能同时进入子集。假设i和j都是正数,则与(i % k == 0 && j % k == 0) || i % k + j % k == k相同。所以我想用剩余模数k对元素进行分组。对于具有余数rk - r(1&lt; = r&lt; k)的任何两个这样的组,我可以安全地将一个组添加到子集中,并且我将想要添加两个中的较大者。我还可以从组中添加一个元素,余数为0(不是两个,因为它们的和可以被k整除)。如果k是偶数,我也可以只从组中添加一个余数为k / 2的元素。

编辑:代码可能更精确,所以这里是:

// assume all elements > 0
static Set<Integer> findLargestSubset(int k, int... baseSetElements) {
    List<Integer> asList = IntStream.of(baseSetElements).boxed().collect(Collectors.toList());
    Set<Integer> baseSet = new HashSet<Integer>(asList);
    int n = baseSet.size();

    // group elements from set by their remainder modulus k
    List<List<Integer>> elementsByModulus = new ArrayList<>();
    for (int ix = 0; ix < k; ix++) {
        elementsByModulus.add(new ArrayList<>());
    }
    for (int i : baseSet) {
        if (i <= 0) {
            throw new IllegalArgumentException("" + i);
        }
        elementsByModulus.get(i % k).add(i);
    }
    Set<Integer> largestSubset = new HashSet<>(n);
    for (int remainder = 1; remainder < (k + 1) / 2; remainder++) {
        List<Integer> groupR = elementsByModulus.get(remainder);
        List<Integer> groupKMinusR = elementsByModulus.get(k - remainder);
        // add larger group to result
        if (groupR.size() > groupKMinusR.size()) {
            largestSubset.addAll(groupR);
        } else {
            largestSubset.addAll(groupKMinusR);
        }
    }
    // add one element with remainder 0 if any
    if (!elementsByModulus.get(0).isEmpty()) {
        largestSubset.add(elementsByModulus.get(0).get(0));
    }
    // if k is even, add one element with remainder k / 2 if any
    if (k % 2 == 0 && !elementsByModulus.get(k / 2).isEmpty()) {
        largestSubset.add(elementsByModulus.get(k / 2).get(0));
    }
    return largestSubset;
}

对于您问题中的第一个示例,这会给出[800309024, 557792122, 384261537, 538539662, 770528134, 101262949],因此大小为6。