递归 - 具有 void 函数返回类型的反向 LinkedList
Posted
技术标签:
【中文标题】递归 - 具有 void 函数返回类型的反向 LinkedList【英文标题】:Recursion - Reverse LinkedList with void function return type 【发布时间】: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;
我无法想象这个问题是否会有这样的解决方案。
有什么建议吗?
【问题讨论】:
向我们展示您的尝试。 为什么不用尾递归? 相当危险的实现,但对于练习来说还可以。递归通常在教学中使用很多,但如果您不知道最大递归深度,则不应在现实世界中使用递归。当深度取决于某些输入数据时,您很容易遇到 *** 错误。在大学或编程课程中通常会省略此细节。 【参考方案1】:经过测试,它可以工作(假设您有自己的链表实现,其中 Node
s 知道 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是可访问的
-
基本情况 - 如果 Node 为空,则不执行任何操作并返回。
如果 Node->Next 为 null,则“使其成为头部”并返回。
其他情况 - 反转 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
为例。以上是关于递归 - 具有 void 函数返回类型的反向 LinkedList的主要内容,如果未能解决你的问题,请参考以下文章