2019.1.30
题目描述:
Given a linked list, remove the n-th node from the end of list and return its head.
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.
Follow up:
Could you do this in one pass?
这题是求一个链表的倒数第N个结点,并将其删除。
解法一:
我们使用两个指针,一个fast一个slow,先放fast后移N个结点,slow处在原点,之后让fast和slow同时移动,那么等到fast移动到null的时候,slow所在位置即倒数第N个结点的位置,此时进行删除操作即可。链表的删除操作就不多言了。
C++代码:
/**
* 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* fast=head;
while(n--)
fast=fast->next;
if(!fast)
return head->next;
ListNode* slow=head;
while(fast->next){
fast=fast->next;
slow=slow->next;
}
slow->next=slow->next->next;
return head;
}
};
时间复杂度:O(n)
解法二:官方解法
遍历两次,第一次遍历求出链表的长度length,那么倒数第N个结点就是length-N+1,所以第二次遍历只要扫描到length-N+1位置删除即可。
首先我们将添加一个哑结点作为辅助,该结点位于列表头部。哑结点用来简化某些极端情况,例如列表中只含有一个结点,或需要删除列表的头部。在第一次遍历中,我们找出列表的长度 L。然后设置一个指向哑结点的指针,并移动它遍历列表,直至它到达第 (L - n)个结点那里。我们把第 (L - n)个结点的 next
指针重新链接至第 (L - n + 2)个结点,完成这个算法。
Java代码:
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0);
dummy.next = head;
int length = 0;
ListNode first = head;
while (first != null) {
length++;
first = first.next;
}
length -= n;
first = dummy;
while (length > 0) {
length--;
first = first.next;
}
first.next = first.next.next;
return dummy.next;
}
时间复杂度O(n)