简体   繁体   中英

Find the largest subset of a set of numbers such that the sum of any 2 numbers is not divisible by a given number

I'm trying to solve the Hackerrank problem Non-Divisible Subset stated below:

在此输入图像描述

I attempted the following solution (which works for the sample test case):

# The lines below are for Hackerrank submissions
# n, k = map(int, raw_input().strip().split(' '))
    # a = map(int, raw_input().strip().split(' '))

n = 4
k = 3
a = [1, 7, 2, 4]

while True:
    all_pairs = [(a[i],a[j]) for i in range(len(a)) for j in range(i+1,len(a))]
    tested_pairs = {pair: (pair[0] + pair[1]) % k != 0 for pair in all_pairs}
    disqualified_pairs = {key: value for key, value in tested_pairs.iteritems() if not value}.keys()
    if not disqualified_pairs:
        break
    occurrences = list(sum(disqualified_pairs, ()))
    counts = map(lambda x: occurrences.count(x), a)
    index_remove = counts.index(max(counts))
    a.remove(index_remove)

print len(a)

What I'm trying to do is identify the 'offending' pairs and removing the element of a which occurs most frequently, until there are no 'offending' pairs left.

However, I'm getting "RunTime Error" for most of the test cases:

在此输入图像描述

Presumably the algorithm above works in this simple case where only one number (the number 2) needs to be removed, but fails in more complicated test cases. Can anyone see what is wrong with it?

UPDATE

Following poke's suggestion to test k = 2 and a = [1, 2, 3] , I made the following modifications:

n = 4
k = 2
a = [1, 2, 3]

while True:
    all_pairs = [(a[i],a[j]) for i in range(len(a)) for j in range(i+1,len(a))]
    disqualified_pairs = [pair for pair in all_pairs if (pair[0] + pair[1]) % k == 0]
    if not disqualified_pairs:
        break
    offending_numbers = sum(disqualified_pairs, ())   # 'Flatten' the disqualified pairs into a single list
    counts = {el: offending_numbers.count(el) for el in set(offending_numbers)}     # Count occurrences of each offending number
    number_to_remove = max(counts, key=counts.__getitem__)
    a.remove(number_to_remove)

print len(a)

The resulting a is [2, 3] and contains two elements as expected. I've also checked that it still works for the original example. However, I am still getting a "Segmentation Fault" on some of the test cases:

在此输入图像描述

According to https://www.hackerrank.com/challenges/pairs/forum/comments/9154 , segmentation faults typically occur because of invalid memory access (array indices which don't exist, etc.). I still haven't managed to find any other test cases, though, where the algorithm fails. Any ideas?

Instead of generating all pairs, this could be done by counting modulus.

Time Complexity: O(n + k)

Space Complexity: O(k) or O(1), because k is 100 at max, O(k) => O(1)


Basic idea

(a + b) % k = ((a % k) + (b % k)) % k

Since (a % k) is in range [0, k-1],

(a % k) + (b % k) is in range [0, 2k-2]

In addition,

(a + b) % k = 0 when

  1. (a % k) = 0 and (b % k) = 0 OR

  2. (a % k) + (b % k) = k

Main idea

  1. Based on condition 2, when you choose any value of modulus i, you can choose any value of any modulus, except modulus ki.
  2. In most case, there is no conflict to choose more than one value of modulus i.
  3. Based on condition 1, you can choose at most 1 value from modulus 0
  4. When k is even, k/2 + k/2 = k. You can choose at most 1 value from modulus k/2 when k is even

Base on the above information, the solution could be

  1. If n<2, return n
  2. Create an array of size k with all initial value 0, denote as Arr, to store modulus count
  3. Loop on array a with index i from 0 to n-1, add 1 to Arr[ a[i]%k ]
  4. Initialize a counter with initial value 0
  5. Loop on array Arr with index i from 1 to k-(k/2)-1, add Max(Arr[i], Arr[ki]) to counter
  6. If Arr[0] > 0, add 1 to counter
  7. If k%2 = 0 and Arr[k/2] > 0, add 1 to counter
  8. return counter

The method I used was:

1. find power set of given list of integers.
2. sort power set by subset size.
3. iterate down the sorted power set and print if subset meets problem's conditions.

In java:

import java.util.*;
public class f implements Comparator<List<?>> {

    @Override
    public int compare(List<?> o1, List<?> o2) {
        return Integer.valueOf(o1.size()).compareTo(o2.size());
    }
    static ArrayList<ArrayList<Integer>> powerSet = new ArrayList<>();

    // get power set of arr
    static void g(int arr[],int[] numbers,int i){
        if(i==arr.length){
            ArrayList<Integer> tmp = new ArrayList<>();
            for(int j = 0;j<arr.length;j++){
                if(arr[j]==1) tmp.add(numbers[j]);
            }
            powerSet.add(tmp);
            return;
        }
        arr[i] = 1;
        g(arr,numbers,i+1);
        arr[i] = 0;
        g(arr,numbers,i+1);
    }
    static void h(int[] a){
        int[] arr=new int[a.length];
        for(int j =0;j<arr.length;j++){
            arr[j]=0;
        }
        g(arr,a,0);
    }
    // check whether the sum of any numbers in subset are not evenly divisible by k
    static boolean condition(ArrayList<Integer> set,int k){
        for(int i = 0;i<set.size();i++){
            for(int j = i+1;j<set.size();j++){
                if((set.get(i)+set.get(j))%k==0){
                    return false;
                }
            }
        }
        return true;
    }

    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int k = in.nextInt();
        int[] a = new int[n];
        for (int i=0;i<n;i++){
            a[i]=in.nextInt();
        }


        h(a);
        Collections.sort(powerSet, new f());
        for(int i=powerSet.size()-1;i>0;i--){
            if(condition(powerSet.get(i),k)){
                System.out.println(powerSet.get(i).size());
                break;
            }
        }

    }
}

Results: 服从 Test case #9 error was the result of StackOverflowError:

在此输入图像描述

Not really familiar with hackerrank errors but maybe your error is similar.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM