Rosalind Java|Enumerating k-mers Lexicographically
时间:2022-11-28 18:00:01
Rosalind编程问题排列组合字母K-mers。
Enumerating k-mers Lexicographically
Problem: Given two strings s and t having the same length n, we say that s precedes t in the lexicographic order (and write s Given: A collection of at most 10 symbols defining an ordered alphabet, and a positive integer n (n≤10). A C G T Return: All strings of length n that can be formed from the alphabet, ordered lexicographically (use the standard order of symbols in the English alphabet). AA 简单总结一下题目大意:给出一系列英文字母和数字n,所有需要输出n字母的组合。 先分析解题思路:
Assume that an alphabet A has a predetermined order; that is, we write the alphabet as a permutation A=(a1,a2,…,ak), where a1
Sample input:
2
Sample output:
AC
AG
AT
CA
CC
CG
CT
GA
GC
GG
GT
TA
TC
TG
TT
看似很简单的题目,但背后需要深入学习java语法很详细。
1.读取所有英文字母(手动去除间隔空间)和k-mers长度n。
2.第一个循环读取所有英文字母到集合。
3.将所有英文字母逐一添加到原始元素到原始元素尾缀中。
4.判断长度不为n的元素并删除。
5.增强for循环输出结果到屏幕。
public class Enumerating_kmers_Lexicographically {
public static void main(String[] args) {
//1.输入组合长度n和待组合字母 Scanner sc = new Scanner(System.in); System.out.println("请输入组合长度n:"); int n = sc.nextInt(); Scanner sr = new Scanner(System.in); System.out.println("请输入待组合的字母:");//网站给出的文件有空间间隔,这里输入需要去除空间。 String alphabet = sr.nextLine(); //2.添加元素并最终输出 List<String> finalalphabet = new ArrayList<>();
kmers(alphabet, finalalphabet, n, 0);
}
public static void kmers(String alphabet, List<String> finalalphabet, int n, int i) {
//初始默认i为0,意为从第一个字母开始遍历产生kmers
while (i < n) {
i += 1;
//从第二轮循环开始向原有元素累加新字符
if (i != 1) {
int size = finalalphabet.size();
for (int k = 0; k < size; k++) {
for (int j = 0; j < alphabet.length(); j++) {
finalalphabet.add(finalalphabet.get(k) + alphabet.charAt(j));
}
}
//使用列表迭代器循环删除元素
ListIterator<String> lit = finalalphabet.listIterator();
while (lit.hasNext()) {
String s = lit.next();
if (s.length() < i) {
lit.remove();//迭代器删除,可以防止删除改变ArrayList大小改变导致的并发修改异常。
}
}
} else {
//第一轮循环直接添加元素进数组
for (int j = 0; j < alphabet.length(); j++) {
finalalphabet.add(String.valueOf(alphabet.charAt(j)));
}
}
}
for (String s : finalalphabet) {
System.out.println(s);
}
}
}
迭代器并发修改错误
撰写上述代码时,“使用列表迭代器循环删除元素”一步至关重要,可以方便后继遍历添加元素,同时及时清理内存。但是小编在写这一部分的时候会提示报错,原有的代码为:
for (String s : finalalphabet) {
if (s.length()<i){
finalalphabet.remove(s) ;
}
}
原因是当finalalphabet删除元素s之后,导致finalalphabet自身大小发生改变,for循环遍历就会产生ConcurrentModificationException并发修改异常。 不过Java非常贴心地准备了迭代器工具,通过迭代器遍历即可实现在不报错的情况下删除目标元素。具体方法参上。