【问题标题】:Create a list with following numbers (recursive)创建一个包含以下数字的列表(递归)
【发布时间】:2020-03-22 09:50:58
【问题描述】:

我需要该函数返回一个包含以下数字的列表,所以follow(null, 5); 应该返回[1, 2, 3, 4, 5]

我试过了:

public static Node <Integer> follow(Node<Integer>list, int num)
{
    if(num==1)
        return new Node<Integer>(1);
    return new Node<Integer>(num, follow(list, num-1));
}

但这会返回[5, 4, 3, 2, 1] 而不是[1, 2, 3, 4, 5] 我需要在函数中进行什么更改才能返回[1, 2, 3, 4, 5]? (我不想添加其他功能)

这是节点类:

package unit4.collectionsLib;

public class Node<T>
{
    private T info;
    private Node<T> next;

    public Node(T x)
    {
        this.info = x;
        this.next = null;
    }

    public Node(T x, Node<T> next)
    {
        this.info = x;
        this.next = next;
    }

    public T getValue()
    {
        return(this.info);
    }



}

【问题讨论】:

  • 您不需要我们的帮助,您已经拥有所需的所有信息。查看您的代码:为什么将较小的数字放在较高数字的右侧而不是左侧? (拿一支铅笔和一些纸,从字面上写出当你从 num=2 开始时每一步发生的事情)
  • Node的构造函数是什么?
  • 补充迈克的评论:问题在于你的递归顺序。
  • 我无法理解如何订购,这令人困惑。
  • 你仍然可以使用相同的实现然后反转它的顺序,如果它是一个数组。

标签: java list recursion nodes


【解决方案1】:
public static Node <Integer> follow(Node<Integer>list, int num)
{
    if(num==1)
        return new Node<Integer>(num, list);
    return follow(new Node<Integer>(num, list), num-1);
}

这将返回[1, 2, 3, 4, 5]

