刷题笔记(1)---链表

目录

  • 链表
    • 标记简介
      • 移除链表元素
        • 203.移除链表元素(√)
        • 237. 删除链表中的节点(√)
        • 83. 删除排序链表中的重复元素(√)
        • 82. 删除排序链表中的重复元素 II
      • 追赶指针技巧(双指针/快慢指针)
        • 876. 链表的中间结点(√)
        • 剑指 Offer 22. 链表中倒数第k个节点(√)
        • 141. 环形链表(√)
        • 142. 环形链表 II / 剑指 Offer II 022. 链表中环的入口节点(√)
        • 160. 相交链表(√)
        • 61. 旋转链表(√)
      • 反转链表
        • 206. 反转链表(√)
        • 92. 反转链表 II(√)
        • 24. 两两交换链表中的节点(√)
        • 面试题 02.05. 链表求和
        • 88. 合并两个有序数组(√)
        • 21. 合并两个有序链表(√)
        • 23. 合并K个升序链表(hard)(√)
        • 148. 排序链表
        • 138. 复制带随机指针的链表

链表

标记简介

一个(×)代表看不懂题解。
没有标记代表没有整理。
一个(√)代表能看懂解析和代码,有思路,实现不完全。
两个(√)代表有思路,能自己实现。
三个(√)代表掌握,从思路-》代码实现-》时间、空间复杂度。
四个(√)代表完全掌握,从思路-》代码实现-》时间、空间复杂度-》不同解法-》相似题型。

移除链表元素

203.移除链表元素(√)
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        if(head == nullptr) return nullptr;

        ListNode* dummy = new ListNode(0);
        dummy->next = head;


        ListNode* p = dummy;
        while(p->next != nullptr)
        {
            if(p->next->val == val)
            {
                ListNode* tmp = p->next;
                p->next = p->next->next;
                delete tmp;
            }
            else
            {
                p = p->next;
            }
            
        }
        return dummy->next;
    }
};
237. 删除链表中的节点(√)

请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点。传入函数的唯一参数为 要被删除的节点 。

偷梁换柱

class Solution {
public:
    void deleteNode(ListNode* node) {
        if(node == NULL) { return; }

        node->val = node->next->val;
        node->next = node->next->next;
    }
};
83. 删除排序链表中的重复元素(√)

链接: 83.删除排序链表中的重复元素.

class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if(head == nullptr) { return nullptr; }

        ListNode* node = head;
        while(node->next != nullptr)
        {
            if(node->val == node->next->val)
            {
                ListNode* temp = node->next;
                node->next = temp->next;
                delete temp;
            }
            else
            {
                node = node->next;
            }
        }

        return head;
    }
};
82. 删除排序链表中的重复元素 II

链接: 82.删除排序链表中的重复元素 II.

class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if(head == nullptr)
        {
            return nullptr;
        }

        ListNode* dummy = new ListNode(0);
        dummy->next = head;

        ListNode* node = dummy;
        while(node->next != nullptr && node->next->next != nullptr)
        {
            if(node->next->val == node->next->next->val)
            {
                int val_prev = node->next->val;
                while(node->next != nullptr && val_prev == node->next->val)
                {
                    ListNode* temp = node->next;
                    node->next = temp->next;
                    delete temp;
                }
            }
            else
            {
                node = node->next;
            }
        }

        return dummy->next;
    }
};
  1. 分隔链表
    链接: 83. 分隔链表.
class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
        if(head == nullptr)
        {
            return nullptr;
        }

        ListNode* leftDummy = new ListNode(0);
        ListNode* left = leftDummy;
        ListNode* rightDummy = new ListNode(0);
        ListNode* right = rightDummy;
        ListNode* node = head;

        while(node != nullptr)
        {
            if(node->val < x)
            {
                left->next = node;
                left = left->next;
            }
            else
            {
                right->next = node;
                right = right->next;
            }
            node = node->next;
        }

        right->next = nullptr;
        left->next = rightDummy->next;

        return leftDummy->next;
    }
};

追赶指针技巧(双指针/快慢指针)

对于寻找list某个特定位置的问题,不妨⽤两个变量chaser与runner,以不同的速度遍历list,找到⽬标位置: ListNode *chaser = head, *runner = head。

876. 链表的中间结点(√)

链接: 876. 链表的中间结点.

class Solution {
public:
    ListNode* middleNode(ListNode* head) {
        if(head == nullptr) { return nullptr; }

        ListNode* slow = head;
        ListNode* fast = head;
        while(fast != nullptr && fast->next != nullptr)
        {
            slow = slow->next;
            fast = fast->next->next;
        }
        return slow;
    }
};
剑指 Offer 22. 链表中倒数第k个节点(√)

链接: 链表中倒数第k个节点.

class Solution {
public:
    ListNode* dummy = new ListNode(0);
        dummy->next = head;

        ListNode* fast = dummy;
        ListNode* slow = dummy;

