优化导致超时?

时间:2017-10-15 13:46:25

标签: java optimization

我正在研究一个带整数的程序,并找到整数所具有的连续和的组合数:

  

数字13可以表示为连续阳性的总和   整数6 + 7.十四可以表示为2 + 3 + 4 + 5,也是一个和   连续正整数。有些数字可以表示为a   不止一种方式的连续正整数之和。对于   例如,25是12 + 13,也是3 + 4 + 5 + 6 + 7。

我研究并发现它是奇数因子减去1的数量。所以我写了一个程序来查找奇数因子的数量,在某些情况下我的答案仍然是错误的。有什么见解吗?

代码似乎工作正常,但是由于超时导致崩溃,这可能是由于优化错误。

可能的输入大小的约束是 1至10 ^(12)

static int consecutive(long num) {
    while (num % 2 == 0) num /= 2; // 1st opt.
    return  consecutiveHelper(num)-1;
}

public static int consecutiveHelper(long num) {
    long factorNumber = 1;
    int count = 0;

    while(factorNumber <= num / 2) { // 2nd opt.
        if(num % factorNumber == 0) {
            count++;
        }
        factorNumber += 2; // 3rd opt.
    }
    if (num % 2 != 0) {
        count++;
    }
    return count;
}

1 个答案:

答案 0 :(得分:1)

让我们尝试找到一种伪优化方法来解决您的问题:

您需要做的是在素数因子中分解您的数字

例如,如果你采用 1200

1200 = 2*2*2*2*3*5*5 = 1 * 2^4 * 3^1 * 5^2

然后,您可以分析如何使用这些素数因子获得奇数因子。快速分析会告诉您:

  • odd * odd = odd
  • odd * even = even
  • even * even = even

考虑到这一点,让我们找到我们用奇数*奇数得到的所有因素:

  • 1 * 1 = 1
  • 3 * 1 = 3
  • 5 * 1 = 5
  • 5 * 3 = 15
  • 5 * 5 = 25
  • 5 * 5 * 3 = 75

快速找到这些组合而不全写它们的方法是“加1方法”:将每个主要奇数因子的出现次数加1,并将加在一起< / strong>:

我们发现1200 = 1 * 2^4 * 3^1 * 5^2,所以我们可以这样做:

  • (“数字3”+ 1)(“数字5”+ 1)= (1 + 1) ( 2 + 1) = 6

数字1200有6个奇数因子,如您所述,从该数字中删除1以获得1200具有的连续总和组合数:

  • 6 - 1 = 5 &lt; - 呜呜!终于得到了结果!

现在,让我们看看代码。 我们想要的是地图,关键是主要因素,价值是他们出现的次数

/*
    If number is odd,
    find the number in the keys and add 1 to its value.
    If the number is not in the keys, add it with value = 1.
 */
public static void addValue(Map<Integer, Integer> factors, int i) {
    if(i % 2 != 0) {
        int count = factors.containsKey(i) ? factors.get(i) : 0;
        factors.put(i, ++count);
    }
}

/*
    Classic algorithm to find prime numbers
 */
public static Map<Integer, Integer> oddPrimeFactors(int number) {
    int n = number;
    Map<Integer, Integer> factors = new HashMap<>();
    for (int i = 2; i <= n / i; i++) {
        while (n % i == 0) {
            addValue(factors, i);
            n /= i;
        }
    }

    if(n > 1) addValue(factors, n);
    return factors;
}

有了这个,让我们尝试打印地图中包含数字 1200 的内容:

public static void main(String[] args) {
    int n = 1200;

    System.out.println(oddPrimeFactors(n));
}


$n : {3=1, 5=2}
好的!现在让我们用我们之前开发的方法完成程序

public static int combinations = 1;

public static void main(String[] args) {
    int n = 1200;

    oddPrimeFactors(n).forEach((key, value) -> combinations *= (value + 1));
    combinations--;

    System.out.println(combinations);
}


$combinations = 5


完了!随便问你是否理解不了什么!

注意:我尝试使用Integer可以处理的最大值的程序,并且我的程序继续花费不到一秒钟,这对我来说似乎相当快。它可能会更快,你可以找到这个代码的最优化版本!