本帖最后由 yanzhendong 于 2016-5-15 21:23 编辑
改进后的代码,之前遍历耗时83秒,改进后耗时53秒,可见性能提升还是很明显的
- /**
- * 这个接口用于定义规则的,用户可以在这个接口的实现类中自定义规则,如果一个item符合这个规则返回真,否则返回假
- */
- interface ItemFilter {
- boolean accept(String item);// 用于检测符合的情况
- boolean exclude(String item);// 用于检测不符合的情况,以避免无谓的遍历
- }
- public static void main(String[] args) throws Exception {
- String[] values = { "H", "E", "L", "L", "O", "H", "E", "I", "M", "A", "!" };
- TreeSet<String> result = new TreeSet<>();
- BufferedWriter out = new BufferedWriter(new FileWriter(new File("D:\\LResult.txt")));
- // 这里我自定义的规则是:L后面跟A,H后面跟I,E和M相隔两个字符,O和!不相邻,不能有连续两个相同的字符(如LL
- // 或HH),O在I前面(不是I前面跟O而是O的位置在I前面,可以相邻可以不相邻)
- ItemFilter filter = new ItemFilter() {
- private Pattern pattern1 = Pattern.compile("(E.{2}M)|(M.{2}E)");// 匹配E和M相隔两个字符
- private Pattern pattern2 = Pattern.compile("(.)\\1");// 匹配不能有连续两个相同的字符(如LL或HH)
- private Pattern pattern3 = Pattern.compile("O.*I");// 匹配O在I前面(不是I前面跟O而是O的位置在I前面,可以相邻可以不相邻)
- private Pattern pattern4 = Pattern.compile("O!|!O");// 匹配O和!不相邻
- private Pattern pattern5 = Pattern.compile("LA");// 匹配L后面跟A
- private Pattern pattern6 = Pattern.compile("HI");// 匹配H后面跟I
- @Override
- public boolean accept(String item) {
- boolean rule1 = pattern1.matcher(item).find();
- boolean rule3 = pattern3.matcher(item).find();
- boolean rule5 = pattern5.matcher(item).find();
- boolean rule6 = pattern6.matcher(item).find();
- // boolean rule2 = !pattern2.matcher(item).find();//
- // 这个要匹配失败才表示没有连续两个相同的字符
- //boolean rule4 = !pattern4.matcher(item).find();//
- // 这个要匹配失败才表示O和!不相邻
- return rule1 && rule3 && rule5 && rule6 ;//&&rule2&&rule4;
- }
- @Override
- public boolean exclude(String item) {
- // 这里面的pattern任意一个匹配成功则以此head开始的组合都是不符合规则的,所以没必要继续递归下去了
- boolean rule2 = pattern2.matcher(item).find();// 这个匹配成功表示有连续两个相同的字符
- boolean rule4 = pattern4.matcher(item).find();// 这个匹配成功表示O和!相邻
- return rule2 || rule4;
- }
- };
- long start = System.currentTimeMillis();
- listAvailableItems(values, "", result, filter);
- out.write("共有" + result.size() + "组\r\n");
- for (String item : result) {
- out.write(item + "\r\n");
- }
- out.flush();
- out.close();
- long end = System.currentTimeMillis();
- System.out.println("共耗时:" + (end - start) / 1000 + "秒");
- }
- public static void listAvailableItems(final String[] values, final String head, TreeSet<String> result,
- ItemFilter filter) {
- for (int i = 0; i < values.length; i++) {
- String[] localV = Arrays.copyOf(values, values.length);
- String localH = new String(head);
- if (localV[i] == null) {// 这里过滤掉null元素,
- continue;
- }
- localH += localV[i];// 到这里说明找到一个可用元素,则把该元素追加到已排列组合的尾部
- localV[i] = null;// 将已取走的元素从values中去除
- if (filter.exclude(localH)) {//这里避免不必要的遍历
- continue;
- }
- if (localH.toCharArray().length == values.length) {// 这是递归结束的条件,即一个组合已排列出来,未必是符合规则的组合
- if (filter.accept(localH)) {// 这里判断这个组合是否符合规则
- result.add(localH);
- }
- return;
- }
- listAvailableItems(localV, localH, result, filter);// 到这里说明还没有排列完成一个组合,则继续递归
- }
- }
复制代码
|