给定一个整数数组,是否可以选择一组整数的组,使得该组与给定目标相加,并具有以下额外约束:如果数组中的数字是相邻的且相同的价值,他们必须全部被选中,或者没有一个被选中。例如,对于数组{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;
}
你能告诉我代码的问题吗?为什么它没有提到的测试场景。
我想知道未选择组的逻辑是什么?
答案 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替换数组。不是一个标准的运行时集合,但很容易想象,找到一个实现,或者做。