代码随想录算法训练营第三天|LeetCode 203.移除链表元素 、LeetCode 707.设计链表、LeetCode 206.反转链表 。

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);
    }
};

思路:还是利用了双指针,但是通过递归函数简化了代码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值