一个经典的字母排列算法
最近在研究一個(gè)問題,自己嘗試些寫了一個(gè)算法:
問題描述:給出一段字符,比如[a,b,c,d……],輸出任意長(zhǎng)度大于n的字符組合
package com.txq.letter.combine;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedDeque;
/**
* 輸出長(zhǎng)度>len的字符串的任意組合,比如String s = "abc",輸出為"ab","ba","ac","ca"……字符的排列
*
* @author TongXueQiang
* @date 2016/03/01
* @since JDK 1.7
*/
public class LetterCombation {
// 存放字符的原始隊(duì)列
private static Queue<Character> queue = new ConcurrentLinkedDeque<Character>();
// 組合過程中產(chǎn)生的第一個(gè)結(jié)果集
private static Queue<List<String>> firstResult = new ConcurrentLinkedDeque<List<String>>();
// 最終結(jié)果集
private static Set<String> finalResult = new HashSet<String>();
// 組合的層級(jí)數(shù),從2開始
private static int level = 2;
/**
* 任意字母組合
*
* @param word
* @param len
* @return
*/
public Set<String> outputLetterCombina(String word, int len) {
if (word == null || word.equals("")) {
return null;
}
// 1.把word加入到原始隊(duì)列中
init(word);
// 2.產(chǎn)生第一次結(jié)果集
firstResult = outputFirstCombination();
// 3.循環(huán)進(jìn)行下一層級(jí)的組合,并得到最終結(jié)果集
finalResult = outputCombination(firstResult, level, word);
// 4.去除不符合期望的字符組合
return removeUnexpectedLetterComb(finalResult, len);
}
/**
* 去除不符合期望的字符串
* @param finalResult2
* @return
*/
private Set<String> removeUnexpectedLetterComb(Set<String> result, int len) {
List<String> deleteList = new ArrayList<String>();
for (String s : result) {
if (s.length() <= len) {
deleteList.add(s);
}
}
result.removeAll(deleteList);
return result;
}
/**
* 產(chǎn)生原始隊(duì)列
*
* @param word
*/
public Queue<Character> init(String word) {
if (word == null || word.equals("")) {
return null;
}
for (int i = 0;i < word.length();i++) {
Character c = Character.valueOf(word.charAt(i));
if (c.equals(' ') || c.equals('\n') || c.equals('\t') || c.equals('\r')) {
continue;
}
queue.add(c);
}
return queue;
}
/**
* 倒置字符串
*
* @param word
* @return
*/
public String reverse(String word) {
StringBuffer result = new StringBuffer();
for (int i = word.length() - 1; i >= 0; i--) {
result.append(word.charAt(i));
}
return result.toString();
}
/**
* 倒置字符串,比如abc,倒置后為cab,abcd,倒置后為dabc……
*
* @param word
* @return
*/
public String reverseCombination(String word) {
char s[] = word.toCharArray();
List<String> ss = new ArrayList<String>();
StringBuffer sb = new StringBuffer();
SoftReference<StringBuffer> srf = new SoftReference<StringBuffer>(sb);
for (int i = 0; i < s.length - 1; i++) {
sb.append(s[i]);
}
// 把除最后一個(gè)字符意外的全部字符串加載到list中
ss.add(sb.toString());
sb = null;
sb = new StringBuffer();
sb.append(s[s.length - 1]);
// 把最后一個(gè)字符加載到list中
ss.add(sb.toString());
Collections.reverse(ss);// 倒置處理
sb = null;
sb = new StringBuffer();
for (String s0 : ss) {
sb.append(s0);
}
// 輸出最后結(jié)果
return sb.toString();
}
/**
* 輸出長(zhǎng)度為2的字母組合,作為第一個(gè)結(jié)果集,以備后續(xù)的組合使用
* @return
*/
public Queue<List<String>> outputFirstCombination() {
StringBuffer sb = null;
List<String> cell = null;
SoftReference<List<String>> srf = new SoftReference<List<String>>(cell);
SoftReference<StringBuffer> srf0 = new SoftReference<StringBuffer>(sb);
// 1.依次取出第一個(gè)字符,與剩下的字符組合
char ch = queue.poll();
for (char cha : queue) {
cell = new ArrayList<String>();
sb = new StringBuffer();
sb.append(ch).append(cha);
// 加入到cell中
cell.add(sb.toString());
cell.add(reverse(sb.toString()));
// 把cell加入到首個(gè)結(jié)果集中
firstResult.add(cell);
sb = null;
cell = null;
}
// 遞歸終止條件
if (queue.size() != 1) {
outputFirstCombination();
}
return firstResult;
}
/**
* 輸出組合,循環(huán)對(duì)輸入的結(jié)果集中的每個(gè)cell處理,產(chǎn)生新的cell,然后把新的cell加載到中間結(jié)果集中,最后返回最后結(jié)果
*
* @param handleResult
* @param level
* @return
*/
public Set<String> outputCombination(Queue<List<String>> inputResult, int level, String word) {
// 定義新的中間結(jié)果集
Queue<List<String>> middleResult = new ConcurrentLinkedDeque<List<String>>();
SoftReference<Queue<List<String>>> srf = new SoftReference<Queue<List<String>>>(middleResult);
StringBuffer sb = null;
// 1.把handleResult加入到最終結(jié)果集中
finalResult = addToFinalResult(inputResult);
// 2.清空隊(duì)列
queue.clear();
// 3.對(duì)輸入的結(jié)果集進(jìn)行處理,進(jìn)行下一層級(jí)的組合
List<String> cell = inputResult.poll();
while (cell != null) {
// 新的cell
List<String> newCell = null;
// ①.初始化隊(duì)列
queue = init(word);
// ②.從cell中取出第一個(gè)字符串,然后去除原始隊(duì)列中與之匹配的字符串
removeStrFromOriginalQueue(cell);
// ③.cell與原始隊(duì)列中剩下的字符串進(jìn)行組合,產(chǎn)生新的cell
originalQueueToCellCombination(newCell, cell, middleResult, sb);
// ④.清空隊(duì)列
queue.clear();
// ⑤.下一個(gè)單元
cell = inputResult.poll();
}
inputResult = null;
++ level;// 4.層級(jí)疊加
// 5.遞歸終止條件
if (level != word.length()) {
outputCombination(middleResult, level, word);
}
// 6.處理最后的中間結(jié)果集
addToFinalResult(middleResult);
middleResult = null;
return finalResult;
}
/**
* cell與原始隊(duì)列中剩下的字符串進(jìn)行組合,產(chǎn)生新的cell
*
* @param newCell
* @param cell
* @param middleResult
* @param sb
*/
private void originalQueueToCellCombination(List<String> newCell, List<String> cell,
Queue<List<String>> middleResult, StringBuffer sb) {
SoftReference<List<String>> srf = new SoftReference<List<String>>(newCell);
SoftReference<StringBuffer> srf0 = new SoftReference<StringBuffer>(sb);
for (char c : queue) {
newCell = new ArrayList<String>();
for (String s : cell) {
sb = new StringBuffer();
sb.append(s).append(c);
newCell.add(sb.toString());
newCell.add(reverseCombination(sb.toString()));
sb = null;// 不用的對(duì)象
}
// 把newCell加載到中間結(jié)果集中
middleResult.add(newCell);
newCell = null;
}
}
/**
* 從cell中取出第一個(gè)字符串,在原始隊(duì)列中移除與之匹配的字符串
*
* @param cell
*/
private void removeStrFromOriginalQueue(List<String> cell) {
String firstWord = cell.get(0);
for (int i = 0; i < firstWord.length(); i++) {
queue.remove(firstWord.charAt(i));
}
}
/**
* 輸出到最終結(jié)果集中
*
* @param middleResult
*/
public Set<String> addToFinalResult(Queue<List<String>> middleResult) {
for (List<String> cell : middleResult) {
finalResult.addAll(cell);
}
return finalResult;
}
}
轉(zhuǎn)載于:https://www.cnblogs.com/txq157/articles/5238079.html
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的一个经典的字母排列算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2013计算机视觉代码合集二
- 下一篇: Button单击事件处理: