2011-05-18 92 views
0

给定一个整数数组,是否可以选择一组整数,这样该组就可以与给定的目标相加,并带有这个额外的约束条件:如果数组中有相邻的数字和相同的价值,他们必须全部被选中,或者他们没有选择。例如,对于数组{1,2,2,2,5,2},中间的所有三个2必须被选择或不被选择,全部作为一个组。 (一个循环可用于查找相同值的范围)。Java分组算法

测试场景均低于

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; 
} 

你能告诉我什么提到的代码的问题,为什么会失败的测试场景。

我想知道未选择组的逻辑是什么?

+1

这功课吗?这也让我想起'NP!= P'问题... – Bobby 2011-05-18 09:44:08

+0

另请参见用户的上一个问题http://stackoverflow.com/questions/6028256/groupsumclump-problem – Qwerky 2011-05-18 09:47:37

+0

你能否提供我在java中的代码的实现以解决上述问题。同时我需要处理没有选中的组的逻辑。您可以在java中为这个提供完整的实现 – 2011-05-19 04:32:43

回答

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包含与否。

+0

它的下雨代码在SO.Thanks Dante !!! – 2011-05-19 14:33:54

+0

@ user756993,不要忘记接受,如果它有效。 – 2011-05-19 14:39:32

+0

可以给我一天的时间来尝试所有的测试用例,因为我需要尝试它们。我一定会让它接受你的答案。感谢所有人的帮助但丁。我想从你身上学到很多东西。我有你的电子邮件地址plz.or你可以发送电子邮件deepakl.2000 @ gmail.com,对不起,我没有声望upvote它,但会接受它,一旦测试和验证明天。 – 2011-05-19 15:01:13

0

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

+0

你能否给我提供在java中的代码的实现来解决上面提到的问题。我还需要处理“未选择组的逻辑”。你能否为此提供'java完整的实现'。 – 2011-05-19 03:54:26