代码随想录算法训练营第3天 |Leetcode 203. 移除链表元素、707设计链表、206翻转链表

Leetcode 203. 移除链表元素

    ListNode* removeElements(ListNode* head, int val) {
        ListNode* cur=nullptr;
        ListNode* front=head;
        //cur=cur->next;
        //用while不用if是为了防止头部几个节点都重复的情况,删除节点直到遇到一个不是val的节点
        while(head)
        {
         front=head;
         if(head->val==val){
             head=head->next;
            delete front;
         }else{
             break;
         }
        
        }
        cout<<"head="<<head->val<<endl;
        cur=head;
        //从第一个不是不是val值得节点开始,遍历链表
        for(;cur!=nullptr;cur=cur->next){//这个地方出了问题
        cout<<cur->val<<endl;
        if(cur->val==val){
          cout<<"delete:"<<cur->val<<endl;
          front->next=cur->next;
          delete cur;
          cur=front->next;
        }
         front=cur;   
        }
        cout<<endl;
        return head;
    }

Line 32: Char 36: runtime error: member access within null pointer of type ‘ListNode’ (solution.cpp)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior prog_joined.cpp:37:36

原因应该是因为,cur=cur->next,如果next是空的时候会遇到这个问题

感悟:

机器的运行规律和我们人不一样,我看到这个数组可以直观的直到要删除哪个,但链表/指针,只能一个一个往后找,就像是在黑暗的单行道上行车,你只能往前走,所以就要设计一个

leetcode707

在构造函数的时候拖了很多时间

leetcode 206翻转链表

我一开始的思路:
class Solution {
public:
	//从头到尾打印整个链表
    void printlinks(ListNode* head)
    {
        ListNode* cur=head;
        for(;cur->next!=nullptr;cur=cur->next)
         {
             cout<<cur->val<<"->";
         }
         cout<<cur->val<<endl<<endl;
    }
    ListNode* reverseList(ListNode* head) {
        ListNode*  front=head;
        ListNode*  rear=head;
        ListNode*  cur=nullptr;
        ListNode*  temp=nullptr;
        if(head==nullptr||head->next==nullptr)
        return head;
        for(;rear->next!=nullptr;rear=rear->next)
         {
             //cout<<rear->val<<"->";
         }
         cout<<endl;
         cur=front->next;
         temp=front;
         temp->next=nullptr;
         while(cur!=rear)
         {
             //cout<<cur->val<<"->";
             temp=cur;
             cur=cur->next; 
             temp->next=front;
             front=temp;
             //cout<<cur->val<<"->";
         }
          cur->next=temp;
         return rear;
    }
};

思考:主要是在如何反转、步骤逻辑上(一共用了4个指针)//
对边界的处理(开头和结尾,这四个指针怎么安排)//
如果元素只有1个或者2 个怎么办

改进后代码:
    ListNode* reverseList(ListNode* head) {
        ListNode*  front=head;
        ListNode*  cur=nullptr;
        ListNode*  temp=nullptr;
        cur=front->next;
        front->next=nullptr;
        while(cur)
        {
            temp=cur;
            cur=cur->next;
            temp->next=front;
            front=temp;
        }
        //printlinks(temp);

    return temp;
    }
递归版本

思考:1.怎样通过递归,让next指向前一个节点呢??????

代码随想录版本:

感觉非常的简洁没有臃肿,思路上先进***(他用temp去保存cur->next,这一点很重要)***
值得学习的逻辑:
1.处理开头,通过pre=NULL,cur->next=pre;可以让head指向null,同时temp能保存第二个节点;
2.末尾处,cur=NULL推出循环,此时pre(pre总是落后于cur)指向最后一个节点

    ListNode* reverseList(ListNode* head) {
        ListNode* temp; // 保存cur的下一个节点
        ListNode* cur = head;
        ListNode* pre = NULL;
        /*
        开始cur指向head;
        1.temp指向cur->next用于"保存"下一个节点
        2.cur反转当前指向(通过pre"保存"前一个节点)
        3.更新pre和cur
        4.开启下一轮循环,直到cur指向了末节点的next既NULL;
        */
        while(cur) {
            temp = cur->next;  // 保存一下 cur的下一个节点,因为接下来要改变cur->next
            cur->next = pre; // 翻转操作
            // 更新pre 和 cur指针
            pre = cur;
            cur = temp;
        }
        return pre;
    }

感悟:

写的程序要简洁,逻辑决定步骤,每个步骤要通用性强;
还有就是,一定要按照机器(程序的逻辑)去思考,链表对于机器或者指针来讲是一条单行道

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值