在Java中递归地对数字的数字进行排序

问题描述 投票:3回答:5

我对编程非常陌生,只是在大学里学习它。我有一个任务,我必须在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;
}

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

java algorithm sorting recursion
5个回答
2
投票

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

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

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并考虑如何在这种情况下实现它们。


1
投票

每个递归方法应包括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;
}

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


1
投票

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

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())。

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


1
投票

这是一个带有一个函数和一个参数的纯递归;没有日志,电源,字符串转换或循环。我说这是一个非常困难的递归练习,即使不仅仅是初学者。我希望这有帮助。随意要求任何澄清。 (也欢迎简化。)

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();

0
投票

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

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。这本来会容易得多。但是谢谢大家:)

© www.soinside.com 2019 - 2024. All rights reserved.