C++ 寻找「;从末端算起的第n个节点;链表的定义
这似乎返回了正确的答案,但我不确定这是否是处理事情的最佳方式。看起来我访问前n个节点的次数太多了。有什么建议吗?请注意,我必须使用单链接列表来完成此操作C++ 寻找「;从末端算起的第n个节点;链表的定义,c++,linked-list,C++,Linked List,这似乎返回了正确的答案,但我不确定这是否是处理事情的最佳方式。看起来我访问前n个节点的次数太多了。有什么建议吗?请注意,我必须使用单链接列表来完成此操作 Node *findNodeFromLast( Node *head, int n ) { Node *currentNode; Node *behindCurrent; currentNode = head; for( int i = 0; i < n; i++ ) { if( curre
Node *findNodeFromLast( Node *head, int n )
{
Node *currentNode;
Node *behindCurrent;
currentNode = head;
for( int i = 0; i < n; i++ ) {
if( currentNode->next ) {
currentNode = currentNode->next;
} else {
return NULL;
}
}
behindCurrent = head;
while( currentNode->next ) {
currentNode = currentNode->next;
behindCurrent = behindCurrent->next;
}
return behindCurrent;
}
public ListNode NthNodeFromEnd(int n){
ListNode pTemp = head, NthNode = null;
for(int count=1; count<n;count++){
if(pTemp!=null){
pTemp = pTemp.getNext();
}
}
while(pTemp!=null){
if(NthNode==null){
NthNode = head;
}
else{
NthNode = NthNode.getNext();
}
pTemp = pTemp.getNext();
}
if(NthNode!=null){
NthNode = NthNode.getNext();
return NthNode;
}
return null;
}
Node*findNodeFromLast(Node*head,int-n)
{
节点*当前节点;
节点*落后于电流;
currentNode=头部;
对于(int i=0;i下一步){
currentNode=currentNode->next;
}否则{
返回NULL;
}
}
落后电流=水头;
同时(当前节点->下一步){
currentNode=currentNode->next;
落后电流=落后电流->下一步;
}
逆流返回;
}
您可以使用双链接列表,这是一个还存储其父级地址的链接列表。横向比较容易,因为你可以从末尾开始,一路工作到开头。你的运行时间仍然是O(n),所以我看不出有什么问题
从概念上讲,可以将列表分为两部分:返回节点之前的部分和返回节点之后的部分。其中一个部分必须步行两次。您的实现选择了第一个,其优点是没有额外的内存使用(除了几个临时变量)
或者,您可以创建一个堆栈,遍历列表并将每个元素放入堆栈,然后弹出n个项目。然后,你将两次走到列表的末尾,而不是开始。这样做的缺点是将列表存储在内存中两次。(通过只存储n个元素并在添加新元素时将其从堆栈底部删除,可以使堆栈变得更智能;然后只使用足够的空间来存储n个节点。)
我假设你不能通过在适当的地方反转列表来吹走它。然后是恒定内存,仍然是O(n),仍然在列表末尾走两次。开始两个指针。将第一个
N
元素向前移动,然后将每个指针移动1个元素。当第一个指针到达终点时,第二个指针将给出答案
编辑:是的,它与问题中给出的代码几乎相同。但我觉得伪代码更清楚。要回答这个问题,没有其他go,因为first
N
元素必须访问两次。如果N
很小,则无所谓。如果N
较大,则第二个循环较小。因此,它始终是一个O(n)
解决方案。首先计算列表中的节点数。然后再次遍历,减少n个节点。仍然是一种O(n)算法,这是不可避免的。另一种不需要访问两次节点的方法如下:
创建一个大小为n的空数组,从索引0开始指向该数组的指针,并从链表的开头开始迭代。每次访问节点时,将其存储在数组的当前索引中,并前进数组指针。填充数组时,环绕并覆盖以前存储的元素。当您到达列表的末尾时,指针将指向列表末尾的元素n
但这也只是一个O(n)算法。你现在所做的一切都很好。我看不出有什么令人信服的理由来更改它。Node*fetchnnoderfrmlast(int arg)
Node* fetchNNodeFrmLast(int arg)
{
Node *temp = head;
Node *nNode = head;
if(head == NULL || arg <= 0)
{
Printf("Either head is null or invalid number entered");
return;
}
while(temp != NULL)
{
temp = temp->next;
if(arg > 1)
{
arg--;
continue;
}
nNode = nNode->next;
}
return nNode;
}
{
节点*温度=头部;
节点*nNode=头部;
if(head==NULL | | arg next;
如果(arg>1)
{
arg--;
继续;
}
nNode=nNode->next;
}
返回nNode;
}
我正在使用一个将递增的静态变量'I'
当从列表末尾回溯时。就像在
问题陈述,我们将基本上跟踪第n个
从链表末尾开始的元素。
递归帮助我们从结尾跟踪
static int i;
public static void NthToLast(LinkedListNode head, int n)
{
if (head == null)
return;
NthToLast(head.Next, n);
i++;
if (n == i)
{
Console.WriteLine("Mth to last" + head.Data);
return;
}
}
这很简单。。
取两个指针p1,p2
在p1移动“n”个节点后启动p2,并让p1移动到最后一个。p2指向的节点将是最后一个节点的第n个节点。保持两个指针n个节点之间的间隔。当第一个指针到达尾部时,第二个指针将指向所需的节点 代码:
}此代码似乎更清晰
public Node<T> findNthNodeFromLast(int n) {
Node<T> current = head;
Node<T> findElement = head;
int length = 0;
while (current != null && current.next != null) {
length++;
if (length >= n) {
findElement = findElement.next;
}
current = current.next;
}
return findElement;
}
公共节点findNthNodeFromLast(int n){
节点电流=头;
节点findElement=头;
整数长度=0;
while(当前!=null&¤t.next!=null){
长度++;
如果(长度>=n){
findElement=findElement.next;
}
当前=当前。下一步;
}
返回findElement;
}
使用两个指针pTemp和NthNode。最初,两个指针都指向列表的头节点。NthNode仅在pTemp移动n次后才开始移动。从这两个指针开始向前移动,直到pTemp到达列表的末尾。因此,NthNode指向链接列表末尾的第n个节点
Node *findNodeFromLast( Node *head, int n )
{
Node *currentNode;
Node *behindCurrent;
currentNode = head;
for( int i = 0; i < n; i++ ) {
if( currentNode->next ) {
currentNode = currentNode->next;
} else {
return NULL;
}
}
behindCurrent = head;
while( currentNode->next ) {
currentNode = currentNode->next;
behindCurrent = behindCurrent->next;
}
return behindCurrent;
}
public ListNode NthNodeFromEnd(int n){
ListNode pTemp = head, NthNode = null;
for(int count=1; count<n;count++){
if(pTemp!=null){
pTemp = pTemp.getNext();
}
}
while(pTemp!=null){
if(NthNode==null){
NthNode = head;
}
else{
NthNode = NthNode.getNext();
}
pTemp = pTemp.getNext();
}
if(NthNode!=null){
NthNode = NthNode.getNext();
return NthNode;
}
return null;
}
public listnothNodeFromend(int n){
ListNode pTemp=head,NthNode=null;
对于(int count=1;count这是一个单链接列表,没有关于列表中有多少项的信息吗?正确。单链接列表。只是为了挑剔,我将命名为currentNode
,并将currentNode
命名为其他内容。关于环形缓冲区的有趣文章:相关帖子-确实,对不起,我是叔叔这必须通过一个单链表来完成。这有具体的原因吗?我看不出使用它会产生任何问题…使用一个指针数组,每个单元格一个。唯一的问题是更新它的开销…这与他当前的解决方案不同吗?…这显然是原始帖子中的代码实现的(假设操作正确)这不是问题中的实现所做的吗?我同意alg必须是O(n)。我不同意“前n个元素必须访问两次”。请参阅我的答案,了解访问所有节点一次的alg。我同意这是正确的