算法记录Day 3 | 链表part01

70 阅读3分钟

算法记录Day 3 | 链表part01

LeetCode 203-移除链表元素

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

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

题目链接:leetcode.cn/problems/re…

题解
class Solution {
   public:
    ListNode *removeElements(ListNode *head, int val) {
        ListNode *dummyHead = new ListNode();
        dummyHead->next = head;
        ListNode *prev = dummyHead;
        ListNode *cur = head;
        while (cur != nullptr) {
            if (cur->val == val) {
                ListNode *next = cur->next;
                prev->next = next;
                cur = next;
            } else {
                cur = cur->next;
                prev = prev->next;
            }
        }
        return dummyHead->next;
    }
};
解题思路

通常要对链表进行操作,构建一个虚拟头结点是非常有必要的。因为虚拟头结点可以作为前结点prev,它的下一个指针的位置就是head。这题可以用到双指针,方便对链表结点进行删除。

LeetCode 707-设计链表

题目描述:实现 MyLinkedList 类:

  • MyLinkedList() 初始化 MyLinkedList 对象。
  • int get(int index) 获取链表中下标为 index 的节点的值。如果下标无效,则返回 -1 。
  • void addAtHead(int val) 将一个值为 val 的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。
  • void addAtTail(int val) 将一个值为 val 的节点追加到链表中作为链表的最后一个元素。
  • void addAtIndex(int index, int val) 将一个值为 val 的节点插入到链表中下标为 index 的节点之前。如果 index 等于链表的长度,那么该节点会被追加到链表的末尾。如果 index 比长度更大,该节点将 不会插入 到链表中。
  • void deleteAtIndex(int index) 如果下标有效,则删除链表中下标为 index 的节点。

题目链接:leetcode.cn/problems/de…

输入
["MyLinkedList", "addAtHead", "addAtTail", "addAtIndex", "get", "deleteAtIndex", "get"]
[[], [1], [3], [1, 2], [1], [1], [1]]
输出
[null, null, null, null, 2, null, 3]
题解

class MyLinkedList {
   private:
    ListNode *dummyHead;
    int size;

   public:
    MyLinkedList() {
        dummyHead = new ListNode();
        size = 0;
    }

    ~MyLinkedList() { freeMemoryLinkedList(dummyHead); }

    void freeMemoryLinkedList(ListNode *head) {
        ListNode *node = head;
        while (node != nullptr) {
            ListNode *tmp = node;
            node = node->next;
            delete tmp;
        }
        head = nullptr;
    }

    int get(int index) {
        if (index > size - 1 || index < 0) {
            return -1;
        }

        ListNode *cur = dummyHead->next;
        while (index > 0) {
            index--;
            cur = cur->next;
        }
        return cur->val;
    }

    void addAtHead(int val) {
        ListNode *node = new ListNode(val);
        ListNode *next = dummyHead->next;
        dummyHead->next = node;
        node->next = next;
        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) {
        ListNode *pre;
        pre = dummyHead;
        if (index == size) {
            addAtTail(val);
            return;
        } else if (index <= 0) {
            addAtHead(val);
            return;
        } else if (index > size) {
            return;
        }

        for (int i = 0; i < index; i++) {
            pre = pre->next;
        }
        ListNode *node = new ListNode(val);
        ListNode *next = pre->next;
        pre->next = node;
        node->next = next;
        size++;
    }

    void deleteAtIndex(int index) {
        if (index > size - 1 || index < 0) {
            return;
        }
        ListNode *pre = dummyHead;
        for (int i = 0; i < index; i++) {
            pre = pre->next;
        }
        ListNode *next = pre->next;
        pre->next = pre->next->next;
        size--;
    }

    void printLinkedList() {
        ListNode *h = dummyHead->next;
        while (h != nullptr) {
            cout << h->val << " ";
            h = h->next;
        }
    }
};
解题思路

该题需要注意的地方是添加和删除指定元素的index是否合法。使用虚拟头节点可以帮助更轻松掌握对边界情况的控制,避免空指针的访问。维护一个size变量可以判断index是否合法。

LeetCode 206-反转链表

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

题目链接:leetcode.cn/problems/re…

输入: head = [1,2,3,4,5]
输出: [5,4,3,2,1]
题解
class Solution {
   public:
    ListNode *reverseList(ListNode *head) {
        if (head == nullptr || head->next == nullptr) {
            return head;
        }
        ListNode *last = reverseList(head->next);
        head->next->next = head;
        head->next = nullptr;
        return last;
    }
};
解题思路

经典老题了,递归反转。直接一步走到底,此时last指向最后一个元素,head指向倒数第二个元素,只要不断修改指针的方向,并且将last元素返回,最后一个元素就变成了第一个元素。