为了避免分头节点和非头节点的分类讨论,设置一个头节点可以使所有节点按照统一的方式移除。设立current指针是为了避免直接修改原来节点的值。
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头节点
dummyHead->next = head;
ListNode* current = dummyHead; // 头节点指针不变,因为最后要返回头节点值
while (current->next != NULL) {
if (current->next->val == val) {
ListNode* tmp = current->next;
current->next = current->next->next;
delete tmp;
}
else{
current = current->next;
}
}
return dummyHead->next;
}
};
这道题要求实现五个接口:
1. 获取链表第index个节点的数值
2. 在链表的最前面插入一个节点
3. 在链表的最后面插入一个节点
4. 在链表第index个节点前面插入一个节点
5. 删除链表的第index个节点
首先是定义链表结构体,C++11有一个新特性是nullptr来区分空指针和0,避免void*隐式转换到其他类型造成C++重载混乱(例如定义一个一个函数数据类型为char,char赋值为NULL,NULL被定义为0,此时会去调用该函数的int型,造成混乱)
获取第index节点的数值注意一下循环是从头节点而非自己创建的虚拟头节点为起始。添加头节点注意先把要插入的新节点指向原来的头节点,防止丢失头节点的位置。在尾部插入节点注意current->next为空时循环停止。在删除第index节点时,我们要知道第n个节点前一个节点的值,所以current指针初始位置设在虚拟头结点处。
class MyLinkedList {
public:
// 定义链表节点结构体
struct LinkedNode {
int val; // 节点上存储的元素
LinkedNode* next;
LinkedNode(int val):val(val),next(nullptr){}
};
// 初始化链表
MyLinkedList() {
_dummyHead = new LinkedNode(0);
_size = 0;
}
int get(int index) {
if (index > (_size -1) || index < 0) {
return -1;
}
LinkedNode* cur = _dummyHead->next;
while (index--) { // index=0循环成立
cur = cur->next;
}
return cur->val;
}
void addAtHead(int val) {
LinkedNode* newNode = new LinkedNode(val);
newNode->next = _dummyHead->next;
_dummyHead->next = newNode;
_size++;
}
void addAtTail(int val) {
LinkedNode* newNode = new LinkedNode(val);
LinkedNode* cur = _dummyHead;
while (cur-> next != nullptr) {
cur = cur->next;
}
cur->next = newNode;
_size++;
}
void addAtIndex(int index, int val) {
if (index > _size) return;
if (index < 0) index = 0;
LinkedNode* newNode = new LinkedNode(val);
LinkedNode* cur = _dummyHead;
while (index--) {
cur = cur->next;
}
newNode->next = cur->next;
cur->next = newNode;
_size++;
}
void deleteAtIndex(int index) { // index从0开始
if (index >= _size || index < 0) {
return;
}
LinkedNode* cur = _dummyHead;
while (index--) {
cur = cur->next;
}
LinkedNode* tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
_size--;
}
void printLinkedList() {
LinkedNode* cur = _dummyHead;
while (cur->next != nullptr) {
cout << cur->next->val << "";
cur = cur->next;
}
cout << endl;
}
private:
int _size;
LinkedNode* _dummyHead;
};
初始化时,current指向头节点,为了达到完全反转的目的,原本尾节点指向null此时设立一个新的指针pre指向null,此时知道了翻转后,原来的头节点变为尾节点要指向null,为了防止丢失头节点下一个节点的位置装了一个tmp指针,用来存储cur->next,最后pre和cur指针每次循环右移,返回最终的头节点也就是pre
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* tmp; // 保存下一个节点
ListNode* cur = head;
ListNode* pre = NULL;
while (cur != NULL) {
tmp = cur->next;
cur->next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
};