203. 移除链表元素
题目链接: 203. 移除链表元素
【思路】
移除链表的元素,首先需要知道此节点的前一个节点pre,然后让pre->next = pre->next->next
,但是当需要移除的元素是头节点时,无法找到头节点的前一个节点,所以需要单独处理头结点。
所以可以设置一个虚拟头节点,让其指向头节点,这样操作起来就方便了许多。
注意: 如果用C++,不要忘记释放掉删除的节点。
【代码】
1. 无虚拟头节点
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
while (head != nullptr && head->val == val) { //注意不是if,因为有可能心得头节点也是要删除元素
ListNode* tmp = head;
head = head->next;
delete tmp;
}
ListNode* cur = head;
while (cur != nullptr && cur->next != nullptr) {
if (cur->next->val == val) {
ListNode* tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
} else {
cur = cur->next;
}
}
return head;
}
};
2.设置虚拟头节点
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode *p=new ListNode(0);
p->next=head;
ListNode* cur=p;
while(cur->next !=NULL) {
if(cur->next->val == val) {
ListNode* tmp = cur->next;
cur->next=cur->next->next;
delete tmp;
} else {
cur=cur->next;
}
}
head=p->next;
delete p; //不要忘记释放设置的虚拟头节点
return head;
}
};
707.设计链表
题目链接: 707.设计链表
【代码】
class MyLinkedList {
public:
struct LinkeNode {
int val;
LinkeNode* next;
LinkeNode(int val):val(val),next(nullptr){};
};
MyLinkedList() {
_dummyHead = new LinkeNode(0);
_size = 0;
}
int get(int index) {
if(index > _size -1 || index < 0) {
return -1;
}
LinkeNode* cur=_dummyHead->next;
while (index--) {
cur=cur->next;
}
return cur->val;
}
void addAtHead(int val) {
LinkeNode* tmp=new LinkeNode(val);
tmp->next=_dummyHead->next;
_dummyHead->next=tmp;
_size++;
}
void addAtTail(int val) {
LinkeNode* cur=_dummyHead;
while (cur->next != nullptr) {
cur=cur->next;
}
cur->next=new LinkeNode(val);
_size++;
}
void addAtIndex(int index, int val) {
if (index > _size) {
return;
}
if (index < 0) {
addAtHead(val);
}
LinkeNode* cur=_dummyHead;
while (index--) {
cur=cur->next;
}
LinkeNode* tmp=new LinkeNode(val);
tmp->next=cur->next;
cur->next=tmp;
_size++;
}
void deleteAtIndex(int index) {
if(index < 0 || index > _size-1) {
return;
}
LinkeNode* cur=_dummyHead;
while(index--) {
cur=cur->next;
}
LinkeNode* tmp=cur->next;
cur->next = tmp->next;
delete tmp;
_size--;
}
private:
LinkeNode* _dummyHead;
int _size;
};
206.反转链表
题目链接: 206.反转链表
【思路】
此题可以用双指针解法,一个pre和tmp,tmp首先指向cur->next
,然后pre指向cur的next,cur->next = pre
。
还可以用迭代法,原理跟双指针法是一样的的,理解了后更加巧妙。
【代码】
1.双指针
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* cur=head;
ListNode* pre=nullptr;
ListNode* tmp;
while(cur) {
tmp= cur->next;
cur->next=pre;
pre = cur;
cur = tmp;
}
return pre;
}
};
2. 迭代法
class Solution {
public:
ListNode* reverse(ListNode* pre, ListNode* cur) {
if(cur == nullptr) return pre;
ListNode* tmp=cur->next;
cur->next = pre;
return reverse(cur, tmp);
}
ListNode* reverseList(ListNode* head) {
return reverse(nullptr, head);
}
};
总结
- 链表一定要注意指针的操作,不要有野指针,注意循环条件;
- 删除节点时,要注意用临时变量保存一下节点,防止找不到这个节点,删除它;
- 注意及时释放不使用的指针。