代码随想录 | Day05 | 链表:移除链表元素&&设计链表&&反转链表

代码随想录 | Day05 | 链表:移除链表元素&&设计链表&&反转链表

主要学习内容:

1.链表删除操作

2.设计自己的链表

3.双指针操作链表

203.移除链表元素

203. 移除链表元素 - 力扣(LeetCode)

解法1:设置虚拟头结点

设置一个虚拟头结点用虚拟头结点的next进行判断

好处是不需要写关于头结点的处理逻辑,比较容易处理

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        ListNode * t=new ListNode;
        ListNode * q=new ListNode;
        t->next=head;
        q=t;
        while(t->next!=NULL)
        {
            if(t->next->val==val)
            {
                ListNode *tmp=t->next;
                t->next=t->next->next;
                delete tmp;
            }
            else
                t=t->next;
        }
        return q->next;
    }
};
关键点:

1.设置一个额外的指针q指向虚拟头结点,head节点可能会被删除,最后无法返回结果

2.手动释放内存 delete

解法2:直接删除

思路:先处理头节点再处理其余节点

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

关键点:

1.头结点是val头结点连着的下面几个可能也是val,所以要用while而不是if来处理头结点

2.没有了虚拟头结点,我们就不知道第一个到底是不是为空,则需要在两个while()处加入head不为空的判断条件

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

    MyLinkedList() {
        prenode=new ListNode;
        _size=0;
    }
    
    int get(int index) {

        if(index>(_size-1)||index<0)
            return -1;

        int n=index+1;
        ListNode *p=new ListNode;
        p=prenode;
        while(n--&&p->next!=NULL)
            p=p->next;
        return p->val;
        
    }
    
    void addAtHead(int val) {
        ListNode* p=new ListNode;
        p->next=prenode->next;
        prenode->next=p;
        if(p->next!=nullptr)
            p->next->pre=p;
        p->val=val;
        p->pre=prenode;
        _size++;
    }
    
    void addAtTail(int val) {
        ListNode* p=new ListNode;
        p->next=NULL;
        p->val=val;
        ListNode* q=new ListNode;
        q=prenode;
        while(q->next!=NULL)
            q=q->next;
        q->next=p;
        p->pre=q;
        _size++;
    }   
    
    void addAtIndex(int index, int val) {
        if(index<0)
        {
            addAtHead(val);
        }
           
        if(index>_size)
            return ;
        else if(index==_size)
        {
            addAtTail(val);
        }
        else
        {
            int n=index;
            ListNode *p=new ListNode;
            p=prenode;
            ListNode *q=new ListNode;
            while(n--&&p->next!=NULL)
                p=p->next;
            q->next=p->next;
            p->next=q;
            q->val=val;
            _size++;
        }
    }
    
    void deleteAtIndex(int index) {
        if(_size==0)
            return;
        if(index>=_size||index<0)
            return ;
        int n=index;
        ListNode *p=new ListNode;
        p=prenode;
        while(n--&&p->next!=NULL)
            p=p->next;
        if(p->next==nullptr)
            return;
        ListNode *q=p->next;
        p->next=q->next;
        if (q->next != NULL)
        {
            q->next->pre = p;//更新前后节点的连接
        }
        _size--;
    }
private:
    ListNode *prenode;
    int _size;
};

707.设计链表

707. 设计链表 - 力扣(LeetCode)

解法一:单链表

注意的点:

addAtIndex函数的if条件里面是要index>size而不是index>=size,因为=的时候是要插入到末尾

(改了2小时才发现,无语住了╭(╯^╰)╮)

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

    MyLinkedList()
    {
        size = 0;
        prenode = new ListNode;
    }

    int get(int index)
    {
        if (index < 0 || index >= size)
            return -1;
        ListNode* t = new ListNode;
        t = prenode;
        int n = index + 1;
        while (n--)
        {
            t = t->next;
        }
        return t->val;
    }

    void addAtHead(int val)
    {
        ListNode* t = new ListNode;
        t->val = val;
        t->next = prenode->next;
        prenode->next = t;
        size++;
    }

    void addAtTail(int val)
    {
        ListNode* t = prenode;
        int n = size;
        while (n--&& t->next != NULL)
            t = t->next;

        ListNode* tmp = new ListNode;
        tmp->val = val;
        tmp->next = NULL;
        t->next = tmp;
        size++;
    }

    void addAtIndex(int index, int val)
    {
        if (index < 0 || index > size)
            return;
        ListNode* t = prenode;
        if (index == 0)
            addAtHead(val);
        else
        {
            while (index--)
                t = t->next;
            ListNode* q = new ListNode;
            q->val = val;
            q->next = t->next;
            t->next = q;
            size++;
        }
    }

    void deleteAtIndex(int index)
    {
        if (size == 0)
            return;
        if (index < 0 || index >= size)
            return;
        if (index == 0)
        {
            ListNode* t = new ListNode;
            t = prenode->next;
            prenode->next = prenode->next->next;
            size--;
            delete t;
        }
        else
        {
            ListNode* t = prenode;
            while (index-- && t->next)
                t = t->next;
            ListNode* p = new ListNode;
            p = t->next;
            t->next = t->next->next;
            delete p;
            size--;
        }
    }

