Алгоритм группировки Java - PullRequest
0 голосов
/ 18 мая 2011

Учитывая массив целых чисел, можно ли выбрать группу некоторых целых чисел, такую, чтобы эта сумма суммировалась с заданной целью, с этим дополнительным ограничением: если в массиве есть числа, которые являются смежными и идентичными ценность, они должны или все быть выбраны, или ни один из них не выбран. Например, с массивом {1, 2, 2, 2, 5, 2} должны быть выбраны либо все три 2 в середине, либо нет, все как группа. (один цикл можно использовать для определения экстента одинаковых значений).

Тестовые сценарии ниже

groupSumClump(0, {2, 4, 8}, 10) → true true OK      
groupSumClump(0, {1, 2, 4, 8, 1}, 14) → true true OK      
groupSumClump(0, {2, 4, 4, 8}, 14) → false false OK      
groupSumClump(0, {8, 2, 2, 1}, 9) → true false X   --->Failing   
groupSumClump(0, {8, 2, 2, 1}, 11) → false false OK      
groupSumClump(0, {1}, 1) → true false X      --->Failing
groupSumClump(0, {9}, 1) → false false OK      
other tests  OK      

Фрагмент, как показано ниже

private int sum(final Integer start, final Collection<Integer> list) {
        int sum = start;

        for (final int i : list) {
            sum += i;
        }

        return sum;
}

   public boolean groupSumClump(final int start, final int[] nums, final int target) {       
        for (int i = 0; i < nums.length-1; i++) {
          if(nums[i] == nums[i+1]){//group selected logic
            int sum = nums[i] + nums[i+1];//is this Ok ?
            nums[i] =sum;
            nums[i+1]=0;
          }else{
          //how to handle the logic for group not selected.               
          }
        }

        final List<Integer> fixed = new ArrayList();
        final List<Integer> candidates = new ArrayList();

        // fills candidates and fixed
        for (int i = 0; i < nums.length; i++) {
            final int cand = nums[i];

            if (cand == 1 && i > 0) {
                final int prev = nums[i - 1];                    
            }else if (cand < target) {
                candidates.add(cand);
            }
        }

        // compute the sum of fixed
        final int sumFixed = sum(0, fixed);

        // if the sum of fixed is equals to target we don't need to do 
        //anything because we already know we need to return true.
        if (sumFixed == target) {
            return true; 
        }            
        if (sumFixed <= target && !candidates.isEmpty()) {
         final Set<Set<Integer>> powerSets = powerSet(new HashSet(candidates));               
            for (final Set<Integer> set : powerSets) {
                if (sumFixed + sum(0, set) == target) {
                    return true; 
                }
            }
        }

        return false;        
}      

 public <T> Set<Set<T>> powerSet(Set<T> originalSet) {       
      Set<Set<T>> sets = new HashSet<Set<T>>();
      if(originalSet.isEmpty()) {
        sets.add(new HashSet<T>());
        return sets;
      }
List<T> list = new ArrayList<T>(originalSet);
T head = list.get(0);
Set<T> rest = new HashSet<T>(list.subList(1, list.size())); 
for (Set<T> set : powerSet(rest)) {
    Set<T> newSet = new HashSet<T>();
    newSet.add(head);
    newSet.addAll(set);
    sets.add(newSet);
    sets.add(set);
}       
return sets;
}  

Не могли бы вы дать мне понять, в чем проблема с кодом и почему он не работает в тестовых сценариях, как уже упоминалось.

Я хочу знать, какая логика для группы не выбрана?

Ответы [ 2 ]

1 голос
/ 19 мая 2011

Вот полное решение, которое проходит все ваши тестовые случаи.

Пожалуйста, отредактируйте себя так, чтобы оно соответствовало вашим API ^ _ ^

public static void main(String[] args) {
    int nums [] = new int[]{2, 4, 8};
    int target = 10;
    int nums_another [] = grouped (nums);
    System.out.println(viable(0, nums_another, 0, target));
}

private static int [] grouped (int nums []) {
    int nums_another[] = new int [nums.length];
    int i = 0;
    int j = 0;
    i++;
    int c = 1;
    while (i < nums.length){
        if (nums[i] == nums[i-1]) { // count identical numbers
            c++;
        }
        else { // not identical, store sum of previous identical numbers (possibly only 1 number)
            if (nums[i-1] != 0) {
                nums_another[j] = nums[i-1] * c;
                j++;
            }
            c = 1;
        }
        i++;
    }
    if (nums[i-1] != 0) { // store last
        nums_another [j] = nums[i-1] * c; 
    }
    return nums_another;
}

/* partial_sum + sub array of "array from start to 0's" -> target */
private static boolean viable (int partial_sum, int array[], int start, int target) {
    if (partial_sum == target) {
        return true;
    }
    else if (start >= array.length || array[start] == 0) {
        return false;
    }
    else { // Key step
        return viable (partial_sum + array[start], array, start + 1, target)
            || viable (partial_sum,                array, start + 1, target);
    }
}

Ключевой шаг:

вернуть, является ли target жизнеспособным через sub array, проверить оба случая start включено или нет.

0 голосов
/ 19 мая 2011

Одним полезным первым шагом будет замена массива на LinkedMultiSet. Не стандартная коллекция времени выполнения, но достаточно простая для того, чтобы представить, найти реализацию или создать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...