百炼OJ1007

9 篇文章 0 订阅
8 篇文章 0 订阅

描述
现在有一些长度相等的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
这个题目意思很简单,关键在于怎么求一个串的逆序数。网上提供的算法多是O(n²),我想了一个O(n)的算法。不过在oj上的运行时间并无太大区别

为了方便运算我用0123代替ACGT,例如CCCGGGGGGA就是1112222220.然后进行如下运算

1 统计一个串中0123出现次数,用t[4]记录。(需要遍历一次)

2 int变量number用来记录逆序数。再次对字符串进行遍历,如果遇到0则number不变,如果遇到1则number=number+t[0],如果遇到2则number=number+t[0]+t[1],

   如果遇到3则number=number+t[0]+t[1]+t[3]。假设遇到的数字是a则t[a]--;

3 按照题目要求排序

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int l = sc.nextInt();
		int n = sc.nextInt();
		int total[] = new int[n];
		String s = null;
		String array[] = new String[n];
		for (int i = 0; i < n; i++) {
			s = sc.next();
			array[i] = s;
			int a[] = new int[l];
			int t[] = new int[4];
			int number = 0;
			for (int j = 0; j < l; j++) {
				a[j] = f(s.substring(j, j + 1));
				t[a[j]]++;
			}
			for (int j = 0; j < l; j++) {
				if (a[j] != 0) {
					switch (a[j]) {
					case 1:
						number = number + t[0];
						break;
					case 2:
						number = number + t[0] + t[1];
						break;
					case 3:
						number = number + t[0] + t[1] + t[2];
						break;
					}
				}
				t[a[j]]--;
			}
			total[i] = number;
		}
		int flag = 0;
		int index = 0;
		for (int i = 0; i < n; i++) {
			flag = Integer.MAX_VALUE;
			index = 0;
			for (int j = 0; j < n; j++) {
				if (total[j] < flag) {
					flag = total[j];
					index = j;
				}
			}
			System.out.println(array[index]);
			total[index] = Integer.MAX_VALUE;
		}
	}

	public static int f(String s) {
		if (s.equals("A"))
			return 0;
		else if (s.equals("C"))
			return 1;
		else if (s.equals("G"))
			return 2;
		else
			return 3;
	}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值