private:
    ListNode* prenode;
    int size;
    
};
解法二:双链表
class MyLinkedList {
public:
    struct ListNode
     {
     int val;
     ListNode *next;
     ListNode *pre;
     ListNode() : val(0), next(nullptr),pre(nullptr) {}
 };

    MyLinkedList() {
        prenode=new ListNode;
        _size=0;
    }
    
    int get(int index) {

        if(index>(_size-1)||index<0)
            return -1;

        int n=index+1;
        ListNode *p=new ListNode;
        p=prenode;
        while(n--&&p->next!=NULL)
            p=p->next;
        return p->val;
        
    }
    
    void addAtHead(int val) {
        ListNode* p=new ListNode;
        p->next=prenode->next;
        prenode->next=p;
        if(p->next!=nullptr)
            p->next->pre=p;
        p->val=val;
        p->pre=prenode;
        _size++;
    }
    
    void addAtTail(int val) {
        ListNode* p=new ListNode;
        p->next=NULL;
        p->val=val;
        ListNode* q=new ListNode;
        q=prenode;
        while(q->next!=NULL)
            q=q->next;
        q->next=p;
        p->pre=q;
        _size++;
    }   
    
    void addAtIndex(int index, int val) {
        if(index<0)
        {
            addAtHead(val);
        }
           
        if(index>_size)
            return ;
        else if(index==_size)
        {
            addAtTail(val);
        }
        else
        {
            int n=index;
            ListNode *p=new ListNode;
            p=prenode;
            ListNode *q=new ListNode;
            while(n--&&p->next!=NULL)
                p=p->next;
            q->next=p->next;
            p->next=q;
            q->val=val;
            _size++;
        }
    }
    
    void deleteAtIndex(int index) {
        if(_size==0)
            return;
        if(index>=_size||index<0)
            return ;
        int n=index;
        ListNode *p=new ListNode;
        p=prenode;
        while(n--&&p->next!=NULL)
            p=p->next;
        if(p->next==nullptr)
            return;
        ListNode *q=p->next;
        p->next=q->next;
        if (q->next != NULL)
        {
            q->next->pre = p;//更新前后节点的连接
        }
        _size--;
    }
private:
    ListNode *prenode;
    int _size;
};
关键点:

1.记得释放空间

2.很需要虚拟头指针和size,可以对很多操作进行简化

206.反转链表

206. 反转链表 - 力扣(LeetCode)

解法1:双指针

快慢指针分别指向需要改变指向的两个结点,然后进行翻转即可

206.翻转链表

//自己写的
class Solution {
public:
    ListNode* reverseList(ListNode* head) 
    {
        if(head==NULL)
            return head;
        ListNode * pre=NULL;//慢指针
        ListNode * cur=head;//快指针
        ListNode * tmp=head->next;//保存节点所用
        while(cur)
        {
            cur->next=pre;//翻转操作
            //快慢指针更新
            pre=cur;
            cur=tmp;
            if(tmp)
                tmp=tmp->next;//更新保存点
        }
        return pre;
    }
};
//代码随想录的
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* temp; // 保存cur的下一个节点
        ListNode* cur = head;
        ListNode* pre = NULL;
        while(cur) {
            temp = cur->next;  // 保存一下 cur的下一个节点,因为接下来要改变cur->next,改变后依靠这个才能找到下一结点
            cur->next = pre; // 翻转操作
            // 更新pre 和 cur指针,pre和cur前移
            pre = cur;
            cur = temp;
        }
        return pre;
    }
};

改进:

用tmp=cur->next来更新tmp,使得cur和tmp产生关联,和循环条件统一起来,当tmp=NULL时,不会因为使用tmp->next而报错。

解法2:递归法

递归由方法一改写而来

递归结束条件对应while循环结束条件

快慢指针前移过程由向下一个递归函数进行赋值来代替,下一次的pre和cur(即需要翻转的两个结点)作为形参传入

最后返回的就是pre

(如果不太明白的小伙伴可以暂时放一放,可以等做完回溯章节再回来,会好很多很多很多很多)

class Solution {
public:
    ListNode* re(ListNode *cur,ListNode * pre)
    {
        if(cur==NULL)//递归结束条件对应while循环条件
            return pre;//返回头结点
        ListNode * tmp=cur->next;//保存cur的下一结点
        cur->next=pre;//翻转操作
        //递归的过程就是快慢指针前移的过程
        //pre=cur;
        //cur=tmp;
        return re(tmp,cur);
    }
    ListNode* reverseList(ListNode* head) 
    {
        return re(head,NULL);
    }
};
  • 8
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值