Day03.移除链表元素、反转链表

Day03.移除链表元素、反转链表

0203.移除链表元素

链接:0203.移除链表元素

思路:如果首位是目标值,那么删除首位,知道首位不为目标值为止。
由于首位不是目标值,那么每次只需要看当前位置的下一个即可。
如果下一个值为目标值,那么临时存储下一个节点,将当前节点指向下一个的下一个节点,删除临时存储的节点。

主要保证链表的连续性。

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val)
    {
        while (head) {
            if (head->val == val) {
                ListNode* d = head;
                head = head->next;
                delete d;
            } else {
                break;
            }
        }
        if (!head) {
            return head;
        }
        ListNode* cur = head;
        while (cur->next) {
            ListNode* temp = cur->next;
            if (temp->val == val) {
                cur->next = temp->next;
                delete temp;
            } else {
                cur = cur->next;
            }
        }
        return head;
    }
};

思路2:设置虚拟头节点,可以精简逻辑。

0707.设计链表

链接:0707.设计链表

这道题的重点是虚拟头节点和尾节点的维护

class MyLinkedList {
public:
    MyLinkedList()
    {
        _vHead = new ListNode;
        _vHead->val = -1;
        _vHead->next = nullptr;
    }

    ~MyLinkedList()
    {
        while (_vHead) {
            ListNode* d = _vHead;
            _vHead = _vHead->next;
            delete d;
        }
    }

    int get(int index)
    {
        ListNode* cur = _vHead->next;
        for (int i = 0; i < index && cur; ++i) {
            cur = cur->next;
        }
        return cur == nullptr ? -1 : cur->val;
    }

    void addAtHead(int val)
    {
        ListNode* curHead = _vHead->next;
        ListNode* h = new ListNode;
        h->val = val;
        h->next = curHead;
        if (curHead == nullptr) {
            _tail = h;
        }
        _vHead->next = h;
    }

    void addAtTail(int val)
    {
        ListNode* n = new ListNode;
        n->val = val;
        n->next = nullptr;
        if (_tail) {
            _tail->next = n;
            _tail = _tail->next;
        } else {
            _vHead->next = n;
            _tail = n;
        }
    }

    void addAtIndex(int index, int val)
    {
        if (index < 0) {
            addAtHead(val);
            return;
        }
        ListNode* prev = _vHead;
        for (int i = 0; i < index && prev; ++i) {
            prev = prev->next;
        }
        if (!prev) {
            return;
        }
        ListNode* r = prev->next;
        ListNode* n = new ListNode;
        n->val = val;
        n->next = r;
        prev->next = n;
        if (r == nullptr) {
            _tail = n;
        }
    }

    void deleteAtIndex(int index)
    {
        ListNode* prev = _vHead;
        for (int i = 0; i < index && prev; ++i) {
            prev = prev->next;
        }
        if (prev && prev->next) {
            ListNode* d = prev->next;
            prev->next = d->next;
            if (prev->next == nullptr) {
                _tail = prev == _vHead ? nullptr : prev;
            }
            delete d;
        }
    }

private:
    ListNode* _vHead = nullptr;
    // ListNode* _head = nullptr;
    ListNode* _tail = nullptr;
};

0206.反转链表

链接:0206.反转链表

思路:维护三个指针:prevcurlatter,分别指向前一个值、当前值、后一个值。
每次将cur的后继指向prev,然后按照prevcurlatter的顺序更新指针,将他们后移一位。

即:

  1. cur的后继指向prev
  2. prev后移为cur
  3. cur后移为latter
  4. latter后移为latter->next

然后循环,直到cur->next为空时停止。退出时cur为最后一个节点,这个cur的后继还没更改为prev
所以退出循环时还有一步cur->next=pre,此时cur就是逆序后的头节点。

核心代码概括为:

while (cur->next) {
    cur->next = prev;
    prev = cur;
    cur = latter;
    if (latter) {
        latter = latter->next;
    }
}
cur->next = prev;

源码:

class Solution {
public:
    ListNode* reverseList(ListNode* head)
    {
        if (!head) {
            return nullptr;
        }
        ListNode* prev = nullptr;
        ListNode* cur = head;
        ListNode* latter = cur->next;
        while (cur->next) {
            cur->next = prev;
            prev = cur;
            cur = latter;
            if (latter) {
                latter = latter->next;
            }
        }
        cur->next = prev;
        return cur;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值