The task is:
A non-empty zero-indexed string S is given. String S consists of N characters from the set of upper-case English letters A, C, G, T.
<The php 100/100 solution:
function solution($S, $P, $Q) {
$S = str_split($S);
$len = count($S);
$lep = count($P);
$arr = array();
$result = array();
$clone = array_fill(0, 4, 0);
for($i = 0; $i < $len; $i++){
$arr[$i] = $clone;
switch($S[$i]){
case 'A':
$arr[$i][0] = 1;
break;
case 'C':
$arr[$i][1] = 1;
break;
case 'G':
$arr[$i][2] = 1;
break;
default:
$arr[$i][3] = 1;
break;
}
}
for($i = 1; $i < $len; $i++){
for($j = 0; $j < 4; $j++){
$arr[$i][$j] += $arr[$i - 1][$j];
}
}
for($i = 0; $i < $lep; $i++){
$x = $P[$i];
$y = $Q[$i];
for($a = 0; $a < 4; $a++){
$sub = 0;
if($x - 1 >= 0){
$sub = $arr[$x - 1][$a];
}
if($arr[$y][$a] - $sub > 0){
$result[$i] = $a + 1;
break;
}
}
}
return $result;
}
Java 100/100
class Solution {
public int[] solution(String S, int[] P, int[] Q) {
int qSize = Q.length;
int[] answers = new int[qSize];
char[] sequence = S.toCharArray();
int[][] occCount = new int[3][sequence.length+1];
int[] geneImpactMap = new int['G'+1];
geneImpactMap['A'] = 0;
geneImpactMap['C'] = 1;
geneImpactMap['G'] = 2;
if(sequence[0] != 'T') {
occCount[geneImpactMap[sequence[0]]][0]++;
}
for(int i = 0; i < sequence.length; i++) {
occCount[0][i+1] = occCount[0][i];
occCount[1][i+1] = occCount[1][i];
occCount[2][i+1] = occCount[2][i];
if(sequence[i] != 'T') {
occCount[geneImpactMap[sequence[i]]][i+1]++;
}
}
for(int j = 0; j < qSize; j++) {
for(int k = 0; k < 3; k++) {
if(occCount[k][Q[j]+1] - occCount[k][P[j]] > 0) {
answers[j] = k+1;
break;
}
answers[j] = 4;
}
}
return answers;
}
}
Here is my solution Using Segment Tree O(n)+O(log n)+O(M) time
public class DNAseq {
public static void main(String[] args) {
String S="CAGCCTA";
int[] P={2, 5, 0};
int[] Q={4, 5, 6};
int [] results=solution(S,P,Q);
System.out.println(results[0]);
}
static class segmentNode{
int l;
int r;
int min;
segmentNode left;
segmentNode right;
}
public static segmentNode buildTree(int[] arr,int l,int r){
if(l==r){
segmentNode n=new segmentNode();
n.l=l;
n.r=r;
n.min=arr[l];
return n;
}
int mid=l+(r-l)/2;
segmentNode le=buildTree(arr,l,mid);
segmentNode re=buildTree(arr,mid+1,r);
segmentNode root=new segmentNode();
root.left=le;
root.right=re;
root.l=le.l;
root.r=re.r;
root.min=Math.min(le.min,re.min);
return root;
}
public static int getMin(segmentNode root,int l,int r){
if(root.l>r || root.r<l){
return Integer.MAX_VALUE;
}
if(root.l>=l&& root.r<=r) {
return root.min;
}
return Math.min(getMin(root.left,l,r),getMin(root.right,l,r));
}
public static int[] solution(String S, int[] P, int[] Q) {
int[] arr=new int[S.length()];
for(int i=0;i<S.length();i++){
switch (S.charAt(i)) {
case 'A':
arr[i]=1;
break;
case 'C':
arr[i]=2;
break;
case 'G':
arr[i]=3;
break;
case 'T':
arr[i]=4;
break;
default:
break;
}
}
segmentNode root=buildTree(arr,0,S.length()-1);
int[] result=new int[P.length];
for(int i=0;i<P.length;i++){
result[i]=getMin(root,P[i],Q[i]);
}
return result;
} }
/* 100/100 solution C++. Using prefix sums. Firstly converting chars to integer in nuc variable. Then in a bi-dimensional vector we account the occurrence in S of each nucleoside x in it's respective prefix_sum[s][x]. After we just have to find out the lower nucluoside that occurred in each interval K.
*/ . vector solution(string &S, vector &P, vector &Q) {
int n=S.size();
int m=P.size();
vector<vector<int> > prefix_sum(n+1,vector<int>(4,0));
int nuc;
//prefix occurrence sum
for (int s=0;s<n; s++) {
nuc = S.at(s) == 'A' ? 1 : (S.at(s) == 'C' ? 2 : (S.at(s) == 'G' ? 3 : 4) );
for (int u=0;u<4;u++) {
prefix_sum[s+1][u] = prefix_sum[s][u] + ((u+1)==nuc?1:0);
}
}
//find minimal impact factor in each interval K
int lower_impact_factor;
for (int k=0;k<m;k++) {
lower_impact_factor=4;
for (int u=2;u>=0;u--) {
if (prefix_sum[Q[k]+1][u] - prefix_sum[P[k]][u] != 0)
lower_impact_factor = u+1;
}
P[k]=lower_impact_factor;
}
return P;
}
Java, 100/100, but with no cumulative/prefix sums! I stashed the last occurrence index of lower 3 nucelotides in a array "map". Later I check if the last index is between P-Q. If so it returns the nuclotide, if not found, it's the top one (T):
class Solution {
int[][] lastOccurrencesMap;
public int[] solution(String S, int[] P, int[] Q) {
int N = S.length();
int M = P.length;
int[] result = new int[M];
lastOccurrencesMap = new int[3][N];
int lastA = -1;
int lastC = -1;
int lastG = -1;
for (int i = 0; i < N; i++) {
char c = S.charAt(i);
if (c == 'A') {
lastA = i;
} else if (c == 'C') {
lastC = i;
} else if (c == 'G') {
lastG = i;
}
lastOccurrencesMap[0][i] = lastA;
lastOccurrencesMap[1][i] = lastC;
lastOccurrencesMap[2][i] = lastG;
}
for (int i = 0; i < M; i++) {
int startIndex = P[i];
int endIndex = Q[i];
int minimum = 4;
for (int n = 0; n < 3; n++) {
int lastOccurence = getLastNucleotideOccurrence(startIndex, endIndex, n);
if (lastOccurence != 0) {
minimum = n + 1;
break;
}
}
result[i] = minimum;
}
return result;
}
int getLastNucleotideOccurrence(int startIndex, int endIndex, int nucleotideIndex) {
int[] lastOccurrences = lastOccurrencesMap[nucleotideIndex];
int endValueLastOccurenceIndex = lastOccurrences[endIndex];
if (endValueLastOccurenceIndex >= startIndex) {
return nucleotideIndex + 1;
} else {
return 0;
}
}
}
I think I'm using dynamic programming. Here is my solution. Little space. Code is mot really clean, just show my idea.
class Solution {
public int[] solution(String S, int[] P, int[] Q) {
int[] preDominator = new int[S.length()];
int A = -1;
int C = -1;
int G = -1;
int T = -1;
for (int i = 0; i < S.length(); i++) {
char c = S.charAt(i);
if (c == 'A') {
A = i;
preDominator[i] = -1;
} else if (c == 'C') {
C = i;
preDominator[i] = A;
} else if (c == 'G') {
G = i;
preDominator[i] = Math.max(A, C);
} else {
T = i;
preDominator[i] = Math.max(Math.max(A, C), G);
}
}
int N = preDominator.length;
int M = Q.length;
int[] result = new int[M];
for (int i = 0; i < M; i++) {
int p = P[i];
int q = Math.min(N, Q[i]);
for (int j = q;;) {
if (preDominator[j] < p) {
char c = S.charAt(j);
if (c == 'A') {
result[i] = 1;
} else if (c == 'C') {
result[i] = 2;
} else if (c == 'G') {
result[i] = 3;
} else {
result[i] = 4;
}
break;
}
j = preDominator[j];
}
}
return result;
}
}