Java 反转链表的前K个节点,为什么在最后一次迭代中执行两次递归
在解决反转链表的前K个元素的问题时,我编写了下面的递归代码,但最后一次迭代执行了两次,即对于K=1,函数调用reverseNode()发生了两次。任何人都不知道为什么会这样。如果我做错了什么,请纠正我Java 反转链表的前K个节点,为什么在最后一次迭代中执行两次递归,java,algorithm,recursion,data-structures,linked-list,Java,Algorithm,Recursion,Data Structures,Linked List,在解决反转链表的前K个元素的问题时,我编写了下面的递归代码,但最后一次迭代执行了两次,即对于K=1,函数调用reverseNode()发生了两次。任何人都不知道为什么会这样。如果我做错了什么,请纠正我 Example : If input is 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 and k = 4 then output is 4 -> 3 -> 2 -&g
Example :
If input is
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8
and k = 4 then output is
4 -> 3 -> 2 -> 1 -> 5 -> 6 -> 7 -> 8
public void reverseListRecursion(int k) {
this.reverseNode(null, headNode,k);
}
public void reverseNode(Node node, Node nextNode,int k) {
while (k > 0) {
k = k-1;
this.reverseNode(node, nextNode.next,k);
}
if (k == 0) {
this.kNode = nextNode;
this.kNode.next = null;
}
if (node == null) {
nextNode.next = this.kNode;
} else {
nextNode.next = node;
}
}
为我的逻辑工作的代码,它是预期的工作。但当我试图在“if”条件中使用变量“k”而不是“presentCounter”时,它就错了。谁能告诉我原因吗
public void reverseListRecursion(int count) {
this.reverseNode(null, headNode, count);
System.out.println("\n");
this.display(this.headNode);
}
/*
* Condition K <= Length of linked list.
*/
public void reverseNode(Node node, Node nextNode, int k) {
int presentCounter = k;
if (k > 1) {
k = k - 1;
this.reverseNode(nextNode, nextNode.next, k);
}
if (presentCounter == 1) {
this.kNode = nextNode.next; // Saving K's Next Node
this.headNode = nextNode; // Setting K node as head node
}
if (node == null) {
nextNode.next = this.kNode;
} else
nextNode.next = node;
}
public void reverseListRecursion(整数计数){
this.reverseNode(null,headNode,count);
System.out.println(“\n”);
this.display(this.headNode);
}
/*
*条件K(1){
k=k-1;
this.reverseNode(nextNode,nextNode.next,k);
}
if(presentCounter==1){
this.kNode=nextNode.next;//保存K的下一个节点
this.headNode=nextNode;//将K节点设置为head节点
}
if(node==null){
nextNode.next=this.kNode;
}否则
nextNode.next=节点;
}
您的递归应该是
if (k > 0) { // and not while
k = k-1;
this.reverseNode(node, nextNode.next,k);
}
...
您在问题中提供的此代码存在几个问题:
public void reverseListRecursion(int k) {
this.reverseNode(null, headNode,k);
}
public void reverseNode(Node node, Node nextNode,int k) {
while (k > 0) {
k = k-1;
this.reverseNode(node, nextNode.next,k);
}
if (k == 0) {
this.kNode = nextNode;
this.kNode.next = null;
}
if (node == null) {
nextNode.next = this.kNode;
} else {
nextNode.next = node;
}
}
null
)就是每次调用中该参数的值。因此,最后一个if
条件的结果将始终相同。这看起来不对if
条件将始终为true,因为它与前面的条件相反,而条件在前面。因此,不需要对k==0
进行测试
if
块中的代码使this.kNode
成为nextNode
的同义词,然后其next
属性设置为null
。应该没有理由将任何next
属性设置为null
。如果有的话,它将打破链表if
块中,nextNode
的next
属性设置为nextNode
(参见上一点,它表明this.kNode
是nextNode
的同义词)。现在你有了一个自引用节点,这是你永远都不想拥有的。此代码使第一个k+1节点自引用,从而有效地将它们从原始链接列表中分离出来this.kNode.next=null
和nextNode.next=this.kNode
不是您将对列表的第一个节点执行的操作list = 1 2 3 4 5 6 7 8
k = 4
将原始第一个节点之后的节点移动到列表的开头
list = 2 1 3 4 5 6 7 8
k = 3
list = 3 2 1 4 5 6 7 8
k = 2
list = 4 3 2 1 5 6 7 8
k = 1
将原始第一个节点之后的节点移动到列表的开头
list = 2 1 3 4 5 6 7 8
k = 3
list = 3 2 1 4 5 6 7 8
k = 2
list = 4 3 2 1 5 6 7 8
k = 1
将原始第一个节点之后的节点移动到列表的开头
list = 2 1 3 4 5 6 7 8
k = 3
list = 3 2 1 4 5 6 7 8
k = 2
list = 4 3 2 1 5 6 7 8
k = 1
当k=1时,无需再移动
以下是您的代码的外观:
public void reverseListRecursion(int k) {
// The reversal returns the node that took the first position
this.headNode = this.reverseNode(this.headNode, k, this.headNode);
};
public Node reverseNode(Node origFirstNode, int k, Node currFirstNode) {
// If 1 element needs to be reversed, there is nothing to do:
if (k <= 1) return currFirstNode;
// Move the node after the original first node before the current first node
Node movingNode = origFirstNode.next;
origFirstNode.next = movingNode.next;
movingNode.next = currFirstNode;
// The moved node is now the current first node. Repeat:
return this.reverseNode(origFirstNode, k-1, movingNode);
};
这将反转给定节点后面的节点
下面是一个实时片段,其中的代码被翻译为JavaScript(仅用于演示):
//节点类
功能节点(val,下一个){
this.val=val;
this.next=next;
this.toString=函数(级联){
如果(!cascade | | this.next==null)返回“(“+this.val+”)”;
如果(this.next==this)返回'('+this.val+')-loop';
返回'('+this.val+')->'+this.next.toString(true);
}
}
//列表类
函数列表(){
this.headNode=null;
this.reverseListRecursion=函数(k){
//反转返回第一个位置的节点
this.headNode=this.reverseNode(this.headNode,k,this.headNode);
};
this.reverseNode=函数(origFirstNode,k,currFirstNode){
//如果需要反转1个元素,则无需执行任何操作:
如果(k=0;i--){
this.headNode=新节点(arr[i],this.headNode);
}
}
this.toString=函数(){
返回'{'+this.headNode.toString(true)+'}';
}
}
var输出=[];
//样本数据
var list=新列表();
列表。插入([1,2,3,4,5,6,7,8]);
output.push('before:'+list);
//打反向电话
列表。反向撤销(4);
output.push('after:'+list);
//在代码段中显示结果
document.write(输出.join(“
”)代码>(请给出注释代码,说明您不满意的地方,并尝试将示例与代码分开。)我不确定我是否理解该问题;实现的输出是否如预期的那样?似乎是这样。只需在调试器中单步执行即可查看发生了什么。您最好使用递归或循环,但不能同时使用两者。尝试将while
替换为if
。