描述
现在有一些长度相等的DNA串(只由ACGT四个字母组成),请将它们按照逆序对的数量多少排序。
逆序对指的是字符串A中的两个字符A[i]、A[j],具有i < j 且 A[i] > A[j] 的性质。如字符串”ATCG“中,T和C是一个逆序对,T和G是另一个逆序对,这个字符串的逆序对数为2。
输入
第1行:两个整数n和m,n(0<n<=50)表示字符串长度,m(0<m<=100)表示字符串数量
第2至m+1行:每行是一个长度为n的字符串
输出
按逆序对数从少到多输出字符串,逆序对数一样多的字符串按照输入的顺序输出。
样例输入
10 6
AACATGAAGG
TTTTGGCCAA
TTTGGCCAAA
GATCAGATTT
CCCGGGGGGA
ATCGATGCAT
样例输出
CCCGGGGGGA
AACATGAAGG
GATCAGATTT
ATCGATGCAT
TTTTGGCCAA
TTTGGCCAAA
原题链接:http://dsalgo.openjudge.cn/huawen10/3/
解题思路:
比较自然的分两步,先把每个字符串的逆序对数量数出来,然后再进行排序就好啦。
数逆序对的方法的话,从后向前遍历一遍,比如说某个位置是T,那以它为首个元素的逆序对数量就是后面所有的A+C+G的数量,其他字母类似。
ps:我大概比较喜欢归并排序- -这个相同数量按输入顺序输出的条件的话也要注意是要用稳定排序算法的。
以下代码:
#include <iostream>
#include <string>
using namespace std;
struct dna
{
int num = 0;
string s;
};
dna a[101];
dna ta[101];
void merge(int left, int right, int middle)
{
int i, j, index1, index2;
for (j = left; j <= right; ++j)
ta[j] = a[j];
index1 = left;
index2 = middle + 1;
i = left;
while (index1 <= middle && index2 <= right)
{
if (ta[index1].num <= ta[index2].num)
{
a[i] = ta[index1];
++i;
++index1;
}
else
{
a[i] = ta[index2];
++i;
++index2;
}
}
while (index1 <= middle)
{
a[i] = ta[index1];
++i;
++index1;
}
while (index2 <= right)
{
a[i] = ta[index2];
++i;
++index2;
}
}
void mergesort(int left, int right)
{
int middle;
if (left < right)
{
middle = (left + right) / 2;
mergesort(left, middle);
mergesort(middle + 1, right);
merge(left, right, middle);
}
}
int main()
{
int n,m;
cin >> n>>m;
for (int i = 0; i < m; ++i)
{
cin >> a[i].s;
}
for (int i = 0; i < m; ++i)
{
int count[4] = { 0,0,0,0 };
for (int j = n - 1; j >= 0; --j)
{
if (a[i].s[j] == 'A')
{
++count[0];
}
if (a[i].s[j] == 'C')
{
a[i].num += count[0];
++count[1];
}
if (a[i].s[j] == 'G')
{
a[i].num += (count[0]+count[1]);
++count[2];
}
if (a[i].s[j] == 'T')
{
a[i].num += (count[0] + count[1]+count[2]);
++count[3];
}
}
}
mergesort(0, m - 1);
for (int i = 0; i < m; ++i)
cout << a[i].s << endl;
//system("pause");
return 0;
}
转载请注明原文链接。
想要浏览更多的学习内容可以看看博主更多其他的博文哦~
http://blog.youkuaiyun.com/weixin_38062864