174 删除链表中倒数第n个节点

原题网址: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)时间复杂度

标签 
 
方法一:
统计链表结点个数total,然后计算要删除的结点index,再找到删除节点与其前驱节点,删除
 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 };

方法二

参考:

https://blog.csdn.net/lyy_hit/article/details/49449589

https://www.cnblogs.com/libaoquan/p/6806769.html

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 };

 

posted @ 2018-03-28 14:27  eeeeeeee鹅  阅读(225)  评论(0编辑  收藏  举报