Problem
protected static String[] applyInterleave(String interleave, int lengthOfSequence, int numOfPermutations){
String[] interleavedPatterns = new String[numOfPermutations];
char[] pattern = interleave.toCharArray();
StringBuilder interleavedPattern = new StringBuilder("");
for(int i = 0; i < numOfPermutations; i++){
char[] data = designs[i].toCharArray();
for(int j = 0; j < lengthOfSequence; j++)
interleavedPattern.append(data[Character.getNumericValue(pattern[j])-1]);
interleavedPatterns[i] = interleavedPattern.toString();
interleavedPattern = new StringBuilder("");
}
return interleavedPatterns;
}
In this code, design
is of size numOfPermutations
and each element in design is a string of length lengthOfSequence
. Now, I am taking each element in design
and applying an interleave mapping based on the parameter interleave
.
For instance, let’s say the string is 1432
. Then, I take each element in design
and I reorder it so that the 1st char of string is still the 1st, then the 4th char becomes the 2nd, the 3rd char stays the 3rd, and the 2nd char becomes the 4th.
For example, if the first element in design, design[0]
= 4321
and if the passed in parameter for interleave
is 1432
then 4321
is reordered as 4123
. There are very specific reasons why I am only working with String
instead of int
, so I am not interested in changing the variable types.
Now, if my design array is really large, say 362880
indices long, then this method takes quite a while. I have optimized to the best of my ability, but is there a way to speed this up even more?
Solution
Optimization 1
Instead of constantly doing Character.getNumericValue(pattern[j])-1
in the inner loop, you could create a precomputed integer array to hold those values. That way, you could replace that expression with patIndex[j]
.
Optimization 2
Instead of using multiple instances of StringBuilder
, you could use and reuse a single char array and create strings from that.
Optimization 3
Instead of creating a char array from your designs[i]
string, you could just leave designs[i]
as a string and use String.charAt()
to read each character.
Sample rewrite
Using the above 3 optimizations, I arrived at:
static String[] applyInterleave(String interleave, int lengthOfSequence,
int numOfPermutations)
{
String[] interleavedPatterns = new String[numOfPermutations];
char [] pattern = interleave.toCharArray();
int [] patIndex = new int[lengthOfSequence];
for (int i = 0; i < lengthOfSequence; i++) {
patIndex[i] = Character.getNumericValue(pattern[i])-1;
}
for(int i = 0; i < numOfPermutations; i++) {
String s = designs[i];
for(int j = 0; j < lengthOfSequence; j++) {
pattern[j] = s.charAt(patIndex[j]);
}
interleavedPatterns[i] = new String(pattern);
}
return interleavedPatterns;
}
I tested this against the original function and found that it was approximately 3x faster.