【问题标题】:Sort a number's digits recursively in Java在Java中递归地对数字的数字进行排序
【发布时间】:2018-08-07 10:30:38
【问题描述】:

我对编程很陌生,刚在大学里学过。我有一个任务,我必须在 java 中递归地解决这个问题(不使用数组、if、else、while 等......)

所以任务是从 13542 到 12345 对数字进行排序。

public static void main(String[] args) {
    System.out.println(sort(13542));

}

public static long sort(long n) {
    return n < 10
            ? n
            : sort(n, 0);
}

public static long sort(long n1, long n2) {
    return n1 > 10
            ? xxx
            : xxx;
}

问题是我不知道该怎么做。我认为我的开始还可以,但是我对第二种方法有问题。

【问题讨论】:

  • 在翻译中,一个 'sortiere' übersehen? s/übersehen/被忽视。 main-method 没有提到 12345 - 应该如何引入这个数字?首先提到较高的数字是否意味着您必须对它们进行降序排序?边界内的所有数字?您能告诉我们,您的课程的主题是什么,可能是 for 循环?
  • 从一个更简单的例子开始,它适合屏幕,例如 (sort 23 17)。当它起作用时,请选择严肃的数字。
  • 一般来说,递归策略是识别一个基本情况,以及达到该基本情况的方法。在第二个函数中,您测试它是否大于 10,如果大于 10 或等于 10,您想使用整数除法和模数将其拆分,然后您想对那些 n1 和 n2 调用排序函数价值观。如果它小于 10,则您已达到基本情况,您可以返回该值。在每次调用时,您希望 n2 从 n1 中取出最大的数字,并使其成为 n2 的最小数字。
  • 你是给long sort(long n)方法的,还是这是你的开始?
  • 没有ifelse?哇哦。那一定是个错误。但是,您的示例代码已经包含一个三元条件;在我看来和if / else 一样。

标签: java algorithm sorting recursion


【解决方案1】:

首先,递归意味着,简单地说,你有一些东西反复调用自己。作业是递归的这一事实暗示了您的讲师希望您如何使用递归方法来解决它。

暂时忽略 main,因为虽然它可以被美化并变得更优雅,但这不是问题的核心。

public int recursiveSort(int toSort){

}

为了整洁,我们需要一个方法来检查它是否已排序,并进行排序。

public Boolean isSorted(int toCheck){
    //TODO: Check if input is sorted
}

public int singleSort(int toSort){
    //TODO: Sorting algorithm
}

这给了我们一个递归的方法

public int recursiveSort(int toSort){
    toSort = singleSort(toSort);
    return isSorted(toSort) ? toSort : recursiveSort(toSort);
}

施加约束的排序是棘手的部分,并且完全取决于您不能使用的内容。
当然,请尝试查看different sorting algorithms 并考虑在这种情况下您将如何实现它们。

【讨论】:

  • 你的递归有一个大问题:它永远不会继续,因为它一遍又一遍地发送相同的参数
  • 我相信你的意思是toSort = singleSort(toSort);
【解决方案2】:

每个递归方法都应该包含两个主要的“成分”:

  1. 终止条件
  2. 向前迈出一步

正如您所提到的,明显的终止条件是一个数字只有 1 位,这意味着它已排序(因此递归应该停止)。

该方法的必要进展是在每次运行时删除一个数字,对较小的数字进行排序,然后将这些数字合并在一起。
如您所见,实际的挑战可能是正确合并,也可能是有效分离。

我选择定位最大数字,将其从原始数字中删除,并将新创建的数字发送回递归函数。最终,该方法将排序后的数字与其右侧的最大数字合并。

public static void main(String[] args) {
    System.out.println(sort(13542));
}

public static long sort(long n) {
    // For testing purposes:
    // System.out.println("sort(" + n + ")");

    if (n < 10) return n;   // Termination condition

    int numOfDigits = (int)(Math.log10(n)+1);
    long largestDigit = n % 10;
    long restOfDigits = n / 10;

    for(int i=0; i<numOfDigits; i++) {
        long current = (long) (n / Math.pow(10, i)) % 10;
        if (current > largestDigit) {
            largestDigit = current;
            restOfDigits = (long) Math.pow(10, i) * (n / (long) Math.pow(10, i + 1))
                    + (n % (long) Math.pow(10, i));
        }
    }

    // Merge the largest number on the right
    return 10 * sort(restOfDigits) + largestDigit;
}

如您所见,出于测试目的,最好在递归方法的开头检查它。您可以打印或使用调试器来查看其进度。

【讨论】:

  • OP 说,“不使用数组,if,else,while 等......”可能也包括for,尽管我不确定。我认为“没有if / else”可能是一个错误,但我认为我确实设法避免了循环。
【解决方案3】:

在最简单的形式中,递归就是让一个方法一遍又一遍地调用自己。这是一个简单的例子。

public void eatAllFoodFromTable(Table tbl, Person prsn) {

    if(tbl.hasFood()) {

        prsn.sustain(1);
        tbl.removeFood(1);
        eatAllFoodFromTable(tbl, prsn); /*As you can see here,
            the method calls itself. However, because the method has a condition
            that can prevent it from running indefinitely (or a way to terminate),
            it will repeat until the condition is met, then terminate. This is recursion!*/

    } else {
        //Do nothing.
    }

}

您想要做的是花很长时间,并将其输入一个名为sort 或类似的方法。然后,该方法将检查其中一些是否有序(通过某种迭代),然后使用排序迭代生成的新 long 再次调用自身 (sort())。

到达排序点后,方法将终止,返回最终排序值。

【讨论】:

    【解决方案4】:

    这是一个带有一个函数和一个参数的纯递归;没有日志、电源、字符串转换或循环。我想说这是一个相当困难的递归练习,即使对于初学者来说也是如此。我希望这有帮助。随时要求任何澄清。 (也欢迎简化。)

    JavaScript 代码:

    function main() {
      console.log(sort(13542));
    }
    
    function sort(n) {
      if (n < 10)
        return n;
      
      let r = n % 10;
      let l = (n - r) / 10 % 10;
    
      let sorted = sort(Math.floor(n / 10) - l + r);
      let last = sorted % 10;
        
      if (l < last)
        return 10 * sort(sorted - last + l) + last;
      else 
        return 10 * sorted + l;
    }
    
    main();

    【讨论】:

      【解决方案5】:

      非常感谢您的帮助。我想我现在明白了:

      public static long sort(long n) {
          return n < 10
                  ? n
                  : shuffle(sort(n / (long) Math.pow(10, count(n) / 2)),
                          sort(n % (long) (Math.pow(10, count(n) / 2))));
      }
      
      public static long count(long n) {
          return n < 10
                  ? 1
                  : 1 + count(n / 10);
      }
      
      public static long shuffle(long n1, long n2) {
          return (n1 > 0 || n2 > 0)
                  ? (n1 % 10 > n2 % 10)
                          ? shuffle(n1 / 10, n2) * 10 + n1 % 10
                          : shuffle(n1, n2 / 10) * 10 + n2 % 10
                  : 0;
      }
      

      遗憾的是,我们不允许使用 if、else 或 while。这会容易得多。不过谢谢大家:)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-09-05
        • 1970-01-01
        • 2019-02-13
        • 2017-08-14
        • 1970-01-01
        • 1970-01-01
        • 2020-10-27
        相关资源
        最近更新 更多