LeetCode 203.移除链表元素
题目链接:LeetCode 203.移除链表元素
直接移除节点:
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
while(head != NULL && head -> val == val)
{
ListNode *tmp = head;
head = head->next;
delete tmp;
}
ListNode *cur = head;
while(cur != NULL && cur -> next != NULL)
{
if(cur -> next -> val == val)
{
ListNode *tmp = cur -> next;
cur -> next = cur -> next -> next;
delete tmp;
}
else
{
cur = cur -> next;
}
}
return head;
}
};
思路:移除节点的方法是通过遍历寻找到值为目标值的链表节点(cur -> val == val),然后将该节点的上一节点直接指向该节点的下一节点,最后删除该节点即可。在寻找时,我们是将某一节点的下一节点的值与目标值进行比较(cur -> next ->val == val),故需要确保能找到目标节点的上一节点(即某一节点)。如果是(head -> val == val),那么在进行操作时,我们就找不到头节点的上一节点,故需进行分类讨论。
情况1:head -> val == val,该情况下,我们仅需将头节点删除,并将头节点的下一节点作为头节点即可。
情况2:head -> next -> val == val(即非头节点的值为目标值的情况),此时,我们需要借助一个临时节点cur进行遍历,并找出(cur -> next -> val == val),之后按照上述操作即可。
小结:
1.在写Cpp时,需要将目标节点存入一个临时指针tmp中,完成操作后在将其删除。
2.遍历的循环条件为目标节点不为空指针,目标节点的上一节点仍不为空指针。
3.当头节点为目标节点时存在下一节点仍还是目标节点的情况,故需将判断条件放入循环中进行遍历。
4.因在操作结束后需返回头节点,而头节点的值不能改变,故引入临时指针cur进行遍历。
设置虚拟头节点来移除节点:
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode *dummyhead = new ListNode(0);
dummyhead -> next = head;
ListNode *cur = dummyhead;
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 = dummyhead -> next;
delete dummyhead;
return head;
}
};
思路:解体思路与直接移除节点一致,但因设置了虚拟头节点,使得一定能找到目标节点的上一节点,因此也就不需要进行分类讨论。
小结:
1.在设置了虚拟头节点后,需将虚拟头节点的下一节点指向原链表的头节点。
2.在进行遍历时因为寻找的是cur->next,故需将临时指针指向虚拟头节点(cur = dummyhead)。
3.在返回值时,因原链表中的头节点可能被删除,故需将头节点指向虚拟头节点的下一节点,并返回head,删除虚拟头节点。
LeetCode 707.设计链表
题目链接:LeetCode 707.设计链表
class MyLinkedList {
public:
struct LinkedNode {
int val;
LinkedNode *next;
LinkedNode(int x):val(x),next(NULL){}
};
MyLinkedList() {
dummyhead = new LinkedNode(0);
size = 0;
}
int get(int index) {
if(index > size - 1 || index < 0)
{
return -1;
}
else
{
LinkedNode *cur = dummyhead -> next;
while(index--)
{
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 != NULL)
{
cur = cur -> next;
}
cur -> next = newNode;
size++;
}
void addAtIndex(int index, int val) {
if(index > size)
{
return;
}
else 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) {
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--;
}
private:
int size;
LinkedNode *dummyhead;
};
思路:
1.整体延续了虚拟头节点的用法。
2.get(index):先判断索引是否有效,之后通过遍历寻找到index对应的节点。
3.addAtHead(val):创立一个新节点,先将新节点的指向头节点(虚拟头节点的下一节点),再将虚拟头节点的指向头节点即可。
4.addAtTail(val):利用最后一个节点的下一节点为空指针寻找到最后一个节点,再将最后一个节点的指向新节点。
5.addAtIndex(index,val):先判断索引值是否符合规定(若小于0则视为加在头节点前),之后通过遍历找到目标节点,后将新节点指向目标节点(cur -> next),再将目标节点的上一节点(cur)指向目标节点即可。
6.deleteAtIndex(index):判断索引是否附和规定,其余同上一题的解法。
小结:
1.需注意因为n从0开始,即第0节点为头节点。
2.在添加节点时,由于题目要求是在目标节点之前添加新节点,故经遍历得到的cur为目标节点的上一节点。
3.在添加新节点时需注意代码执行顺序;在 addAtIndex(index,val) 中,若先将目标节点的上一节点(cur)指向新增节点,则无法寻找到目标节点(cur -> next)。
LeetCode 206.反转链表
题目链接:LeetCode 206.反转链表
双指针法:
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode *pre = NULL;
ListNode *cur = head;
while(cur != 0)
{
ListNode *tmp = cur -> next;
cur -> next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
};
思路:利用双指针进行遍历从而改变链表指向,指针初始值为pre == NULL ,cur == head。
小结:
1.循环结束条件是cur为空指针。
2.需引入临时指针来存储目标节点的下一节点。
3.指针移动顺序应是先移动第一个指针(pre),再移动第二个指针(cur);否则就无法使pre移动到下一节点。
递归法:
class Solution {
public:
ListNode* reverse(ListNode* cur,ListNode* pre)
{
if(cur == NULL)
return pre;
ListNode *tmp = cur -> next;
cur -> next = pre;
return reverse(tmp,cur);
}
ListNode* reverseList(ListNode* head) {
return reverse(head,NULL);
}
};
思路:还是利用了双指针,但是通过递归函数简化了代码。