添加数组直到某个值

时间:2016-02-22 09:49:15

标签: java arrays algorithm

对于练习,我必须添加数组的值,直到达到某个值,显示所有可能的组合。

  

示例:value = 4,array = {1,2,3}

     

可能的组合是:1 + 1 + 1 + 1,1 + 1 + 2,1 + 2 + 1,1 + 3 + 2 + 1 + 1,2 + 2,3 + 1

但是,我的代码似乎不起作用:

ggplot(df, aes(x,y, group=id)) + 
  geom_line() + 
  geom_line(data=df[1:10,], aes(x,y, group=id), size=5)

输出:

public static void main(String[] args) {

    double[] array = { 1., 2., 3. };
    double value = 4.;
    for (int i = 0; i < array.length; i++) {
        addNumber(array, value, i);
    }
}

public static void addNumber(double[] array, double value, int index) {

    double startNumber = array[index];
    double checkSum = 0;

    for (int i = 0; i < array.length; i++) {
        checkSum += array[i] + startNumber;
        if (checkSum == value){
        System.out.println(startNumber + " + " + array[i] + " = " + checkSum);
        } else if (checkSum < value){
            moreNumbers(array, value, checkSum);
        }
        checkSum = 0;
    }
}

public static void moreNumbers (double[] array, double value, double current){

    if (current == value){
        System.out.println(current);
    } else if (current < value) {

        for (int i = 0; i < array.length; i++){             
            current += array[i];
            System.out.println("+ " + array[i] + " = " + current);              
        }
        moreNumbers(array, value, current);
    }       
}

我相信我找不到合适的算法,因为我只获得了一些组合,但并非全部。

我的问题是:我正在寻找一种算法来帮助我理解这个练习,这是逻辑,而不是最终的代码。

编辑:在本练习的进一步发展中,我必须使用0.5或0.2之类的数字,但数字总是正数,所以这是我希望找到答案的另一个问题。

3 个答案:

答案 0 :(得分:2)

这是基于组合技术的解决方案之一。

<强>算法:

  1. 计算从{length}到1的所有组合(重复)。
  2. 仅打印满足总和条件的组合。
  3. 例如,如果输入为4,那么length = 4的一些不同组合将如下所示:

    1 1 1 1
    1 1 1 2
    .
    .
    2 1 2 3
    .
    .
    3 3 3 3
    

    现在,我们只打印1 1 1 1,因为它总结为输入,即4并满足条件。

    同样,对于length = 3,一些不同的组合将如下:

    1 1 1
    1 1 2
    .
    .
    1 2 1
    .
    .
    3 3 3
    

    现在,我们只打印1 1 21 2 12 1 1,因为它们都满足总和条件。

    以下是如何计算不同组合的简要说明:

    1. 组合函数检查数组的最后一个元素,如果它不是MAX则递增它并为函数分支。
    2. 如果最后一个元素是max,那么我们将扫描数组以寻找不是MAX的下一个数字。
    3. 如果上面的扫描因阵列耗尽而失败,那么我们将流程返回到主函数,但是,如果扫描返回的位置不是max,那么我们将该位置的值递增1并重置所有值那个位置到MIN。我们再次分支这个功能。
    4. (它使用递归计算给定长度的所有组合)

      代码段:

      class Combinations
      {
          /* Constants Array (Sorted) */
          private static final double[] ARR_CNST = {0.1,0.2,0.3};
          /* Size of Constant Array */
          private static final int SIZE = 3;
      
          public static void main (String[] args)
          {
              /* Input Number */
              double input = 0.4;
              /* Start Permutations {Length --> 1} */
              for(int i = (int) (input/ARR_CNST[0]); i > 0; i--) {
                  double[] storage = new double[i];
                  /* Fill Array With Least Element */
                  Arrays.fill(storage,ARR_CNST[0]);
                  /* Check Sum Condition */
                  if(check(storage,input)) {
                      /* Print */
                      print(storage);
                  }
                  /* Calculate Rest of the Combinations */
                  calc(storage, input);
              }
          }
      
          private static void calc(double[] arr, double input) {
              /* Increment Last Element if not MAX */
              if(arr[arr.length - 1] < ARR_CNST[SIZE - 1]) {
                  int k = 0;
                  while(k < SIZE && arr[arr.length - 1] != ARR_CNST[k++]);
                  arr[arr.length - 1] = ARR_CNST[k];
                  if(check(arr,input)) {
                      print(arr);
                  }
                  calc(arr, input);
              }
      
              /* Increment & Reset */
              int i = arr.length - 1;
              while(i >= 0 && arr[i] >= ARR_CNST[SIZE - 1])
                  i--;
      
              if(i >= 0) {
                  int k = 0;
                  while(k < SIZE && arr[i] != ARR_CNST[k++]);
                  arr[i] = ARR_CNST[k];
      
                  for(int x = i + 1; x < arr.length; x++) {
                      arr[x] = ARR_CNST[0];
                  }
      
                  if(check(arr,input)) {
                      print(arr);
                  }
                  calc(arr, input);
              }
      
              /* Return */
              return;
          }
      
          /* Check Sum Condition */
          private static boolean check(double[] arr, double input) {
              double sum = 0;
              for(int i = 0; i < arr.length; i++) {
                  sum += arr[i];
              }
              if(sum == input) {
                  return true;
              }
              return false;
          }
      
          /* Print Array Values */
          private static void print(double[] arr) {
              StringBuilder sb = new StringBuilder();
              for(int i = 0; i < arr.length; i++) {
                  sb.append(arr[i] + " + ");
              }
              System.out.println(sb.substring(0,sb.length() - 3));
          }
      }
      

      输出:

      0.1 + 0.1 + 0.1 + 0.1
      0.1 + 0.1 + 0.2
      0.1 + 0.2 + 0.1
      0.2 + 0.1 + 0.1
      0.1 + 0.3
      0.2 + 0.2
      0.3 + 0.1
      

