给定N,找到添加的最大*奇数/偶数*数来得到N.

时间:2016-07-05 03:58:19

标签: algorithm math

我想根据这个问题提出一个后续问题: Given n, find the maximum numbers added to get n

如果我只能使用奇数来总结N.如果有任何公式可以推广它怎么办?谢谢!

e.g。 给定7,ans为1,为7 给定16,ans为4,对于1 + 3 + 5 + 7 给定13,ans为3,对于1 + 5 + 7

1 个答案:

答案 0 :(得分:1)

我打算提出解决你问题的代码,然后尝试证明/捍卫它。

  public static int maxOddSumToInt(final int n) throws IllegalArgumentException {
    if(n < 0) throw new IllegalArgumentException("n must be positive");

    LinkedList<Integer> currentNums = new LinkedList<>();
    currentNums.add(1);
    int sum = 1;
    int next = 3;
    while(sum < n) {
      currentNums.add(0, next);
      sum += next;
      next += 2;
    }
    while (sum > n) {
      int r = currentNums.remove(0);
      sum -= r;
      while(sum < n) {
        currentNums.set(0, currentNums.get(0) + 2);
        sum += 2;
      }
    }
    return currentNums.size();
  }

问题的关键在于您只需要与目标相加的最独特的奇数整数的计数。因此,无论我们如何达到最大计数,只要我们确信我们拥有它。

使用最多数字的快速通道是尽可能使用最小的数字。因此,我们想要使用1,3,5,7,9,...而不是1,9,15。因此,第一步是尽可能多地按升序包括数字,直到达到或超过我们的目标。如果我们点击它,太棒了!根据定义,这是要使用的最大数量的数字集,因为没有可用的较小数字。例如,对于输入“9”,算法将添加1,添加3,添加5,看到它达到9并返回大小3.

如果我们超过目标,我们删除最后一个添加,因为这显然使其不再可能。通过与上面类似的逻辑,这意味着我们所处的任何一组大小(n)将不起作用,因为我们之前设置了最小的求和,甚至太大了。因此,我们尝试了大小n-1的集合。从这里开始,我们尝试访问目标 并不重要,只需检查是否有任何大小n-1的工作。因此,为简单起见,我们反复增加2的最新添加量,以查看我们是否达到了目标。这两者都确保我们不重复一个数字(我们正在制作一个更大的数字,因此它不可能成为重复)并且如果我们再次超过目标并需要重复这一步骤,我们可以做一次删除,并且肯定会再次低于我们的目标。

总时间复杂度有点棘手。我想我可以声称它是最O(N^2),其中N是目标的价值。最糟糕的情况是数字只能由它自己表示(一组大小为1),所以我们建立一个集合求和直到我们超过它(O(N)),然后逐渐移除,直到我们再次超过( N*O(N))。基于数字的东西可能会有更严格的约束,但不是我的头脑。

算法不做的一件事是优雅地处理无效输入。如果你给它一个没有解决方案的数字,它将永远运行。如果您可以为此找出一个简单的数值测试,您可以将它添加到顶部的非法参数异常。