代码随想录day3 链表初探

203.移除链表元素

题目

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

示例 1:

输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]

思考

之前很少接触链表的题目,一看道题感觉非常懵,以为是用list做,没想到是listnode,完全用不了list的方法,后面看了视频讲解才慢慢了解listnode应该怎么写,本题主要有两种方法:

1、在原链表上直接删除,这种方法需要注意单独判断头节点是不是val,因为我们正常删除节点的方法是找到其上一个节点,让上一个节点指向其下一个节点,然后再删除(1->2->3,要删除2则必须将1指向3),而头节点前面没有节点,所以当头节点是val时则需要做head = head->next的操作,另外还需要注意,该方法是需要用两个while来做循环遍历

2、虚拟头节点,这种方法比较容易理解,就是类似数学添辅助线的方法在头节点前再加一个节点,这样头节点就不是头了,然后正常判断,最后把刚开始添加的头节点删掉就行

代码

//  原链表

class Solution {

public:

    ListNode *removeElements(ListNode *head, int val)

    {

        // 先判断头结点是不是val

        while (head != nullptr && head->val == val) {

            ListNode *tmp = head;  // 用临时节点来存储头节点

            head = head->next;

            delete tmp;

        }

        // 如果头结点不是val

        ListNode *cur = head;

        while(cur != nullptr && cur->next != nullptr)//这里要判断cur和cur->next都不为空 {

            if(cur->next->val == val) {

            ListNode *tmp = cur->next;

            cur->next = cur->next->next;

            delete tmp;

            }

            else cur = cur->next;

    }

    return head;

}

};

// 虚拟节点

class Solution {

public:

    ListNode *removeElements(ListNode *head, int val)

    {

        ListNode *dummyHead = new ListNode(0);  // 虚拟头节点

        dummyHead->next = head;

        ListNode *cur = dummyHead;

        // 和删除原链表中头节点不是val的方法一样

        while (cur->next != nullptr) {

            if (cur->next->val == val) {

                ListNode *tmp = cur->next;

                cur->next = cur->next->next;

                delete tmp;

            } else

                cur = cur->next;

        }

        head = dummyHead->next;  // 要把dummyHead删除,所以先把head确定好

        delete dummyHead;

        return head;

    }

};

707.设计链表

题目

在链表类中实现这些功能:

  • get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
  • addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
  • addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
  • addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val  的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
  • deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点

思考

这题是就是把链表的各种方法给自己写出来,没有什么算法技巧,对于我来说,需要注意的有以下几点:

1、本题用虚拟头节点非常有效,但是需要注意在private对象里先把dummyHead和size给先申明好

2、每个方法开头要判断index是否会越界导致异常

3、在写插入元素的方法时要先将要插入的node->next = cur->next, 然后再将cur->next = node,不然链会断掉;另:在指定位置插入元素是判断越界条件是index>size而不是index>size-1,因为可以在listnode的末尾前插入元素,相当于push_back

代码

public:

    MyLinkedList() {

        dummyHead = new ListNode(0);

        size = 0;

    }

    

    int get(int index) {

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

        ListNode* cur = dummyHead->next;

        while(index--) cur = cur->next;

        return cur->val;

    }

    

    void addAtHead(int val) {

        ListNode* node = new ListNode(val);

        node->next = dummyHead->next;

        dummyHead->next = node;

        size++;

    }

    

    void addAtTail(int val) {

        ListNode* node = new ListNode(val);

        ListNode* cur = dummyHead;

        while(cur->next != nullptr) cur = cur->next;

        cur->next = node;

        size++;

    }

    

    void addAtIndex(int index, int val) {

        if(index > size) return ;//关键,可以在listnode的末尾前插入元素,相当于push_back

        if(index < 0) index = 0;//如果index小于0,则在头部插入节点

        ListNode* node = new ListNode(val);

        ListNode* cur = dummyHead;

        while(index--) cur = cur->next;

        node->next = cur->next;

        cur->next = node;

        size++;

    }

    

    void deleteAtIndex(int index) {

        if(index < 0 || index >= size) return ;

        ListNode* cur = dummyHead;

        while(index--) cur = cur->next;

        ListNode* tmp = cur->next;

        cur->next = cur->next->next;

        delete tmp;

        //delete命令指示释放了tmp指针原本所指的那部分内存,

        //被delete后的指针tmp的值(地址)并非就是NULL,而是随机值。也就是被delete后,

        //如果不再加上一句tmp=nullptr,tmp会成为乱指的野指针

        //如果之后的程序不小心使用了tmp,会指向难以预想的内存空间

        tmp = nullptr;

        size--;

    }

private:

    int size;

    ListNode* dummyHead;

};

206.反转链表

题目

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL

思考

不看讲解视频确实想不到用双指针的解法,还在傻傻地想着像二叉树翻转一样用stack,本题精髓在于三点:

1、用双指针pre和cur,初始pre = nullptr, cur = head,因为要反过来,像示例里那样最后需要指向nullptr

2、在各自向前移位时先保存tmp = cur->next,这样当cur->next = pre后cur = tmp,不至于断链

3、从示例中来看,循环到最后时*pre = 5, cur = nullptr,pre就变成了头节点,所以return pre 

代码

class Solution {

public:

    ListNode* reverseList(ListNode* head) {

        ListNode* cur = head;

        ListNode* pre = nullptr;//双指针

        while(cur != nullptr) {

            ListNode* tmp = cur->next;

            cur->next = pre;

            pre = cur;

            cur = tmp;

        }

        return pre;

    }

};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值