问题
I am trying to learn to write more efficient code. Any chance that some of you genius developers could help me out and let me know where my code is going wrong? How can I make it more efficient?
I just completed a task on Codility.com, and I passed all the tests, but my code wasn't efficient enough when larger strings were passed in.
Task description:
A prefix of a string S is any leading contiguous part of S. For example, "c" and "cod" are prefixes of the string "codility". For simplicity, we require prefixes to be non-empty. The product of prefix P of string S is the number of occurrences of P multiplied by the length of P. More precisely, if prefix P consists of K characters and P occurs exactly T times in S, then the product equals K * T.
For example, S = "abababa" has the following prefixes:
"a", whose product equals 1 * 4 = 4,
"ab", whose product equals 2 * 3 = 6,
"aba", whose product equals 3 * 3 = 9,
"abab", whose product equals 4 * 2 = 8,
"ababa", whose product equals 5 * 2 = 10,
"ababab", whose product equals 6 * 1 = 6,
"abababa", whose product equals 7 * 1 = 7.
The longest prefix is identical to the original string. The goal is to choose such a prefix as maximizes the value of the product. In above example the maximal product is 10.
In this problem we consider only strings that consist of lower-case English letters (a-z).
Write a function
class Solution { public int solution(String S); }
that, given a string S consisting of N characters, returns the maximal product of any prefix of the given string. If the product is greater than 1,000,000,000 the function should return 1,000,000,000.
For example, for a string:
S = "abababa" the function should return 10, as explained above,
S = "aaa" the function should return 4, as the product of the prefix "aa" is maximal.
Assume that:
N is an integer within the range [1..300,000];
string S consists only of lower-case letters (a-z).
Complexity:
Expected worst-case time complexity is O(N);
Expected worst-case space complexity is O(N) (not counting the storage required for input arguments).
Here were my failed results:
easy_morphism a -> a?a 2.150 s. TIMEOUT ERROR running time: >2.15 sec. large_random_string cyclic + random string 1.180 s. TIMEOUT ERROR running time: >1.18 sec.
large_cyclic large cyclic tests 2.170 s. TIMEOUT ERROR running time: >2.17 sec.
single_letter_with_some_tweaks 2.170 s. TIMEOUT ERROR running time: >2.17 sec.
same_small_pattern_with_small_tweaks 2.160 s. TIMEOUT ERROR running time: >2.16 sec.
same_big_pattern_with_small_tweaks 4.660 s. TIMEOUT ERROR running time: >4.66 sec.
small_pattern_with_tweaks_in_one_place 4.700 s. TIMEOUT ERROR running time: >4.70 sec.
Any help or hints would be handy!
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:
I came across a few solutions in the end after some searching. Thank you to @afk5min for your suggestions.
I also recommend reading about Z-Algorithms: http://codeforces.com/blog/entry/3107
and also the KMP Algorithm: http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm
I think the main thing to do with efficiency that I need to learn is not to nestle loops. If code is going into a loop and then into another loop it suddenly consumes a lot more time and becomes inefficient for scaling up.
The way I need to start thinking about my algorithms is that it is OK to traverse over something a few times, to get the final result. It is a lot better to do this than to nestle loops inside of loops.
来源:https://stackoverflow.com/questions/20251645/java-programming-task-efficiency