        while(fast->next && k--)
        {
            fast = fast->next;
        }

        while(fast->next != nullptr)
        {
            fast = fast->next;
            slow = slow->next;
        }

        return slow->next->val;
    }
};
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        if(head == nullptr || n < 0) { return nullptr; }

        ListNode* dummy = new ListNode(0);
        dummy->next = head;

        ListNode* fast = dummy;
        ListNode* slow = dummy;

        while(fast->next && n--)
        {
            fast = fast->next;
        }

        while(fast->next != nullptr)
        {
            fast = fast->next;
            slow = slow->next;
        }
        
        ListNode* tmp = slow->next;
        slow->next = slow->next->next;
        delete tmp;

        return dummy->next;
    }
};
141. 环形链表(√)

链接: 141. 环形链表.

class Solution {
public:
    bool hasCycle(ListNode *head) {
        if ((head == nullptr) || (head->next == nullptr))  return false;

        ListNode *slow = head;
        ListNode *fast = head;

        do
        {
            if((fast == nullptr) || (fast->next == nullptr))  
            {
              return false;
            }
            slow = slow->next;
            fast = fast->next->next;
        }while(slow != fast);

        return true;
    }
};
class Solution {
public:
    bool hasCycle(ListNode *head) {
        if(head == NULL) { return false; }

        ListNode* fast = head;
        ListNode* slow = head;

        while(fast && fast->next)
        {
            fast = fast->next->next;
            slow = slow->next;

            if(fast == slow) { return true; }
        }
        return false;
    }
};
142. 环形链表 II / 剑指 Offer II 022. 链表中环的入口节点(√)

链接: 142. 环形链表 II.

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        if(head == NULL)
        {
            return NULL;
        }

        ListNode* slow = head;
        ListNode* fast = head;

        do{
            if((fast == NULL) || (fast->next == NULL))
            {
                return NULL;
            }

            slow = slow->next;
            fast = fast->next->next;

        }while(slow != fast);

        ListNode* ptr = head;
        while(slow != ptr)
        {
            ptr = ptr->next;
            slow = slow->next;
        }

        return slow;
    }
};
class Solution {
public:
    bool hasCycle(ListNode *head) {
        if(head == NULL) { return false; }

        ListNode* fast = head;
        ListNode* slow = head;

        while(fast && fast->next)
        {
            fast = fast->next->next;
            slow = slow->next;

            if(fast == slow) { return true; }
        }
        return false;
    }
};
160. 相交链表(√)

链接: 160.相交链表.

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* curA = headA;
        ListNode* curB = headB;

        int lenA = 0;
        int lenB = 0;

        while(curA != NULL)
        {
            lenA++;
            curA = curA->next;
        }

        while(curB != NULL)
        {
            lenB++;
            curB = curB->next;
        }

        curA = headA;
        curB = headB;

        if(lenB > lenA)
        {
            swap(lenA, lenB);
            swap(curA, curB);
        }

        int gap = lenA - lenB;
        while(gap--) { curA = curA->next; }

        while(curA != NULL)
        {
            if(curA == curB) { return curA; }

            curA = curA->next;
            curB = curB->next;
        }

        return NULL;
    }
};
61. 旋转链表(√)

链接: 61. 旋转链表.

class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if(head == nullptr || head->next == nullptr || k == 0)
        {
            return head;
        }

        int count = 1;
        ListNode* p = head;
        while(p->next != nullptr)
        {
            p = p->next;
            count++;
        }

        int offset = count - k % count;
        if(offset == count)
        {
            return head;
        }

        p->next = head;
        while(offset--)
        {
            p = p->next;
        }

        ListNode* ret = p->next;
        p->next = nullptr;
        return ret;
    }
};

反转链表

206. 反转链表(√)

链接: 206. 反转链表.

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* pre = nullptr;
        ListNode* cur = head;
        ListNode* tmp;
        while (cur) {
            tmp = cur->next;
            cur->next = pre;
            pre = cur;
            cur = tmp;
        }
        return pre;
    }
};
92. 反转链表 II(√)

给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。

class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int left, int right) {
        // 设置 dummyNode 是这一类问题的一般做法
        ListNode *dummy = new ListNode(0);
        dummy->next = head;
        ListNode *pre = dummy;
         for (int i = 0; i < left - 1; i++) {
            pre = pre->next;
        }

        ListNode *cur = pre->next;
        ListNode *tmp;
        for (int i = 0; i < right - left; i++) {
            tmp = cur->next;
            cur->next = tmp->next;
            tmp->next = pre->next;
            pre->next = tmp;
        }

        return dummy->next;
    }
};
24. 两两交换链表中的节点(√)

