Java编程任务效率

时间:2013-11-27 19:43:47

标签: java time-complexity performance

我正在努力学习编写更高效的代码。有些天才开发人员可以帮助我,让我知道我的代码出错了吗?我怎样才能提高效率呢?

我刚刚在Codility.com上完成了一项任务,并且我通过了所有测试,但是当传入更大的字符串时,我的代码效率不高。

任务说明:

  

字符串S的前缀是S的任何前导连续部分   例如,“c”和“cod”是字符串“codility”的前缀。对于   简单,我们要求前缀非空。前缀的产物   字符串S的P是P的出现次数乘以   P.更确切地说,如果前缀P由K个字符和   P在S中恰好出现T次,然后乘积等于K * T.

例如,S =“abababa”具有以下前缀:

  

“a”,其产品等于1 * 4 = 4,

     

“ab”,其产品等于2 * 3 = 6,

     

“aba”,其产品等于3 * 3 = 9,

     

“abab”,其产品等于4 * 2 = 8,

     

“ababa”,其产品等于5 * 2 = 10,

     “ababab”,其产品等于6 * 1 = 6,

     “abababa”,其产品等于7 * 1 = 7。

最长前缀与原始字符串相同。目标是选择这样的前缀以最大化产品的价值。在上面的例子中,最大乘积是10。

在这个问题中,我们只考虑由小写英文字母(a-z)组成的字符串。

写一个函数

class Solution { public int solution(String S); }

给定由N个字符组成的字符串S,返回给定字符串的任何前缀的最大乘积。如果产品大于1,000,000,000,则该函数应返回1,000,000,000。

例如,对于字符串:

  

S =“abababa”该函数应返回10,如上所述,

     

S =“aaa”函数应返回4,作为前缀的乘积   “aa”是最大的。

假设:

  

N是[1..300,000]范围内的整数;

     

字符串S仅由小写字母(a-z)组成。

复杂度:

预期的最坏情况时间复杂度为O(N);

预期的最坏情况空间复杂度为O(N)(不计算输入参数所需的存储空间)。

以下是我失败的结果:

  

easy_morphism a - > a?a 2.150 s。 TIMEOUT ERROR运行时间:> 2.15秒。   large_random_string cyclic + random string 1.180 s。超时错误   运行时间:> 1.18秒

     

large_cyclic大型循环测试2.170 s。 TIMEOUT ERROR运行时间:> 2.17秒

     

single_letter_with_some_tweaks 2.170 s。 TIMEOUT ERROR运行时间:> 2.17秒

     

same_small_pattern_with_small_tweaks 2.160 s。 TIMEOUT ERROR正在运行   时间:> 2.16秒

     

same_big_pattern_with_small_tweaks 4.660 s。 TIMEOUT ERROR正在运行   时间:> 4.66秒

     

small_pattern_with_tweaks_in_one_place 4.700秒。 TIMEOUT ERROR正在运行   时间:> 4.70秒

任何帮助或提示都会很方便!

public class test {

    public static void main(String[] args) {
        long startTime = System.nanoTime();
        System.out.println("solution: " + solution("abababa"));
        long endTime = System.nanoTime();

        long duration = endTime - startTime;
        System.out.println("duration: " + duration/1000000.0 + " seconds");
    }

    public static int solution(String S) {
        int solution = 0, N = S.length();
        String P;
        for (int K = 1; K <= N; K++) {
            P = S.substring(0, K);

            int T = calculateT(P, S);

            int tmpSolution = K * T;
            if (tmpSolution > solution) {
                solution = tmpSolution;
            }
        }

        return solution;
    }

    public static int calculateT(String P, String S) {
        int T = 0, indexOfStart = 0;

        while (indexOfStart > -1) {
            T++;
            indexOfStart = S.indexOf(P, indexOfStart+1);
        }

        return T;
    }
}

1 个答案:

答案 0 :(得分:3)

经过一番搜索,我最终遇到了一些解决方案。感谢@ afk5min的建议。

我还建议阅读Z-Algorithms: http://codeforces.com/blog/entry/3107

以及KMP算法:http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm

我认为我需要学习的与效率有关的主要事情不是嵌套循环。如果代码进入循环然后进入另一个循环,它会突然消耗更多的时间并且变得无法进行扩展。

我需要开始考虑我的算法的方法是,可以遍历几次,以获得最终结果。这样做比在循环中嵌套循环要好得多。