Rosalind编程问题排列组合字母K-mers。
Enumerating k-mers Lexicographically
Assume that an alphabet A has a predetermined order; that is, we write the alphabet as a permutation A=(a1,a2,…,ak), where a1<a2<?<ak. For instance, the English alphabet is organized as (A,B,…,Z).
Given two strings s and t having the same length n, we say that s precedes t in the lexicographic order (and write s<Lext) if the first symbol s[j] that doesn’t match t[j] satisfies sj<tj in A.
A collection of at most 10 symbols defining an ordered alphabet, and a positive integer n (n≤10). :
A C G T 2
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 AC AG AT CA CC CG CT GA GC GG GT TA TC TG TT
简单总结一下题目大意:给出一系列英文字母和数字n,所有需要输出n字母的组合。 看似很简单的题目,但背后需要深入学习java语法很详细。
先分析解题思路:
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) ;
}
}
不过Java非常贴心地准备了迭代器工具,通过迭代器遍历即可实现在不报错的情况下删除目标元素。具体方法参上。