【问题标题】:Recursion - Reverse LinkedList with void function return type递归 - 具有 void 函数返回类型的反向 LinkedList
【发布时间】:2013-07-05 17:36:09
【问题描述】:

我试图使用递归来反转链表。我得到了解决方案,但无法解决在互联网上找到的以下问题。

使用递归反转链表,但函数应该有 void 返回类型。

我能够实现返回类型为 Node 的函数。以下是我的解决方案。

public static Node recursive(Node start) {

    // exit condition
    if(start == null || start.next == null)
        return start;

    Node remainingNode = recursive(start.next);

    Node current = remainingNode;

    while(current.next != null)
           current = current.next;

    current.next = start;
    start.next = null;
    return remainingNode;
 }

我无法想象这个问题是否会有这样的解决方案。

有什么建议吗?

【问题讨论】:

  • 向我们展示您的尝试。
  • 为什么不用尾递归?
  • 相当危险的实现,但对于练习来说还可以。递归通常在教学中使用很多,但如果您不知道最大递归深度,则不应在现实世界中使用递归。当深度取决于某些输入数据时,您很容易遇到 StackOverflow 错误。在大学或编程课程中通常会省略此细节。

标签: java algorithm data-structures recursion linked-list


【解决方案1】:

经过测试,它可以工作(假设您有自己的链表实现,其中 Nodes 知道 next 节点)。

public static void reverse(Node previous, Node current) {
    //if there is next node...
    if (current.next != null) {
        //...go forth and pwn
        reverse(current, current.next);
    }

    if (previous == null) {
        // this was the start node
        current.next= null;
    } else {
        //reverse
        current.next= previous;
    }   
}

你用它来称呼它

reverse(null, startNode);

【讨论】:

  • +1 表示良好的算法。但是,您应该为反向链表设置头节点。调用reverse(null, startNode);后startNode会和list的head一样,无法找到list的head。
  • tm99 确实有效。只是 startNode 现在是最后一个。检查此测试示例:pastebin.com/JxyDLHab
  • 改为发布我的解决方案
【解决方案2】:
public void recursiveDisplay(Link current){

        if(current== null)
           return ;
        recursiveDisplay(current.next);
        current.display();
}

【讨论】:

    【解决方案3】:
    static StringBuilder reverseStr = new StringBuilder();
    
    public static void main(String args[]) {
        String str = "9876543210";
        reverse(str, str.length() - 1);
    }
    
    public static void reverse(String str, int index) {
        if (index < 0) {
            System.out.println(reverseStr.toString());
        } else {
            reverseStr.append(str.charAt(index));
            reverse(str, index - 1);
            index--;
        }
    }
    

    【讨论】:

      【解决方案4】:

      这应该可以工作

      static void reverse(List list, int p) {
          if (p == list.size() / 2) {
              return;
          }
          Object o1 = list.get(p);
          Object o2 = list.get(list.size() - p - 1);
          list.set(p, o2);
          list.set(list.size() - p - 1, o1);
          reverse(list, p + 1);
      }
      

      虽然要使用 LinkedList 高效,但应该将其重构为使用 ListIterator

      【讨论】:

        【解决方案5】:

        我不熟悉Java,但这里有一个C++ 版本。反转列表后,仍然保留了列表的头部,这意味着仍然可以从旧的列表头部List* h访问该列表。

        void reverse(List* h) {
            if (!h || !h->next) {
              return;
            }
            if (!h->next->next) {
              swap(h->value, h->next->value);
              return;
            }
            auto next_of_next = h->next->next;
            auto new_head = h->next;
            reverse(h->next);
            swap(h->value, new_head->value);
            next_of_next->next = new_head;
            h->next = new_head->next;
            new_head->next = nullptr;
          }
        

        【讨论】:

          【解决方案6】:

          试试这个代码 - 它确实有效

              public static ListElement reverseListConstantStorage(ListElement head) {
              return reverse(null,head);
          }
          
          private static ListElement reverse(ListElement previous, ListElement current) {
          
              ListElement newHead = null;
              if (current.getNext() != null) {
                  newHead = reverse(current, current.getNext());
              } else {//end of the list
                  newHead=current;
                  newHead.setNext(previous);
              }
          
              current.setNext(previous);        
              return newHead;        
          }
          

          【讨论】:

            【解决方案7】:
            public static Node recurse2(Node node){
                Node head =null;
                if(node.next == null) return node;
                Node previous=node, current = node.next;
                head = recurse2(node.next);
                current.next = previous;
                previous.next = null;
                return head;
            
            }
            

            调用函数时,返回值如下:

             list.head=recurse2(list.head);
            

            【讨论】:

              【解决方案8】:

              下面的函数是基于 darijan 选择的答案,我所做的只是添加 2 行代码,以便它适合你们想要工作的代码:

              public void reverse(Node previous, Node current) {
                      //if there is next node...
                      if (current.next != null) {
                          //...go forth and pwn
                          reverse(current, current.next);
                      }
                      else this.head = current;/*end of the list <-- This line alone would be the fix
                      since you will now have the former tail of the Linked List set as the new head*/
              
              
                      if (previous == null) {
                          // this was the start node
                          current.next= null;
                          this.tail = current; /*No need for that one if you're not using a Node in 
                          your class to represent the last Node in the given list*/
                      } else {
                          //reverse
                          current.next= previous;
                      }   
                  }
              

              另外,我已将其更改为非静态函数,因此使用它的方式是:myLinkedList.reverse(null, myLinkedList.head);

              【讨论】:

                【解决方案9】:

                这是我的版本 - void ReverseWithRecursion(Node currentNode) - 这是LinkListDemo类的方法,所以head是可访问的

                1. 基本情况 - 如果 Node 为空,则不执行任何操作并返回。 如果 Node->Next 为 null,则“使其成为头部”并返回。
                2. 其他情况 - 反转 currentNode 的 Next。

                  public void ReverseWithRecursion(Node currentNode){
                     if(currentNode == null) return;
                     if(currentNode.next == null) {head = currentNode; return;}
                  
                     Node first = currentNode;
                     Node rest = currentNode.next;
                  
                     RevereseWithRecursion(rest);
                  
                     first.next.next = first;
                     first.next = null;
                  }
                  

                你这样称呼它-

                LinkListDemo ll = new LinkListDemo(); // assueme class is available
                ll.insert(1);  // Assume method is available
                ll.insert(2);
                ll.insert(3);
                ll.ReverseWithRecursion(ll.head);
                

                【讨论】:

                  【解决方案10】:

                  我能想到的最简单的方法是:

                  public static <T> void reverse( LinkedList<T> list )
                  {
                      if (list.size() <= 1) {
                          return;
                      }
                      T first = list.removeFirst();
                      reverse( list);
                      list.addLast( first );
                  }
                  

                  【讨论】:

                  • 请不要开玩笑。如果可以使用库LinkedList,为什么不使用Collection.reverse?如果您不使用该库,为什么不向我们展示addLast 的工作原理?请不要说你要遍历返回的列表。
                  • @Icn 这只是一个递归练习。链表的实现不是本题的主题,我只以LinkedList为例。
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-03-24
                  • 1970-01-01
                  • 2012-08-02
                  • 2017-02-08
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多