20
04/2015
[LeetCode] Remove Nth Node From End of List
Remove Nth Node From End of List
Given a linked list, remove the nth node from the end of list and return its head.
For example,
Given linked list: 1->2->3->4->5, and n = 2. After removing the second node from the end, the linked list becomes 1->2->3->5.
Note:
Given n will always be valid.
Try to do this in one pass.
解题思路:
1、最简单的办法就是两遍扫描。第一次扫描计算出链表的长度,第二次找到删除节点的前一个节点。注意头结点的特殊性。
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* removeNthFromEnd(ListNode* head, int n) { int len=0; ListNode* p=head; while(p!=NULL){ len++; p=p->next; } if(len==0||n>len||n<1){ return NULL; } if(n==len){ p=head; head=p->next; delete p; return head; } p=head; for(int i=0; i<len-n-1; i++){ p=p->next; } ListNode* q=p->next; p->next=q->next; delete q; return head; } };
2、这样不满足题意了。题目要求只扫描一遍。可以考虑回溯,又因为它是单链表,因此考虑递归来回溯。下面的代码中,调用递归方法一次,便可以得到链表的长度和要删除节点的前一个节点。
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* removeNthFromEnd(ListNode* head, int n) { if(head==NULL||n<=0){ return NULL; } int count=0; ListNode* q=NULL; getBNthNode(head, q, n+1, count); //此时count即为链表的长度 if(n>count){ return NULL; } if(n==count){ q=head; head=q->next; delete q; return head; } ListNode* p=q->next; q->next=p->next; delete p; return head; } void getBNthNode(ListNode* p, ListNode* &q, int n, int& count){ if(p!=NULL){ getBNthNode(p->next, q, n, count); count++; if(count==n){ q=p; //当前p是第n个 } } } };
3、用一个vector存储所有的指针,可以通过vector获得任何一个节点元素。
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* removeNthFromEnd(ListNode* head, int n) { if(head==NULL || n<=0){ return NULL; } vector<ListNode*> pVector; ListNode* p=head; while(p!=NULL){ pVector.push_back(p); p=p->next; } int len=pVector.size(); if(n>len){ return NULL; } if(n==len){ p=head; head=p->next; delete p; return head; } pVector[len-n-1]->next=pVector[len-n]->next; delete pVector[len-n]; return head; } };
4、用两个指针来做。第一个指针先走n步,第二个指针再开始走,待第一个指针走到最后一个节点,第二个指针刚好走到了倒数第n+1个节点
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* removeNthFromEnd(ListNode* head, int n) { if(head==NULL || n<=0){ return NULL; } ListNode* p=head, *q=head; int i=0; while(i<n&&p!=NULL){ p=p->next; i++; } if(i<n){ //表示不够n个 return NULL; } if(p==NULL){ //表示刚好n个 head=head->next; delete q; return head; } while(p->next!=NULL){ //直到p指向最后一个节点 p=p->next; q=q->next; } p=q->next; q->next=p->next; delete p; return head; } };
二次刷题(update in 2015-07-30)
递归回溯法:
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* removeNthFromEnd(ListNode* head, int n) { ListNode* myHead = new ListNode(0); myHead->next = head; helper(myHead, n); head = myHead->next; delete myHead; return head; } int helper(ListNode* head, int n){ if(head==NULL){ return 0; } int k = 1 + helper(head->next, n); if(k == n + 1){ ListNode* p = head->next; head->next = p->next; delete p; } return k; } };
根本意义上说,递归回溯法仍然扫描了两次,正向一次,反向一次。且与计算机的栈的大小有关。双指针法才是这道题的正确解决办法。
为了避免是不是删除链表头,我们可以自行建一个表头,这是很多链表操作的技巧。
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* removeNthFromEnd(ListNode* head, int n) { if(head == NULL || n<=0){ return NULL; } ListNode* myHead = new ListNode(0); myHead->next = head; ListNode* p = myHead, *q = myHead; int count = 0; while(count < n && p!=NULL){ p = p->next; count++; } //不足n个 if(count<n){ delete myHead; return head; } while(p->next!=NULL){ p=p->next; q=q->next; } p = q->next; q->next = p->next; delete p; head = myHead->next; delete myHead; return head; } };
0 条评论