链接: 24. 两两交换链表中的节点.

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if(head == nullptr) { return nullptr; }
        
        ListNode* dummy = new ListNode(0);
        dummy->next = head;

        ListNode* prev = dummy;
        ListNode* node1 = head, *node2 = head->next;

        while(node1 && node1->next)
        {
            node2 = node1->next;
            //swap the "next" of prev nodes
            prev->next = node1->next;  // = node2

            //swap the "next" of current nodes
            node1->next = node2->next;
            node2->next = node1;

            prev = node1;
            node1 = prev->next;
        }
        return dummy->next;
    }
};

这个版本好理解。

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* dummy = new ListNode(0);
        dummy->next = head;

        ListNode* cur = dummy;
        ListNode* tmp1;
        ListNode* tmp2;

        while(cur->next != nullptr && cur->next->next != nullptr)
        {
            tmp1 = cur->next;
            tmp2 = cur->next->next;

            cur->next = tmp2;
            tmp1->next = tmp2->next;
            tmp2->next = tmp1;

            cur = tmp1;
        }
        return dummy->next;
    }
};
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if(head == nullptr) { return nullptr; }
        
        ListNode* dummy = new ListNode(0);
        dummy->next = head;

        ListNode* cur = dummy;
        while((cur->next != nullptr) && (cur->next->next != nullptr))
        {
            ListNode* tmp1 = cur->next;
            ListNode* tmp2 = cur->next->next->next;

            cur->next = cur->next->next;
            cur->next->next = tmp1;
            tmp1->next = tmp2;

            cur = cur->next->next;
        }

        return dummy->next;
    }
};
面试题 02.05. 链表求和

链接: 面试题 02.05. 链表求和.

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode dummy(0);
        ListNode* p = &dummy;

        int cn = 0;
        while(l1 || l2)
        {
            int val = cn + (l1 ? l1->val : 0) + (l2 ? l2->val : 0);
            cn = val / 10;
            val = val % 10;
            p->next = new ListNode(val);
            p = p->next;

            if(l1)
            {
                l1 = l1->next;
            }

            if(l2)
            {
                l2 = l2->next;
            }
        }
        if(cn != 0)
        {
            p->next = new ListNode(cn);
            p = p->next;
        }

        return dummy.next;
    }
};
88. 合并两个有序数组(√)
class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        int p1 = m - 1, p2 = n - 1, cur = m + n - 1;

        while(p1 >= 0 && p2 >= 0)
        {
            nums1[cur--] = nums1[p1] > nums2[p2] ? nums1[p1--] : nums2[p2--];
        }

        while(p2 >= 0)
        {
            nums1[cur--] = nums2[p2--];
        }
    }
};
21. 合并两个有序链表(√)

链接: 21. 合并两个有序链表.

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode* dummy = new ListNode(0);
        ListNode* cur = dummy;
        while(l1 && l2)
        {
            if(l1->val <= l2->val)
            {
                cur->next = l1;
                l1 = l1->next;
            }
            else
            {
                cur->next = l2;
                l2 = l2->next;
            }
            cur = cur->next;
        }

        cur->next = (l1 != nullptr) ? l1 : l2;

        return dummy->next;
    }
};
23. 合并K个升序链表(hard)(√)

链接: 23. 合并K个升序链表.

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
private:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2)
    {
        ListNode* dummy = new ListNode(0);
        ListNode* cur = dummy;

        while(l1 && l2)
        {
            if(l1->val <= l2->val)
            {
                cur->next = l1;
                l1 = l1->next;
            }
            else
            {
                cur->next = l2;
                l2 = l2->next;
            }
            cur = cur->next;
        }

        cur->next = (l1 != nullptr) ? l1 : l2;
        return dummy->next; 
    }
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        if(lists.empty()) return nullptr;

        ListNode* p = lists[0];
        for(int i=1; i<lists.size(); ++i)
        {
            p = mergeTwoLists(p, lists[i]);
        }

        return p;
    }
};
148. 排序链表
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        if(head == nullptr || head->next == nullptr) return head;

        ListNode* head1 = head;
        ListNode* head2 = split(head);
        
        head1 = sortList(head1);
        head2 = sortList(head2);

        return merge(head1, head2);
    }

    ListNode* split(ListNode* node){
        ListNode* slow = node;
        ListNode* fast = node->next;

        while(fast && fast->next){
            slow = slow->next;
            fast = fast->next->next;
        }

        ListNode* splitHead = slow->next;
        slow->next = nullptr;
        return splitHead;
    }

    ListNode* merge(ListNode* node1, ListNode* node2){
        ListNode* p1 = node1;
        ListNode* p2 = node2;

        ListNode* dummy = new ListNode(0);
        ListNode* p = dummy;

        while(p1 && p2){
            if(p1->val < p2->val){
                p->next = p1;
                p1 = p1->next;
            }
            else{
                p->next = p2;
                p2 = p2->next;
            }

            p = p->next;
        }

        p->next = (p1 == nullptr) ? p2 : p1;
        return dummy->next;
    }
};
138. 复制带随机指针的链表

链接: 138. 复制带随机指针的链表.

你可能感兴趣的:(刷题笔记,数据结构,算法,c++,链表)