A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© yanzhendong   /  2016-5-13 22:47  /  1778 人查看  /  23 人回复  /   2 人收藏 转载请遵从CC协议 禁止商业使用本文

我的算法还可以改进一下,等下会把改好的发上来
回复 使用道具 举报
本帖最后由 yanzhendong 于 2016-5-15 21:23 编辑

改进后的代码,之前遍历耗时83秒,改进后耗时53秒,可见性能提升还是很明显的
  1.         /**
  2.          * 这个接口用于定义规则的,用户可以在这个接口的实现类中自定义规则,如果一个item符合这个规则返回真,否则返回假
  3.          */
  4.         interface ItemFilter {
  5.                 boolean accept(String item);// 用于检测符合的情况

  6.                 boolean exclude(String item);// 用于检测不符合的情况,以避免无谓的遍历
  7.         }

  8.         public static void main(String[] args) throws Exception {
  9.                 String[] values = { "H", "E", "L", "L", "O", "H", "E", "I", "M", "A", "!" };
  10.                 TreeSet<String> result = new TreeSet<>();
  11.                 BufferedWriter out = new BufferedWriter(new FileWriter(new File("D:\\LResult.txt")));
  12.                 // 这里我自定义的规则是:L后面跟A,H后面跟I,E和M相隔两个字符,O和!不相邻,不能有连续两个相同的字符(如LL
  13.                 // 或HH),O在I前面(不是I前面跟O而是O的位置在I前面,可以相邻可以不相邻)
  14.                 ItemFilter filter = new ItemFilter() {
  15.                         private Pattern pattern1 = Pattern.compile("(E.{2}M)|(M.{2}E)");// 匹配E和M相隔两个字符
  16.                         private Pattern pattern2 = Pattern.compile("(.)\\1");// 匹配不能有连续两个相同的字符(如LL或HH)
  17.                         private Pattern pattern3 = Pattern.compile("O.*I");// 匹配O在I前面(不是I前面跟O而是O的位置在I前面,可以相邻可以不相邻)
  18.                         private Pattern pattern4 = Pattern.compile("O!|!O");// 匹配O和!不相邻
  19.                         private Pattern pattern5 = Pattern.compile("LA");// 匹配L后面跟A
  20.                         private Pattern pattern6 = Pattern.compile("HI");// 匹配H后面跟I

  21.                         @Override
  22.                         public boolean accept(String item) {
  23.                                 boolean rule1 = pattern1.matcher(item).find();
  24.                                 boolean rule3 = pattern3.matcher(item).find();
  25.                                 boolean rule5 = pattern5.matcher(item).find();
  26.                                 boolean rule6 = pattern6.matcher(item).find();
  27.                                 // boolean rule2 = !pattern2.matcher(item).find();//
  28.                                 // 这个要匹配失败才表示没有连续两个相同的字符
  29.                                 //boolean rule4 = !pattern4.matcher(item).find();//
  30.                                 // 这个要匹配失败才表示O和!不相邻
  31.                                 return rule1 && rule3 && rule5 && rule6 ;//&&rule2&&rule4;
  32.                         }

  33.                         @Override
  34.                         public boolean exclude(String item) {
  35.                                 // 这里面的pattern任意一个匹配成功则以此head开始的组合都是不符合规则的,所以没必要继续递归下去了
  36.                                 boolean rule2 = pattern2.matcher(item).find();// 这个匹配成功表示有连续两个相同的字符
  37.                                 boolean rule4 = pattern4.matcher(item).find();// 这个匹配成功表示O和!相邻
  38.                                 return rule2 || rule4;
  39.                         }
  40.                 };
  41.                 long start = System.currentTimeMillis();
  42.                 listAvailableItems(values, "", result, filter);
  43.                 out.write("共有" + result.size() + "组\r\n");
  44.                 for (String item : result) {
  45.                         out.write(item + "\r\n");
  46.                 }
  47.                 out.flush();
  48.                 out.close();
  49.                 long end = System.currentTimeMillis();
  50.                 System.out.println("共耗时:" + (end - start) / 1000 + "秒");
  51.         }

  52.         public static void listAvailableItems(final String[] values, final String head, TreeSet<String> result,
  53.                         ItemFilter filter) {
  54.                 for (int i = 0; i < values.length; i++) {
  55.                         String[] localV = Arrays.copyOf(values, values.length);
  56.                         String localH = new String(head);
  57.                         if (localV[i] == null) {// 这里过滤掉null元素,
  58.                                 continue;
  59.                         }

  60.                         localH += localV[i];// 到这里说明找到一个可用元素,则把该元素追加到已排列组合的尾部
  61.                         localV[i] = null;// 将已取走的元素从values中去除

  62.                         if (filter.exclude(localH)) {//这里避免不必要的遍历
  63.                                 continue;
  64.                         }
  65.                         if (localH.toCharArray().length == values.length) {// 这是递归结束的条件,即一个组合已排列出来,未必是符合规则的组合
  66.                                 if (filter.accept(localH)) {// 这里判断这个组合是否符合规则
  67.                                         result.add(localH);
  68.                                 }
  69.                                 return;
  70.                         }
  71.                         listAvailableItems(localV, localH, result, filter);// 到这里说明还没有排列完成一个组合,则继续递归
  72.                 }
  73.         }
复制代码






回复 使用道具 举报
看一看,多多学习
回复 使用道具 举报
膜拜大神,完全看不懂
回复 使用道具 举报
12
您需要登录后才可以回帖 登录 | 加入黑马