代码之家  ›  专栏  ›  技术社区  ›  polygenelubricants

使用递归重新排序参数(支持、反对、替代)

  •  3
  • polygenelubricants  · 技术社区  · 15 年前

    例如,我的解决方案是 endOther from codingbat.com :

    给两个字符串,返回 true str.toLowerCase() 返回字符串的小写版本。

    public boolean endOther(String a, String b) {
      return a.length() < b.length() ? endOther(b, a)
        : a.toLowerCase().endsWith(b.toLowerCase());
    }
    

    对于这种递归技术,有两种明显的替代方法:

    交换 a b

    public boolean endOther(String a, String b) {
      if (a.length() < b.length()) {
        String t = a;
        a = b;
        b = t;
      }
      return a.toLowerCase().endsWith(b.toLowerCase());
    }
    
    • 在像Java这样的语言中,不方便通过引用传递
    • 很多代码只是为了做一个简单的操作
    • 额外的 if 声明打破了“流动”

    public boolean endOther(String a, String b) {
      return (a.length() < b.length())
        ? b.toLowerCase().endsWith(a.toLowerCase())
        : a.toLowerCase().endsWith(b.toLowerCase());
    }
    
    • 显式对称也许是件好事(或者不是?)
    • 坏主意,除非重复的代码非常简单
      • ……不过,在这种情况下,你可以去掉三元,然后 || 这两种表达方式

    • 这三种技术有名字吗?(还有吗?)
    • 我可能遗漏了哪些优点/缺点?

    为了将讨论重点更多地放在技术上而不是特定的codingbat问题上,这里还有一个例子,我觉得递归比一堆if-else、swap或重复代码要优雅得多。

    // sorts 3 values and return as array
    static int[] sort3(int a, int b, int c) {
        return
          (a > b) ? sort3(b, a, c) :
          (b > c) ? sort3(a, c, b) :
          new int[] { a, b, c };
    }
    

    4 回复  |  直到 12 年前
        1
  •  1
  •   Konrad Rudolph    15 年前

    让我们首先确定代码复制通常是个坏主意。

    所以不管我们采取什么解决方案 逻辑

    我认为有三种解决办法:

    1. 第一次递归(使用 if
    2. swap 这在Java中是个问题,但在其他语言中可能是合适的。
    3. 两个独立的方法(如@Has solution),其中一个作为 实施 逻辑的另一个作为 接口

    我不知道这些解决方案中哪一个客观上是最好的。然而,我注意到有些算法(1)被普遍接受为惯用解,例如计算两个数的GCD的Euklids算法。

    我一般不喜欢 不做任何额外的算法,因为它在算法中添加了任何东西。现在, 这不是一个问题,我怀疑它会比(1)或(3)使用任何像样的编译器效率低。但它增加了一个精神上的减速带。

    解决方案(3)给我的印象是过度设计,虽然我想不出任何批评,除了它的更多文本阅读。一般来说,我不喜欢任何后缀为 Impl .

    总之,对于大多数情况,我可能更喜欢(1),尽管我 事实上在类似的情况下使用。

        2
  •  1
  •   Sebastien Lorber    15 年前

    抱歉,您的代码:

    // sorts 3 values and return as array
    static int[] sort3(int a, int b, int c) {
        return
          (a > b) ? sort3(b, a, c) :
          (b > c) ? sort3(a, c, b) :
          new int[] { a, b, c };
    }
    

    只有在需要高性能的情况下才应该使用难以阅读的代码(但无论如何,许多性能问题都是由糟糕的体系结构引起的…)。如果您必须编写这样的代码,那么您所能做的就越少,那就是编写一个好的javadoc和单元测试。。。我们的开发人员通常不关心这些方法的实现,如果我们只是要使用它,而不是返工它。。。但是因为第一眼看到的东西并不能告诉我们它是什么,我们可以相信它会像我们期望的那样工作,我们可以腾出时间。。。

    递归方法在很短的时间内是可以的,但我认为如果算法很复杂,如果有其他方法可以在几乎相同的计算时间内完成,则应该避免使用递归方法。。。特别是其他人是否愿意用这种方法工作。

    以你的例子来说,这是一个很短的方法,但不管怎样,如果你不关心性能,你可以使用类似的方法:

    // sorts int values
    public static int[] sort(Integer... intValues) {
        ArrayList list = new ArrayList(
        for ( Integer i : intValues ) {
          list.add(i);
        }
        Collections.sort(list);
        return list.toArray();
    }
    

    不是最快的,但如果只是关于速度,请使用c++或asm:)

        3
  •  1
  •   Michael Aaron Safyan    15 年前

    public boolean endOther(String a, String b){
        String alower=a.toLowerCase();
        String blower=b.toLowerCase();
        if ( a.length() < b.length() ){
            return blower.endsWith(alower);
        } else {
            return alower.endsWith(blower);
        }
    } 
    

    if 语句通常更容易理解,尤其是当操作数相当复杂时。另外,如果在 如果

    人们经常听说“递归”与“迭代”/“非递归”实现。我没听说过你给的各种选择有什么特别的名字。

    无论如何,我的建议是在每一次发言中尽可能少做一些事情。在一个语句中执行的操作越多,对于需要维护代码的其他人来说,它就越令人困惑。


    我对三元运算符的论点是无效的。。。绝大多数编程语言都使用带有三元运算符的延迟求值(在编写本文时,我想到的是Verilog,这是一种硬件描述语言(HDL),其中两个分支都是并行计算的)。也就是说,有充分的理由避免在三元运算符中使用复杂的表达式;例如,对于if…else语句,可以在其中一个条件分支上设置断点,而对于三元运算符,两个分支都是同一语句的一部分,因此大多数调试器不会在它们上拆分。

        4
  •  0
  •   Ha.    15 年前

    使用另一种方法代替递归稍微好一点

    public boolean endOther(String a, String b) {
        return a.length() < b.length() ? endOtherImpl(b,a):endOtherImpl(a,b);
    }
    
    protected boolean endOtherImpl(String longStr,String shortStr)
    {
        return longStr.toLowerCase().endsWith(shortStr.toLowerCase());
    }