原题网址:http://www.lintcode.com/zh-cn/problem/remove-nth-node-from-end-of-list/#
给定一个链表,删除链表中倒数第n个节点,返回链表的头节点。
注意事项
链表中的节点个数大于等于n
给出链表1->2->3->4->5->null和 n = 2.
删除倒数第二个节点之后,这个链表将变成1->2->3->5->null.
O(n)时间复杂度
1 /** 2 * Definition of singly-linked-list: 3 * class ListNode { 4 * public: 5 * int val; 6 * ListNode *next; 7 * ListNode(int val) { 8 * this->val = val; 9 * this->next = NULL; 10 * } 11 * } 12 */ 13 14 class Solution { 15 public: 16 /** 17 * @param head: The first node of linked list. 18 * @param n: An integer 19 * @return: The head of linked list. 20 */ 21 ListNode * removeNthFromEnd(ListNode * head, int n) { 22 // write your code here 23 if (n==0||head==NULL) 24 { 25 return head; 26 } 27 28 ListNode *temp=head; 29 int total=1; 30 while(temp->next != NULL) //蠢哭了,此处关键字应为while而不是if,然而第一次写的是if还检查不出来哪里有问题; 31 { 32 total++; 33 temp=temp->next; 34 } 35 //cout<<"total="<<total<<endl; //晕菜,注释cout的两行代码是检测错误用; 37 38 int index=total-n+1; 39 //cout<<"index="<<index<<endl; 40 ListNode *pre=NULL,*curNode=head; 41 42 if (index==1) 43 { 44 head=head->next; 45 return head; 46 } 47 48 for (int i=1;i<index;i++)//找前驱结点; 49 { 50 pre=curNode; 51 curNode=curNode->next; 52 } 53 pre->next=curNode->next; 54 return head; 55 } 56 };
方法二
参考:
1 https://blog.csdn.net/lyy_hit/article/details/49449589
2 https://www.cnblogs.com/libaoquan/p/6806769.html
3 https://www.cnblogs.com/theskulls/p/4868893.html
要删除倒数第n个结点,只要找到倒数第n+1个结点即可。定义两个指针pre和cur,初始两个指针都为head。指针每走一步(每循环一次),指向的都是下一个位置,所以cur走n步后,指向第n+1个结点。
如果第n+1个结点为NULL,说明只有n个结点,倒数第n个结点即头结点,要删除的为头结点;
否则,n小于总结点数t,cur继续向前走,直到尾节点,同时pre跟着向前走,二者步数一样为t-(n+1),循环结束时pre指向正数第t-n个结点,即倒数第n+1个结点。
删除节点时注意头节点的判断
脑子笨,n和n+1搞得我晕头转向,梳理了半天,我发现自己对于类似索引啊,个数啊很容易懵逼,尤其这种非要反着数数的妖艳jian货,一口老血吐出来
顺便,这还是参照着前辈们的代码梳理出来的,要是给我两个指针让我自己想,我估计花的时间会更多……我也很绝望
1 /** 2 * Definition of singly-linked-list: 3 * class ListNode { 4 * public: 5 * int val; 6 * ListNode *next; 7 * ListNode(int val) { 8 * this->val = val; 9 * this->next = NULL; 10 * } 11 * } 12 */ 13 14 class Solution { 15 public: 16 /** 17 * @param head: The first node of linked list. 18 * @param n: An integer 19 * @return: The head of linked list. 20 */ 21 ListNode * removeNthFromEnd(ListNode * head, int n) { 22 // write your code here 23 if (n==0||head==NULL) 24 { 25 return head; 26 } 27 28 ListNode *pre=head,*cur=head; 29 for (int i=0;i<n;i++) //cur走了n步,循环完指向第n+1个结点; 30 { 31 cur=cur->next; 32 } 33 34 if (cur==NULL)//说明n为结点总数,要删除的为头结点; 35 { 36 head=head->next; 37 return head; 38 } 39 40 while(cur->next!=NULL) //此循环里cur和pre走的步数一样,指针每走一步,指向的都是下一个位置,所以cur走了(总数-(n+1))次,最后指向尾节点; 41 { //pre走了同样的步数,指向第(总数-n)个结点,即倒数第n+1个结点; 42 cur=cur->next; 43 pre=pre->next; 44 } 45 46 pre->next=pre->next->next; 47 return head; 48 } 49 };
代码改进,头指针不存储数据,有效头节点为newhead->next(原head),这样删除节点时不用引入头结点的判断。
啊,真是学无止境,膜拜大神们
1 /** 2 * Definition of singly-linked-list: 3 * class ListNode { 4 * public: 5 * int val; 6 * ListNode *next; 7 * ListNode(int val) { 8 * this->val = val; 9 * this->next = NULL; 10 * } 11 * } 12 */ 13 14 class Solution { 15 public: 16 /** 17 * @param head: The first node of linked list. 18 * @param n: An integer 19 * @return: The head of linked list. 20 */ 21 ListNode * removeNthFromEnd(ListNode * head, int n) { 22 // write your code here 23 if (n==0||head==NULL) 24 { 25 return head; 26 } 27 ListNode *newhead=new ListNode(0); 28 newhead->next=head; 29 ListNode *pre=newhead,*cur=newhead; 30 for (int i=0;i<n;i++) //循环n次,cur指向第n个结点; 31 { 32 cur=cur->next; 33 } 34 while(cur->next!=NULL) //n不是结点总数; 35 { 36 cur=cur->next; 37 pre=pre->next; 38 } 39 //循环执行t-n次,pre指向第t-n个结点,倒数第n+1个结点; 40 pre->next=pre->next->next; 41 return newhead->next;//这里如果没有释放删除结点的指针,也可以返回head; 42 } 43 };