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

Leetcode 203.移除链表元素
思路分析:
移除链表元素和移除数组元素类似,可采用元素覆盖的方式。链表移除head节点和非head节点有差异,可分类讨论。更好的实现方法是引入dummy节点,令dummy->next为head。这样可以实现移除head节点和非head节点的处理逻辑相同。只要cur_node->next不是空指针,就需要一直向后寻找,如果cur_node->next的元素等于指定的val,则需要更新覆盖用next->next覆盖next元素,否则只需用往后查找。
注意:被覆盖的链表指向的内存需要释放掉,否则会引起内存泄漏。虽然不释放,leetcode上也不报错,但有内存泄漏风险。

代码实现:

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        ListNode* dummy = new ListNode();
        dummy->next = head;
        ListNode* cur_node = dummy;
        while (cur_node->next) {
            if (cur_node->next->val == val) {
                ListNode* tmp = cur_node->next;
                cur_node->next = cur_node->next->next;
                delete tmp;    // 注意释放被删除节点的内存
            } else {
                cur_node = cur_node->next;
            }
        }
        // return dummy->next;
        head = dummy->next;
        delete dummy;       // 注意释放被删除节点的内存
        return head;
    }
};

Leetcode 707.设计链表
思路解析:使用了带有虚拟头节点的单链表来实现一个简单的链表数据结构。链表中的每个节点都包含一个整数值和一个指向下一个节点的指针。
首先,定义一个 LinkedNode 结构体作为链表节点。结构体包含一个整数值 val 和一个指向下一个节点的指针 next。
在 MyLinkedList 类中定义一个私有的 _size 变量用于记录链表的大小,以及一个 _dummyHead 虚拟头节点指针,初始化时设置为空节点。
实现 MyLinkedList 的构造函数 MyLinkedList(),在构造函数中初始化 _dummyHead 为一个值为 0 的虚拟头节点,并将 _size 设置为 0。
实现 get(int index) 方法,根据给定的索引获取链表中对应位置节点的值。首先检查索引是否有效,如果无效则返回 -1。然后遍历链表直到找到目标节点,返回其值。
实现 addAtHead(int val) 方法,在链表头部插入一个新节点。创建一个新的节点并将其 next 指针指向当前头节点,然后将 _dummyHead 的 next 指针指向新节点,并将 _size 增加 1。
实现 addAtTail(int val) 方法,在链表尾部插入一个新节点。创建一个新的节点并将其 next 指针设置为空。然后通过遍历链表找到最后一个节点,将其 next 指针指向新节点,并将 _size 增加 1。
实现 addAtIndex(int index, int val) 方法,在给定的索引位置插入一个新节点。首先检查索引是否有效,如果无效则直接返回。然后创建一个新的节点,并在链表中找到目标位置的前一个节点。将新节点的 next 指针指向目标位置的节点,并将前一个节点的 next 指针指向新节点。最后将 _size 增加 1。
实现 deleteAtIndex(int index) 方法,删除给定索引位置的节点。首先检查索引是否有效,如果无效则直接返回。然后找到目标位置的前一个节点,并将其 next 指针指向目标位置的下一个节点。删除目标位置的节点,并将 _size 减少 1。
实现 printLinkedList() 方法,用于打印链表中所有节点的值。通过遍历链表,依次输出每个节点的值。

代码实现:

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

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

    int get(int index) {
        if (index > (_size - 1) || index < 0) {
            return -1;
        }
        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 != nullptr){
            cur = cur->next;
        }
        cur->next = newNode;
        _size++;
    }

    void addAtIndex(int index, int val) {
        if (index > _size || index < 0) {
            return;
        }
        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--;
    }

    void printLinkedList() {
        LinkedNode* cur = _dummyHead;
        while (cur->next != nullptr) {
            cout << cur->next->val << " ";
            cur = cur->next;
        }
        cout << endl;
    }
private:
    int _size;
    LinkedNode* _dummyHead;

};

Leetcode 206.反转链表
思路分析:
通过不断修改节点之间的连接关系来实现链表的反转。在遍历过程中,每次都将当前节点的next指针指向前一个节点,使得链表方向反转。同时,使用三个指针变量在循环过程中进行节点的遍历和保存,保证了反转操作的正确性。
定义pre_node,让当前节点cur_node的next指针指向pre_node,可定义pre_node的初值为空指针nullptr。
当前链表的最后一个节点即为反转链表的head节点。或cur_node的最后一个值即为反转链表的head节点。

代码实现:

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* pre_node = nullptr;
        ListNode* cur_node = head;
        ListNode* reverse_head = nullptr;
        while (cur_node != nullptr) {
            ListNode* p_next = cur_node->next;    // next值需要先保存下来,因为后面会被覆盖
            if (cur_node->next == nullptr) {
                reverse_head = cur_node;
            }
            cur_node->next = pre_node;
            pre_node = cur_node;
            cur_node = p_next;
        }
        return reverse_head;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值