给出链表 3->2->1->5->null和n = 2,返回倒数第二个节点的值1.
第一种方法:单链表只有头指针,所以只能从头部开始寻找,先遍历一遍链表,确定链表中节点的个数k。然后从前往后第k-n+1个节点就是倒数第n个节点。一共遍历2次链表
/**
* Definition of ListNode
* class ListNode {
* public:
* int val;
* ListNode *next;
* ListNode(int val) {
* this->val = val;
* this->next = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param head: The first node of linked list.
* @param n: An integer.
* @return: Nth to last node of a singly linked list.
*/
ListNode *nthToLast(ListNode *head, int n) {
// write your code here
ListNode* p;
if ( head == NULL || n == 0 ) {
return NULL;
}
p = head;
int count = 0;
while (p -> next != NULL) {
p = p -> next;
count++;
}
p = head;
for ( int i = 0; i < count-n+1; i++) {
p = p ->next;
}
return p;
}
};
第二种方法:只遍历一次链表。设置2个指针,当第一个指针从表头向前走到第n-1个节点时,第二个指针开始从表头出发。当第一个指针走到尾节点时,第二个指针的位置即为倒数第n个节点
class Solution {
public:
/**
* @param head: The first node of linked list.
* @param n: An integer.
* @return: Nth to last node of a singly linked list.
*/
ListNode *nthToLast(ListNode *head, int n) {
// write your code here
ListNode *p1 , *p2;
// 边界条件,如果链表为空,或者输入的数字非正,返回空
if ( head == NULL || n <= 0 ) {
return NULL;
}
p1 = head;
for ( int i = 0; i < n-1 ; i++ ) {
// 第一个指针开始遍历,保证输入的n值小于链表的长度,否则返回空
if ( p1 -> next != NULL ) {
p1 = p1 -> next;
} else {
return NULL;
}
}
p2 = head; // 第二个指针开始遍历
while ( p1 ->next != NULL ) {
p1 = p1 ->next;
p2 = p2 ->next;
}
return p2;
}
};
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。(medium)
同样适用快慢指针的方法,但是要注意可能删除的是第一个节点。
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
if(head == NULL || n<=0) return NULL;
ListNode *p1 = head;
ListNode *p2 = head;
for(int i=0; i<n; ++i){
p2 = p2->next;
}
if(p2 == NULL) return head->next; //删除的是第一个节点
while(p2->next != NULL){
p1 = p1->next;
p2 = p2->next;
}
p1->next = p1->next->next;
return head;
}
};