【解题报告】openjudge DNA排序 数据结构与算法mooc 内排序

本文介绍了一种针对DNA串的特殊排序算法,通过计算各DNA串的逆序对数量来实现排序。采用归并排序确保了相同逆序对数量的DNA串保持原始输入顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

描述
现在有一些长度相等的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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值