链表理论基础
- 与数组的区别主要是存在形式:连续空间不连续空间;查找效率;随机访问;删除插入效率;长度是否固定;几个方面
- 链表存在形式:单链表,双链表(双向链表),循环链表
- 链表特别注意在删除时,先保存下一个结点的地址,再删除当前结点,最后将保存的地址赋值回来
203. 移除链表元素
题目链接:203. 移除链表元素
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode * nhead = new ListNode(0, head);
ListNode * curNode = nhead;
while(curNode->next != nullptr){
if(curNode->next->val == val){
ListNode * temp = curNode->next->next; //保存下一个节点地址
delete curNode->next; //删除待删除的节点
curNode->next = temp; //指向下一个结点
}else{
curNode = curNode->next;
}
}
ListNode * temp = nhead;
nhead = nhead->next;
delete temp;
return nhead;
}
};
707. 设计链表
题目链接:707. 设计链表
注意事项:
- 在使用whlie遍历链表进行下一步操作时,注意弄清楚需要到达的是哪个结点,是待操作的结点当前结点还是待操作的上一个结点
- 对于边界问题要仔细考虑
- 使用虚拟头结点可以降低在头部插入删除的代码量,但是需要注意对虚拟结点的释放,还需要注意在设置cur结点去遍历时,最开始的cur指针指向的是哪个结点,是head指针还是head->next指针,如果设置不争取会找不到正确的指针地址
class MyLinkedList {
public:
struct LinkedNode{
int val;
LinkedNode * next;
LinkedNode(int val):val(val),next(nullptr){}
};
LinkedNode * head;
int num;
MyLinkedList() {
head = new LinkedNode(0);
num = 0;
}
int get(int index) {
if(index >= num || index < 0){
return -1;
}
LinkedNode * cur = head->next;
while(index--){
cur = cur->next;
}
return cur->val;
}
void addAtHead(int val) {
LinkedNode * temp = new LinkedNode(val);
temp->next = head->next;
head->next = temp;
num++;
}
void addAtTail(int val) {
LinkedNode * temp = new LinkedNode(val);
LinkedNode * cur = head;
while(cur->next != nullptr){
cur = cur->next;
}
cur->next = temp;
num++;
}
void addAtIndex(int index, int val) {
if(index < 0){
addAtHead(val);
}else if(index > num){ //此处要注意,index是可以在num处插入的,可以等于num
return;
}else{
LinkedNode * cur = head;
LinkedNode * temp = new LinkedNode(val);
while(index--){
cur = cur->next;
}
temp->next = cur->next;
cur->next = temp;
}
num++;
}
void deleteAtIndex(int index) {
if(index < 0 || index >= num){
return;
}
LinkedNode * cur = head;
while(index--){
cur = cur->next;
}
LinkedNode * temp = cur->next;
cur->next = cur->next->next;
delete temp;
num--;
}
};
/**
* Your MyLinkedList object will be instantiated and called as such:
* MyLinkedList* obj = new MyLinkedList();
* int param_1 = obj->get(index);
* obj->addAtHead(val);
* obj->addAtTail(val);
* obj->addAtIndex(index,val);
* obj->deleteAtIndex(index);
*/
206.反转链表
题目链接: 206.反转链表
注意事项
- 逻辑可能会很绕,但是用笔模拟一下就很容易理解
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode * newhead = new ListNode();
ListNode * cur = head;
while(cur != nullptr){
ListNode * temp = newhead->next;
newhead->next = cur;
ListNode * temp2 = cur->next;
cur->next = temp;
cur = temp2;
}
return newhead->next;
}
};