哪种解决方案更好,更快且可读性更好?

时间:2019-05-02 20:12:17

标签: java algorithm time

好,问题:“等距图是一个没有重复字母,连续或不连续的单词。实现一个函数,该函数确定仅包含字母的字符串是一个等距图。假定空字符串是一个等距图。忽略信箱。”  我写了两个解决方案

第一个解决方案:

Scanner scanner = new Scanner(System.in);
String string = scanner.next();
long start = System.currentTimeMillis();
char words[] = string.toCharArray();
boolean isIsogram=true;
for (int i=(words.length-1); i>=0; i--){
  for(int j=0; j<(i-1);j++){
    if(words[i]==words[j]){
      isIsogram=false;
    }
  }
}
long finish = System.currentTimeMillis();
System.out.println(isIsogram + " time:"+ (finish-start) );

第二种解决方法:

    Scanner scanner = new Scanner(System.in);
    String string = scanner.next();
    long start = System.currentTimeMillis();
    boolean isIsogram = (string.length() == string.toLowerCase().chars().distinct().count());
    long finish = System.currentTimeMillis();
    System.out.println(isIsogram + " time:"+ (finish-start) );

我已经测试了这两种解决方案,并且有结果: 输入:“ asd”
1)真实时间0
2)真实时间113

我想知道您的想法和意见,哪种解决方案更好? 我的老师告诉我2个解决方案更好,但1个解决方案需要 时间更少了,我不确定哪个更好.....

2 个答案:

答案 0 :(得分:-1)

正确的答案实际上是分析您的特定问题,并查看符合您要求的方法。

可读性很重要。哪种方法最易读是非常主观的。面向流的操作通常从更具声明性的方法而不是强制性的方法来解决问题。声明性代码通常更容易阅读,而命令性代码通常更快。

但是您需要多快?甚至您的(非常有缺陷的)基准测试也仅显示100毫秒的差异。那快于人类感知的门槛。如果您的代码不太慢,则不必担心使其速度更快。担心首先要弄清楚,可维护,可调试且正确


无论如何,由于这是一个有趣的问题,所以我拨了一分钟。字符串中有2 16 个可能的char值,因此,如果使用BitSet,则每个值都可以是/否,并且仍然适合整个在8K的内存中。

您说的问题是折叠案件。这听起来像是一种简化,但实际上并非如此,除非您的数据是ASCII(在这种情况下,您只需要256位BitSet,或者可能只需要26位!)。如果您可以使用所有范围的Unicode字符,那么即使将大小写可靠地转换为小写也几乎不可能正确地解决。 (大小写转换最终是特定于语言环境的。)

因此,我假设您要处理所有可能的char值,该值将无法正确处理UTF-16替代(例如您需要表情符号),但应处理所有被视为“字母”的内容“以字母语言显示。

这是我想出的:

static boolean isIsogram(String text) {
    java.util.BitSet bits = new java.util.BitSet(1 << 16);
    for (int i = 0; i < text.length; i++) {
        int ch = (int) text.charAt(i);
        if (bits.get(ch)) {
            return false;
        }
        bits.set(ch);
    }
    return true;
}

答案 1 :(得分:-2)

关于可读性的几件事:

第一个代码块:

我会让计数器朝同一方向计数-它将仍然以此方式比较每个单词。这不是一个非常重要的更改,但是它可以使读者省去一步,因为结果很明显(因为很容易看出来,他们不必花心思就可以确定代码是否产生了预期的结果。代码的时间复杂度为O(n ^ 2))。

boolean isIsogram = true; 
Scanner scanner = new Scanner(System.in);
String string = scanner.next();
long start = System.currentTimeMillis();
char words[] = string.toCharArray();

for (int i = 0 ; i <= words.length - 1; i++){
    for(int j = 0; j <= words.length - 1; j++){
         if(words[i] == words[j]){
             isIsogram = false;
             break; //I agree with the first answer
         }
    }
    if (!isIsogram)
        break; 
}  

long finish = System.currentTimeMillis();
System.out.println(isIsogram + " time:" + (finish-start) );

第二个代码块可读性很强,尽管我可能已准备好理解问题,因此它实际上可能更具可读性。但是就目标而言,比较不同角色的呼吁是完全有意义的。