【讨论】:

    【解决方案2】:

    更新

    鉴于您评论的限制,您可以从设置为 1 的节点开始并向上计数。

    package stackoverflow;
    
    public class Question {
        public static void main (String [] args){
            Node<Integer> list = new Node<Integer>(1);
            list.setNext(follow(list, 5));
            print(list);
        }
    
        public static Node <Integer> follow(Node<Integer>list, int num)
        {
            if(list.getValue() == num)
                return null;
    
            Node<Integer> nextNode = new Node<Integer>(list.getValue()+1);
            nextNode.setNext(follow(nextNode, num));
            return nextNode;
        }
    
        public static void print(Node<Integer> list) {
            System.out.println(list.getValue());
            if (list.next == null) {
                return;
            }
    
            print(list.next);
        }
    
        public static class Node<T>
        {
            private T info;
            private Node<T> next;
    
            public Node(T x)
            {
                this.info = x;
                this.next = null;
            }
    
            public Node(T x, Node<T> next)
            {
                this.info = x;
                this.next = next;
            }
    
            public T getValue()
            {
                return(this.info);
            }
    
            public void setNext(Node<T> next) {
                this.next = next;
            }
        }
    }
    

    结果

    1
    2
    3
    4
    5
    

    老答案

    不是最干净的解决方案,但考虑到所要求的内容,您可以计算以下方法中的信息字段。我使用了一个类变量max 来了解列表需要多大

    package stackoverflow;
    
    public class Question {
        static int max = 5;
        public static void main (String [] args){
            Node<Integer> list = follow(null, max);
            print(list);
        }
    
        public static Node <Integer> follow(Node<Integer>list, int num)
        {
            int calculatedInfo = max - (num - 1);
            if(calculatedInfo == max)
                return new Node<Integer>(max);
            return new Node<Integer>(calculatedInfo, follow(list, num-1));
        }
    
        public static void print(Node<Integer> list) {
            System.out.println(list.info);
            if (list.next == null) {
                return;
            }
    
            print(list.next);
        }
    
        public static class Node<T>
        {
            private T info;
            private Node<T> next;
    
            public Node(T x)
            {
                this.info = x;
                this.next = null;
            }
    
            public Node(T x, Node<T> next)
            {
                this.info = x;
                this.next = next;
            }
    
            public T getValue()
            {
                return(this.info);
            }
        }
    }
    

    结果

    1
    2
    3
    4
    5
    

    最大结果 = 10

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    

    【讨论】:

    • 该函数需要使用 num 和 list 并且没有更多的变量。
    • @yoav 编辑您的问题并解释您的要求。您的问题没有作为限制提及您的评论。
    • 我不确定这个解决方案是递归的,因为你必须用 max 变量调用函数。
    • @yoav 代码调用跟随在跟随中,那不是递归吗?查看更新的答案。
    【解决方案3】:

    随着您深入递归,您正在从 5 倒数到 1。如果在深入递归的过程中从 1 数到 5 会怎样?数字的顺序是什么?

    要实现这一点,最大数量(在您的示例中为 5)需要在每个递归步骤中都可用,因此您需要一个额外的参数。

    public static Node <Integer> follow(Node<Integer>list, int num, int max)
    {
        if(num==max)
            return new Node<Integer>(max);
        return new Node<Integer>(num, follow(list, num + 1, max));
    }
    

    如果您仍然希望在不传递额外参数的情况下方便地调用,您可以通过添加该方法的便捷版本来重载该方法:

    public static Node <Integer> follow(Node<Integer>list, int max)
    {
        return follow(list, 1, max);
    }
    

    【讨论】:

    • 此解决方案更改了函数的签名。有一个尾递归解决方案可以使签名保持不变。 (并且编译器可能能够优化递归。)
    • @Code-Apprentice 添加重载方法不会改变函数的签名。您甚至可以将第一种方法设为私有。这是一种非常常见的递归方式——因为递归步骤可能需要额外的参数(如本例中的累加器或收集器,公共方法上不存在)
    • 是的,这是一个常用的递归工具。在这种特殊情况下,这是不必要的。可以修改原始代码中的 return 语句以获得所需的行为,而无需引入辅助函数。
    【解决方案4】:
    public static Node <Integer> follow(Node<Integer>list, int num)
    {
        if(num==1)
            return new Node<Integer>(1);
    

    在您的基本情况下,您正在创建一个编号最小的节点。如何更改它以将最小的数字放在列表的前面?

        return new Node<Integer>(num, follow(list, num-1));
    

    在递归情况下,您将当前数字添加到列表的前面。你如何改变它以在末尾添加当前数字?

    }
    

    【讨论】:

    • 那么如何将当前号码添加到列表末尾?这就是问题的症结所在。正如在列表处理中经常做的那样,列表被定义为一个单元素头部和一个本身就是一个列表的尾部。以这种递归方式将单个元素添加到列表的末尾并非易事。
    • @ErwinBolwidt “那么如何将当前号码添加到列表末尾?”解决方案是切换对follow() 的递归调用的嵌套和new Node() 的创建。
    • @ErwinBolwidt 也许我的措辞选择不当。我猜你并没有真正“将当前号码添加到列表的末尾”。相反,您将其添加到传入的 list 参数之前,而不是在递归调用 follow() 的返回之前。
    • @ErwinBolwidt 在伪代码中,构建follow(follow(follow(3)), 2), 1)follow(follow(follow(1), 2), 3) 之间的区别。
    • 这意味着你有一个列表作为头部,单个项目作为尾部。很少有算法可以使用它(实际上,实际上您刚刚说过“以相反的顺序遍历列表”,因为更改构造函数参数的顺序不会更改数据结构)。并且向后遍历 head|tail 列表的效率非常低,因为它甚至需要递归到第一个元素。
    猜你喜欢
    • 2019-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-31
    • 1970-01-01
    相关资源
    最近更新 更多