可能重复:
Java : Summation of multiples of 5
in a group to a given target
大家好,
我正在努力让下面的问题在没有正确方向的情况下解决。
编写一个java函数,以便给定一个in数组,是否可以选择一个由某些in组成的组,以便该组与给定目标的总和具有以下附加约束:数组中所有5的倍数都必须包含在组中。如果紧跟在倍数5后面的值是1,则不能选择它。
(0,{2,5,10,4},19)
{3,5,1},4) 假→
该函数是公共布尔groupSum5(int,int[] num,int目标)。
我已经编写了部分代码,但是也有失败的测试用例。
public boolean groupSum5(int start, int[] nums, int target) {
start = 0;
boolean flag = false;
for(int i=0;i<nums.length;i++){
if(nums[i]%5==0){
start+=nums[i];
}else if((start != target) && (start%5==0)){
start+=nums[i];
}else if(start == target){
flag = true;
return flag;
}else if((nums[i]%5==0) && (nums[i+1]==1)){
continue;
}
}
return flag;
}
即使在编写了这段代码之后,所有的测试用例都失败了。很长一段时间以来,我都在努力争取这个仪式。
编辑迪兰特:你能给我提供的代码修复,因为我已经尝试了这么多,我不知道如何继续
发布于 2011-05-13 05:58:22
这里有一个解决方案,,但请参阅之后的讨论
package so5987154;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
public class Summation {
/**
* Sum of start and every element of the collection.
*
* @param start
* starting value for the sum
* @param list
* Collection to sum.
* @return the sum.
*/
private int sum(final Integer start, final Collection<Integer> list) {
int sum = start;
for (final int i : list) {
sum += i;
}
return sum;
}
/**
* Given an array of ints, is it possible to choose a group of some of the ints, such that the group sums to the given target
* with these additional constraints: all multiples of 5 in the array must be included in the group. If the value immediately
* following a multiple of 5 is 1, it must not be chosen.
*
* @param start
* not used
* @param nums
* array of int (input)
* @param target
* target value for the summation
* @return true if we found a group that meet the criteria.
*/
public boolean groupSum5(final int start, final int[] nums, final int target) {
// list of values that need to be included (multiple of 5)
final List<Integer> fixed = Lists.newArrayList();
// list of value that can be included (anything but 1 preceded by a multiple of 5)
final List<Integer> candidates = Lists.newArrayList();
// 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];
if (prev % 5 != 0) {
candidates.add(cand);
}
} else if (cand % 5 == 0) {
fixed.add(cand);
} 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; // NOPMD
}
// if the sum of fixed is greater than target we don't need to do anything because
// we already know we need to return false (all multiple of 5 must be included)
// If candidates is empty there's no way we can achieve the desired goal.
if (sumFixed <= target && !candidates.isEmpty()) {
// generates all subsets of candidates:
// { 1, 2 } => {}, {1}, {2}, {1, 2}
final Set<Set<Integer>> powerSet = Sets.powerSet(Sets.newHashSet(candidates));
// for each found subset, computes the sum of the subset and add it to the sum of
// multiples of 5 then compare it to target. If equals => return true.
for (final Set<Integer> set : powerSet) {
if (sumFixed + sum(0, set) == target) {
return true; // NOPMD
}
}
}
return false;
}
}
相关测试:
package so5987154.tests;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import so5987154.Summation;
@SuppressWarnings("PMD")
public class SummationTest {
private final Summation s = new Summation();
@Test
public void testGroupSum5() {
assertTrue(s.groupSum5(0, new int[] { 2, 5, 10, 4 }, 19));
assertTrue(s.groupSum5(0, new int[] { 2, 5, 10, 4 }, 17));
assertFalse(s.groupSum5(0, new int[] { 2, 5, 10, 4 }, 12));
assertTrue(s.groupSum5(0, new int[] { 2, 5, 10, 4 }, 19));
assertTrue(s.groupSum5(0, new int[] { 3, 5, 1 }, 5));
assertFalse(s.groupSum5(0, new int[] { 3, 5, 1 }, 4));
assertTrue(s.groupSum5(0, new int[] { 3, 1 }, 4));
assertFalse(s.groupSum5(0, new int[] { 3, 1 }, 2));
assertTrue(s.groupSum5(0, new int[] { 1 }, 1));
}
}
但是,您的签名参数start
建议使用递归。在第一步中,您可以从ints数组中删除:
的倍数。
然后用start和新的int数组调用您的方法。
在该方法中,您需要:
F 220
)
示例:{ 2,5,10,4 },目标= 19
倍数之和5: 5+10 = 15,NO1前面有5 =>新数组{ 2,4}
第一个呼叫:method(15, {2, 4}, 19)
F 231
第二次调用(r1):method(15+2, {4}, 19)
F 242
第三呼叫(r11):method(15+2+4, {}, 19)
false
第二次调用(r2):method(15+4, {2}, 19)
true
我们回到了r1 = r11 = false
和r2 = true
=> return false OR true = true
的第一次通话结束。
您可以看到,Sets.powerSet
等价于递归调用r(k)
https://stackoverflow.com/questions/5987154
复制相似问题