给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
进阶:
你能尝试使用一趟扫描实现吗?
第一个想到的是回溯法,回溯到链表尾部,然后往回回溯n个。
链表题都可以使用dummyhead,用于处理要删除的是链表头等特殊情况。
但是这样可能不算是一趟扫描。
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode(int x) : val(x), next(NULL) {} 7 * }; 8 */ 9 class Solution { 10 public: 11 ListNode* removeNthFromEnd(ListNode* head, int n) { 12 int ret=backtrace(head,n); 13 if(!ret) 14 return head->next; 15 return head; 16 } 17 18 int backtrace(ListNode* cur, int n){ 19 int ret=-2; 20 if(cur->next!=NULL) 21 ret=backtrace(cur->next,n); 22 //cout<<ret<<endl; 23 if(ret==-1) 24 return -1; 25 else if(ret==0){ 26 //cout<<"abc"; 27 cur->next=cur->next->next; 28 return -1; 29 } 30 if(cur->next==NULL) 31 return n-1; 32 return ret-1; 33 } 34 };
真正实现一遍扫描,是使用双指针。第二个指针保持和第一个指针n的距离一起移动,直到第一个指针到达尾部。
public ListNode removeNthFromEnd(ListNode head, int n) { ListNode dummy = new ListNode(0); dummy.next = head; ListNode first = dummy; ListNode second = dummy; // Advances first pointer so that the gap between first and second is n nodes apart for (int i = 1; i <= n + 1; i++) { first = first.next; } // Move first to the end, maintaining the gap while (first != null) { first = first.next; second = second.next; } second.next = second.next.next; return dummy.next; } 作者:LeetCode 链接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/solution/shan-chu-lian-biao-de-dao-shu-di-nge-jie-dian-by-l/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。