Java分组算法

时间:2011-05-18 09:41:37

标签: java algorithm

给定一个整数数组,是否可以选择一组整数的组,使得该组与给定目标相加,并具有以下额外约束:如果数组中的数字是相邻的且相同的价值,他们必须全部被选中,或者没有一个被选中。例如,对于数组{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 个答案:

答案 0 :(得分:1)

以下是通过所有测试用例的完整解决方案。

请自行编辑以使其适合您的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是否包括在内。

答案 1 :(得分:0)

一个有用的第一步是用LinkedMultiSet替换数组。不是一个标准的运行时集合,但很容易想象,找到一个实现,或者做。