题目:
题解:
1.采用滑动窗口求出长度为n的所有子序列
2.计算每个子序列的GC比例
3.保存最大的GC比例
public String getMaxGCRatioSubString(String str, int n) {
double max = -1;
String result = "";
for (int i = 0, j = i + n; j <= str.length(); i++, j++) {
String sub = str.substring(i, j);
double ratio = calculateGCRatio(sub);
if (ratio > max) {
max = ratio;
result = sub;
}
}
return result;
}
private double calculateGCRatio(String s) {
char c = 'C';
char g = 'G';
int count = 0;
for (char c1 : s.toCharArray()) {
if (c1 == c || c1 == g) {
count++;
}
}
return (count * 1.0) / s.length();
}
滑动窗口求子串复杂度为O(n),求窗口内的GC比例复杂度为O(m),所以整体时间复杂度:O(n*m)。
优化:
1.在上面代码中,每次窗口都要求一次GC比例,但是窗口内只有首尾元素发生变化,无需每次都遍历。
2.求GC比例可以换成求GC字符数量,因为总量不变,GC数量越大,比例越高。
public String getMaxGCRatioSubString(String str, int n) {
int count = 0;
// 遍历第一个窗口
for (int i = 0; i < n; i++) {
char c = str.charAt(i);
if (c == 'C' || c == 'G') {
count++;
}
}
// 最大值初始化为第一个窗口
int max = count;
String result = str.substring(0, n);
// 遍历每个窗口
for (int i = 1, j = i + n; j <= str.length(); i++, j++) {
char pre = str.charAt(i-1);
char next = str.charAt(j-1);
// 窗口左边出去的是CG
if (pre == 'C' || pre == 'G') {
count--;
}
// 窗口右边进来的是CG
if (next == 'C' || next == 'G') {
count++;
}
// 更新最大值
if (count > max) {
max = count;
result = str.substring(i, j);
}
}
return result;
}
时间复杂度:O(n)。