答案 1 :(得分:2)

这似乎可以通过递归轻松解决,如下所示:

获得4和{1,2,3}的解决方案(下面写成解决方案(4,{1,2,3})就像获得解决方案

  • “1 +”+解决方案(3,{1,2,3})
  • “2 +”+溶液(2,{1,2,3})
  • “3 +”+溶液(1,{1,2,3})

在每一步,你减少了数字(当然,如果可用数字列表中没有0),那么你确定递归将完成。

您可以有两个结果:

  • 没有可能(就像你需要生成1,但可用数字列表中没有1)
  • 一个或多个可能的解决方案

还有另一件需要注意的事项:浮点平等。 ==每次都不会工作。

代码如:

public static void main(String[] args) {
    ArrayList<String> solutions = new ArrayList<String>();
    solve("", 1.0d, new Double[] {0.2d, 0.50d}, solutions);
    System.out.println(solutions);
    // [0.2 + 0.2 + 0.2 + 0.2 + 0.2, 0.5 + 0.5]
    solutions.clear();
    solve("", 4d, new Double[] {1d, 2d, 3d}, solutions);
    System.out.println(solutions);
    // [1.0 + 1.0 + 1.0 + 1.0, 1.0 + 1.0 + 2.0, 1.0 + 2.0 + 1.0, 1.0 + 3.0, 2.0 + 1.0 + 1.0, 2.0 + 2.0, 3.0 + 1.0]
}

public static void solve(String subSolution, Double remaining, Double[] authorizedNumbers, List<String> solutions) {
    if (doubleEquals(remaining, 0d)) {
        solutions.add(subSolution);
    } else {
        for(Double authorizedNumber : authorizedNumbers) {
            if (doubleEquals(authorizedNumber, remaining)) {
                solutions.add(subSolution + authorizedNumber);
            } else if (authorizedNumber < remaining) {
                solve(subSolution + authorizedNumber + " + ", remaining - authorizedNumber, authorizedNumbers, solutions);
            }
        }
    }
}

public static boolean doubleEquals(double d1, double d2) {
    return Math.abs(d1 - d2) < 0.000000001d;
}

答案 2 :(得分:1)

一般方法是:

  1. 选择一个可用的数字,看看它是否等于目标。
  2. 如果没有,您可以从可用的号码中选择任何其他号码并将其添加到之前选择的号码;再次,检查你是否已达到目标。
  3. 继续前行,直至达到(或超过)目标总和。
  4. 这可以这样实现:

    public static void startRecursion(int target, int[] numbers) {
      int min = numbers[0];
      for (int i = 1; i < numbers.length; ++i) {
        min = Math.min(min, numbers[i]);
      }
      // We need to choose at most ceil(target / min) numbers.
      int maxPicks = (target + min - 1) / min;
      recurse(new int[maxPicks], 0, 0, target, numbers);
    }
    
    private static void recurse(
        int[] picked, int numPicked, int sumOfPicked,
        int target, int[] numbers) {
      if (sumOfPicked == target) {
        // We reached the target! Print out the numbers we chose to get here.
        for (int i = 0; i < numPicked; ++i) {
          if (i != 0) System.out.print(" + ");
          System.out.print(picked[i]);
        }
        System.out.println(" = " + target);
      } else if (sumOfPicked < target) {
        // We haven't reached the target yet.
        // Go through each of the numbers that you can choose from numbers
        // in turn, increasing the sum by this amount.
        for (int i = 0; i < numbers.length; ++i) {
          picked[numPicked] = numbers[i];
          recurse(
              picked, numPicked + 1, sumOfPicked + numbers[i],
              target, numbers);
        }
      } else {
        // We have overshot the target. Since no numbers are negative,
        // we can't get back to the target again.
      }
    }