代码随想录算法训练营Day3

本文介绍了如何使用C++处理链表问题,包括通过虚拟头结点法移除链表元素,理解构造函数的作用,以及用双指针法反转链表。在解决链表问题时,作者强调了画图辅助理解的重要性,并分享了编程过程中遇到的错误及调试经验。
摘要由CSDN通过智能技术生成

203.移除链表元素

链表这块我不是很熟悉,大一下学C大程的时候摆烂了一学期……摆过的烂最后还是要还QAQ。但是链表这块在仔细研究了卡哥的题解以及知识点讲解后我发现画图可以很好得理清思路,写起来思路非常清晰不会出现问题。下面是我通过画图解析的虚拟头结点法(能统一处理肯定还是统一处理更好嘛)

这里提一嘴我也是第一次接触的概念——构造函数
这里就拿卡哥给的这个例子吧,我个人的理解是构造函数让我们可以有多种初始化的方式,而且表达形式简洁不需要单独拎出来初始化(不知道理解得对不对哈)

struct ListNode {
    int val;  // 节点上存储的元素
    ListNode *next;  // 指向下一个节点的指针
    ListNode(int x) : val(x), next(NULL) {}  // 节点的构造函数
};

我们先画出加入虚拟头结点的状态
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-66eJ8brx-1690572698405)(664354fb6fa633a9aca0c1a30f0404a.png)]

然后我们根据条件,如果要判断链表中数值部分是否等于val,那么就要让当前结点的next指针所指向的结点的val部分和val进行比较,翻译过来就是
temp->next->val==val这个判定条件了。

那么如何进行删除操作呢?在链表中无非就是让next指针绕过下一个结点,直接指向下下个结点,翻译一下就是temp->next=temp->next->next
在这里插入图片描述

最后需要考虑的是什么时候我们发现所有链表已经遍历结束了呢?假如当前处于temp,那么我们根据之前的判定每次做判定都是temp->next->val,也就是说如果temp目前是最后一个结点,那么说明不需要继续查找了,最后一个结点最大的特征便是next指针指向了NULL,那么判定条件也就是temp->next!=NULL
在这里插入图片描述

下面是我的代码,初始版本并没有考虑到释放内存这件事,后来学习了题解之后意识到了,所以添加进去了,tem这个变量就是用来存储即将释放的地址的,因此并没有加入实际运算及操作

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        ListNode* dummynode=new ListNode(0);
         dummynode->next=head;
        ListNode* temp=dummynode;
       
        while (temp->next!= NULL)
        {
            if (temp->next->val==val)
            {
                ListNode* tem=temp->next;
                temp->next=temp->next->next;
                delete tem;
            }
            else{
              temp=temp->next;
            }
        }
        return dummynode->next;
        delete dummynode;
    }
};

707.设计链表

debug到心态快崩了……主要是每个函数之间都会相互影响,可能在这个地方的报错,往往是你其他地方出现的谬误所导致。基本思路方面我还是作图进行直观理解,效果很不错
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

我自己本身程序的问题其实出在两个地方,一个是在addAtIndex中多写了一个next,这个是思路上出现的错误,这种错误可以通过图表理解和检验排查。还有一个致命的问题就是我在判定了特殊情况后未能及时return结束函数进程,反而是继续了后续的判定。而正是因为这么小的两个错误,让我debug了估计有一个半小时。。。导致我在凌晨两三点中身心俱疲,最后猛然醒悟还是靠的题解一段一段替换我的代码来找出问题所在,leetcode上面无法追踪数据让debug难度直线上升QAQ

最后上代码(实在太累了,内存释放什么的没有补充,以后再完善)

class MyLinkedList {
public:
   struct LinkedNode {
        int val;
        LinkedNode* next;
        LinkedNode(int val):val(val), next(nullptr){}
    };

    MyLinkedList() {
        _dummy=new LinkedNode(0);
       _size=0;
    }

    int get(int index) {
        int i;
        LinkedNode* temp=new  LinkedNode(0);
        temp=_dummy;
        if (index>=_size || index<0) return -1;
         for (i=1;i<=index+1;i++)
         {
             temp=temp->next;
         }
         return temp->val;
         delete temp;
    }
     void addAtHead(int val) {
         LinkedNode* temp=new LinkedNode(val);
         temp->next=_dummy->next;
         _dummy->next=temp;
         _size++;
    }
    
    void addAtTail(int val) {
         LinkedNode* temp=new  LinkedNode(0);
           LinkedNode* tail=new  LinkedNode(val);
         temp=_dummy;
         while (temp->next!=nullptr)
         {
             temp=temp->next;
         }
         temp->next=tail;
         _size++;
    }
    
      void addAtIndex(int index, int val) {
       int i;
       LinkedNode* temp=new  LinkedNode(0);
       LinkedNode* add=new  LinkedNode(val);
       if (index==_size)
       {
           addAtTail(val);
           return;
        }
        if (index>_size || index<0) return;
        temp=_dummy;
       for (i=1;i<=index;i++)
       {
           temp=temp->next;
       }
        add->next=temp->next;
        temp->next=add;
        _size++;
    }
    
 void deleteAtIndex(int index) {
          int i;
    LinkedNode* temp=new  LinkedNode(0);
    if (index>=_size || index<0)
    { 
        return;
    }
         temp=_dummy;
          for (i=1;i<=index;i++)
          {
              temp=temp->next;
          }
          temp->next=temp->next->next;
          _size--;
    }
    private:
       int _size;
    LinkedNode* _dummy;
};

206. 反转链表

经过第二题的折磨,这题可以说是宝宝巴士了。经典双指针法,一个读取,一个存储,直接把链表的箭头转向即可,注意初始化即可
大概图解如下
在这里插入图片描述

下面是代码

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
         ListNode* left=new ListNode(0);
         ListNode* right=new ListNode(0);
         ListNode* temp=new ListNode(0);
         left=NULL;
         right=head;
         while (right!=NULL)
         {
            temp=right->next;
            right->next=left;
            left=right;
            right=temp;
         }
         return left;
    }
};
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14天的训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15天的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16天的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值