看下问题描述
即要求删除倒数第n个节点。其中给定的n是合法的,因此我们不需要考虑是否会有所给n超出链表的问题。
遇到这个问题首先想到的自然是先遍历链表一次确定其长度,然后再来第二遍完成删除。然而题目要求尝试一趟完成,这就要求当第一次遍历到目标位置时,就该删除。
因此我想到一个方法:用两个指针,pos1, pos2,它们相距n-1个节点,对链表遍历,当pos2到底后,pos1就是倒数第n个节点比如1->2->3->4->5
pos1指向的就是要删除节点的上一个节点,这样有利于删除的进行。具体做法首先让pos1和pos2都指向头,然后先对pos2进行向后遍历,当它们距离n-1时,pos1也开始遍历
此时pos2指向最后一个节点,pos1有两种可能:
1. dis < n,表示要删除的是第一个,此时返回的head要更改(遇到NULL要单独返回)
2. dis == n,正常删除中间节点
源代码如下:
/* 2017-10-15 by 王世祺 */
/* From https://leetcode.com/problems/remove-nth-node-from-end-of-list/description/ */
/**问题描述
* 给一个链表,删除第n个节点
*/
/* 想法:用两个指针,pos1, pos2,它们相距n-1个节点,对链表遍历,当pos2到底后,pos1就是倒数第n个节点*/
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* pos1 = head;
ListNode* pos2 = head;
int dis = 0; // 记录pos1和pos2之间的距离,因为要删除,所以要求相距n-1
/* 如何删除:找到应当删除的节点的上一个指针,将其next指针移给下下一个节点并删除目标节点(下一个节点) */
while (pos2->next != NULL) {
if(dis == n) {
pos1 = pos1->next;
} else {
dis++;
}
pos2 = pos2->next;
}
/* 此时pos2指向最后一个节点,pos1有两种可能:
1. dis < n,表示要删除的是第一个,此时返回的head要更改
2. dis == n,此时放心删
*/
if (dis < n) {
ListNode* temp = head;
head = head->next;
delete temp;
if (head != NULL)
return head;
else
return NULL;
} else {
ListNode* temp = pos1->next;
pos1->next = temp->next;
delete temp;
return head;
}
}
只遍历了一次,因此时间复杂度是O(n)