最容易想到的是遍历两回链表,第一次获知长度,第二次删除倒数第N个结点。
但题目中进阶要求说到,可以尝试线性级时间复杂度的算法,我最先想到的是,遍历一回链表,将每个元素都存在可以随机访问的数据结构中。本想用动态数组实现一下,但malloc和realloc函数操作起来较繁琐,为简单起见,采用map来实现。
得CPP代码如下:
/**
* 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 fakeHead(0),*p;
fakeHead.next=head;
p=&fakeHead;
map<int,ListNode*> record;
int i=0;
if(head==NULL || n<=0) return NULL;
while(p!=NULL)
{
record[i]=p;
p=p->next;
i++;
}
if(i<n+1)
return NULL;
record[i-1-n]->next=record[i-1-n]->next->next;
return fakeHead.next;
}
};
但这样总归还是用了额外的空间,在看了官方解答后,更改如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
struct ListNode fakeHead;
struct ListNode *p1,*p2;
int i;
fakeHead.val=0;
fakeHead.next=head;
p1=&fakeHead;
p2=&fakeHead;
if(head==NULL || n<=0) return NULL;
for(i=0;i<n;i++)
{
if(p2==NULL) return NULL;
p2=p2->next;
}
while(p2->next!=NULL){p2=p2->next;p1=p1->next;}
p1->next=p1->next->next;
return fakeHead.next;
}
注意:虽然题目中有“Given n will always be valid.”的字眼,但还是要考虑链表为空的情况……多考虑一些,全面一点,总没错。