Rosalind Java|Enumerating k-mers Lexicographically

Rosalind编程问题之排列组合字母的K-mers。

Enumerating k-mers Lexicographically

Problem:
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.

Given: A collection of at most 10 symbols defining an ordered alphabet, and a positive integer n (n≤10).
Sample input

A C G T
2

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).
Sample output

AA
AC
AG
AT
CA
CC
CG
CT
GA
GC
GG
GT
TA
TC
TG
TT


简单概述下题目大意:给出一系列英文字母和数字n,需要输出长度为n的字母的所有组合。
看似非常简单的题目,但是背后需要深入学习的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非常贴心地准备了迭代器工具,通过迭代器遍历即可实现在不报错的情况下删除目标元素。具体方法参上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值