改善执行时间

时间:2014-07-22 16:13:14

标签: java algorithm dynamic dynamic-programming execution-time

如何改进以下程序执行时间。 我已经在"递归"中使用了动态编程。以及" prime"功能。 但没有获得有效的执行时间。

问题:在受害人的房子里有一块4xN的墙。受害者也有无限 在她家里供应4x1和1x4尺寸的砖块。在每一个 配置,墙必须用砖完全覆盖。 Gale Bertram想知道砖块可以在墙上排列的总数,以便每次都能出现新的配置。 设配数= M。

因此,他希望帕特里克计算素数(比如P)直到M(即<= M)。 你需要帮助Patrick正确解决难题。

示例输入 第一行输入将包含一个整数T,后跟T行,每行包含一个 整数N。

示例输出 为每个测试用例打印一行输出。输出应该包含 数字P. 约束 1·; = T&LT; = 20 1·; = N&LT; = 40

import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
class Solution{
    public static int[] b = new int[217287];
    public static void main(String[] args){
        Scanner stdin = new Scanner(System.in);
    int t = stdin.nextInt();
    int[] a = new int[41];
    for(int j=0;j<4;j++){
            a[j] = 1;          //till n<=3, number of possiblities = 1. These will work as base cases.
        }
        a[4] = 2;
    for(int x=0;x<t;x++){
        int n = stdin.nextInt();
        for(int i=5;i<=n;i++){
            a[i] = -1;         //initialise all value in the array as -1.
        }
        if(n<4)
            System.out.println("0"); // if n<4, number of possibilities =1. So no prime number before that is 0.
        else{
                     //for n=4, possibilities = 2. This is a base case.
        int num1 = recursive(a,n);          // storing number of possibilities in num1.
        int num2 = prime(num1);    //calling to calculate number of prime numbers before or equal to num1.
        System.out.println(num2);
        }
    }
}
public static int recursive(int[] a, int n){
    if(a[n]!=-1)                             // retrieving a[n] value if already calculated.
        return a[n];
    else{
        a[n] = recursive(a,n-1) + recursive(a,n-4); // calling recursively.If we fill with a 4*1 first tile then number 
                                                    //tiles left is n-1(try visualising).If we fill 1*4 tile first
                                                    // we have n-4 tile left.
        return a[n];
    }
}
public static int prime(int n){
    int count = 0;
    if(b[n]!=0)
        return b[n];
    else{
    for(int i=2;i<=n;i++){
        if(b[i]!=0){
            count = b[i];
        }
        else{
        int flag = 0;           
        for(int j=2;j<=i/2;j++){
            if(i%j==0){
                flag = 1;
                break;
                }
            }
    if(flag==0){
        count++;
        b[i]=count;
    }
    }
    }
    return count;
    }
}

}

我得到了以下输入的超时(超过4秒)。 20 35 23 25 38 4 35 19 8 23 35 3 36 12 10 三十 13 18 31 40 37

2 个答案:

答案 0 :(得分:1)

你在这里犯了2个重大错误(或者更确切地说是2个效率低下):

  1. 您正在重新初始化并重新计算每个循环的a数组。那些不会改变,只是通过最初分配大小为40的数组重用上次的结果(你也可能想考虑更好的命名约定......)
  2. 你是在&#34; prime&#34;中使用动态编程部分任务。动态编程是为了保存中间结果以备将来使用,您只需保存答案,希望再次使用它(它不会再次使用,因为n对于唯一N将是唯一的{ {1}} - 再次命名约定
  3. 第1部分不太可能增加太多时间,因为计算是微不足道的并且N <= 40  第2部分是搞砸的地方。您可以执行以下操作,而不是只保存b[n]:从1循环到n填充b,其中素数小于或等于i其中{{1}是索引。这是通过单次素数检查完成的 - 如果i为素数,则将i置为b[i-1]。这意味着您只需检查一个数字是否为每个数字一次(在您当前的实现中,您检查它20次)。您可以在评论中添加一个筛子以进一步提高性能,但上述内容可能会给予足够的加速,在具有给定约束的平庸机器上具有0.1秒的运行时间。

答案 1 :(得分:0)

您可能希望进一步优化int prime(int n)功能。 (当然,您可以使用'net中的任何有效算法,但:)为了避免再次进行相同的计算,请注意,如果您已经prime(n+m),则可以更快地计算prime(n)

(我认为你已经在考虑这个方向,因为你已经为已计算的数字使用了一些'缓存'。)

编辑: 见Ordous的回答#2:)

EDIT2:

详细说明这个想法:

问:如果我知道素数c的数量<= X,素数<= (X+1)的数量是多少?

A:c,如果X+1 是素数,或c+1如果X+1 a主要。像这样:

public static int prime2( final int n ) {
    int count;
    if ( n <= 2 ) {
        count = 1;
    } else {
        count = prime2(n-1);
        if ( isPrime(n) ) {
            count = count + 1;
        }
    }
    return count;
}

然后添加您的缓存方法来存储任何计算prime2(x)的结果以供以后使用。