我的
想法:
- 找到倒数第n-1个节点,通过遍历
问题:
* 需要准确计算需要循环多少次才能找到第n-1个节点。
* 假如有5个节点,要删除倒数第2个节点,有个虚拟头结点的情况下,用count=0计数需要遍历第一次,到第一个节点,count=1,遍历第二次,到第二个节点,count=2,当count==n-1时,不再遍历,此时curr指针指的就是第n-1个节点
正确
思路:
利用双指针距离差一起走,距离差正好是倒数第n个节点前一个位置和链表最后一个节点
适用场景:
双指针:两个指针的距离差;两个指针间的元素关系
代码
//题目:
#include <iostream>
using namespace std;
#include <vector>
//解决方法
class Solution
{
public:
//方法
// 链表节点
struct ListNode {
int val;
ListNode* next;
ListNode() : val(0), next(nullptr) {}
ListNode(int val) : val(val), next(nullptr){}
};
//返回链表,移除倒数第n个元素
ListNode* removeNthFromEnd(ListNode* Head, int n) {
//初始化虚拟头结点
ListNode* dummyHead = new ListNode(0);
dummyHead = Head->next;
//双指针初始化
ListNode* slow = dummyHead;
ListNode* fast = dummyHead;
//先把fast指针往前移动n+1个位置
while (n-- && fast != nullptr) { //防止n大于链表长度
fast = fast->next;
}
fast = fast->next;
//移动两个指针
while (fast) {
slow = slow->next;
fast = fast->next;
}
//删除节点,此时slow是待删除节点的前一节点
slow->next = slow->next->next;
return dummyHead->next;
}
};
class LinkedList
{
public:
//初始化链表
LinkedList() {
_dummyHead = new Solution::ListNode(0);
_size = 0;
}
//头插法
void addAtHead(int val) {
Solution::ListNode* newNode = new Solution::ListNode(val);
newNode->next = _dummyHead->next;
_dummyHead->next = newNode;
_size++;
}
void printList() {
Solution::ListNode* curr = _dummyHead->next;
while(curr) {
cout << curr->val << " ";
curr = curr->next;
}
cout << endl;
}
private:
int _size;
Solution::ListNode* _dummyHead;
};
//主函数
int main()
{
/*int a[] = {0};
int target = 0;
vector<int> nums(a, a + sizeof(a) / sizeof(a[0]));
Solution solution;
cout << "方法调用" << endl;*/
LinkedList linklist;
linklist.addAtHead(2);
linklist.printList();
return 0;
}
学习到
代码编写过程中
- removeNthFromEnd:移除倒数第N个
- n-- && fast != nullptr:代码直观简单易懂,isNull,
- fast != nullptr:要考虑到每种情况都出现的后果