Java 等于目标的最大连续奇数整数数

Java 等于目标的最大连续奇数整数数,java,algorithm,Java,Algorithm,我目前正在寻找最大数量的连续奇数加起来等于一个目标数 我当前查找3个连续整数的代码如下所示 public class consecutiveOdd { public static void main(String[] args){ int target = 160701; boolean found = false; for(int i = 1; i < target; i++){ if(i + (i+2)

我目前正在寻找最大数量的连续奇数加起来等于一个目标数

我当前查找3个连续整数的代码如下所示

public class consecutiveOdd {
    public static void main(String[] args){
        int target = 160701;
        boolean found = false;

        for(int i = 1; i < target; i++){
            if(i + (i+2) + (i+4) == target){
                System.out.print(i + " + " + (i+2) + " + " + (i+4));
                found = true;
            }

         }
         if(!found){
            System.out.println("Sorry none");
         }
     }
}
公共类连续奇数{
公共静态void main(字符串[]args){
int目标=160701;
布尔值=false;
for(int i=1;i
我认为需要进行(I+2)增量的while循环构建迭代,但在开发正确的算法时遇到了困难。任何帮助或提示都将不胜感激

最好的,
水獭查看图案:

  • 对于1个总和,
    i=target
  • 对于2个求和,等式为
    2*i+2=target
    ,因此
    i=(target-2)/2
  • 对于3个总和,等式为
    3*i+6=target
    ,因此
    i=(target-6)/3
  • 对于4个求和,等式为
    4*i+12=target
    ,因此
    i=(target-12)/4

  • 显然,
    i
    在所有情况下都必须是奇数整数

    您可以计算出
    n
    summands的一般表达式,并对其进行简化以向您展示一个算法,但您可能已经能够看到一个算法


    应用@rossum的建议:

  • 对于1个总和,
    2m+1=目标
  • 对于2个总和,
    2m+1=(目标-2)/2
    ,因此
    m=(目标-4)/4
  • 对于3个总和,
    2m+1=(目标-6)/3
    ,因此
    m=(目标-9)/6
  • 对于4个总和,
    2m+1=(目标-12)/4
    ,因此
    m=(目标-16)/8

  • 假设答案等于
    k(k>0)
    。然后对于一些奇怪的
    i
    我们可以写:
    i+(i+2)+(i+4)+(i+2k-2)=目标
    。你可以看到这是的和,所以你可以用一个众所周知的公式来计算它。应用公式,我们可以得到:
    i=target/k-k+1

    基于此公式,我建议采用以下算法:

  • 迭代
    k的值
  • 如果
    target/k-k+1
    为正奇数整数,则更新答案
  • 简单的实现

    int answer = -1;
    for (int k = 1;; k++) {
        int i = target / k - k + 1;
        if (i <= 0) {
            break;
        }
        // Check if calculated i, can be the start of 'odd' sequence.
        if (target % k == 0 && i % 2 == 1) {
            answer = k;
        }
    }
    
    int-answer=-1;
    for(int k=1;k++){
    int i=目标/k-k+1;
    
    如果(i一系列
    n
    奇数整数之和可以计算为平均值(中点
    m
    )乘以值的数量(
    n
    ),那么:

    如果
    n
    为奇数,则
    m
    为奇数;如果
    n
    为偶数,则
    m
    为偶数

    序列的
    第一个
    最后一个
    编号可计算为:

    first  =  m - n + 1  =  8 - 4 + 1  =  5
    last   =  m + n - 1  =  8 + 4 - 1  =  11
    
    其他有趣的公式:

    m  =  sum / n
    m  =  (first + last) / 2
    last  =  first + (n - 1) * 2  =  first + 2 * n - 2
    m  =  (first + first + 2 * n - 2) / 2  =  first + n - 1
    
    最长的序列必须从尽可能低的
    first
    值开始,这意味着
    1
    ,因此我们得到:

    sum  =  m * n  =  (first + n - 1) * n  =  n * n
    
    这意味着任何给定的
    sum
    的最长序列最多可以是
    sqrt(sum)
    long

    因此,从
    sqrt(sum)
    开始,向下搜索,直到找到有效的
    n

    /**
      * Returns length of sequence, or 0 if no sequence can be found
      */
    private static int findLongestConsecutiveOddIntegers(int sum) {
        for (int n = (int)Math.sqrt(sum); n > 1; n--) {
            if (sum % n == 0) { // m must be an integer
                int m = sum / n;
                if ((n & 1) == (m & 1)) // If n is odd, mid must be odd. If n is even, m must be even.
                    return n;
            }
        }
        return 0;
    }
    
    结果:

    由于
    sqrt(160701)=400.875…
    ,结果在10次迭代(400到391次,包括400到391次)中找到

    结论:

    等于160701的最大连续奇数整数:391

    21 + 23 + 25 + ... + 799 + 801 = 160701
    

    for循环将查看奇数集{1,3,5},但也会查看偶数集{2,4,6}因此,你可能想说i+=2而不是i++。顺便说一句,我喜欢上面的数学解,而不是蛮力搜索。仅供参考:答案是391:
    21+23+25+…+799+801=160701
    嘿,谢谢大家!显然
    i
    在所有情况下都必须是奇数。根据问题,使用替换
    i=2m+1
    并求解
    m
    以放宽要求。这样
    m
    可以是奇数也可以是偶数。@rossum整洁的建议,我已将其添加到答案中。
    n  =  findLongestConsecutiveOddIntegers(160701)  =  391
    m  =  sum / n  =  160701 / 391  =  411
    first  =  m - n + 1  =  411 - 391 + 1  =  21
    last   =  m + n - 1  =  411 + 391 - 1  =  801
    
    21 + 23 + 25 + ... + 799 + 801 = 160701