【C++算法】链表

知识总结

  • 常用技术:

1.画图!!——>直观+形象+便于理解

2.引入虚拟”头结点“

  1. 便于处理边界情况
  2. 方便对链表操作

3.不要吝啬空间,大胆定义变量

4.快慢双指针——判环、找链表中环的入口、找链表中倒数第n个节点

  • 链表中的常用操作

1.创建一个新节点

2.尾插

3.头插

俩数相加

  • 题目链接

俩数相加icon-default.png?t=O83Ahttps://leetcode.cn/problems/add-two-numbers/

  • 算法原理

  • 代码步骤
/**
 * 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* addTwoNumbers(ListNode* l1, ListNode* l2) 
    {
        ListNode* cur1 = l1, *cur2 = l2;
        ListNode* newHead = new ListNode(0);
        int t = 0;
        ListNode* tail = newHead;
        while(cur1 || cur2 || t)
        {
            if(cur1) 
            {
                t += cur1->val;
                cur1 = cur1->next;
            }
            if(cur2)
            {
                t += cur2->val;
                cur2 = cur2->next;
            } 
            tail->next = new ListNode(t % 10);
            t /= 10;
            tail = tail->next;
        }
        tail = newHead->next;
        delete newHead;
        return tail;
    }
};

俩俩交换链表中的节点

  • 题目链接

俩俩交换链表中的节点icon-default.png?t=O83Ahttps://leetcode.cn/problems/swap-nodes-in-pairs/description/

  • 算法原理

  • 代码步骤
/**
 * 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* swapPairs(ListNode* head) 
    {
        if(head == nullptr || head->next == nullptr) return head;
        ListNode *newHead = new ListNode(0);
        newHead->next = head;
        ListNode *prev = newHead, *cur = newHead->next;
        ListNode *next = cur->next, *nnext = cur->next->next;
        while(cur && next)
        {
            prev->next = next;
            next->next = cur;
            cur->next = nnext;

            prev = cur;
            cur = nnext;
            if(cur) next = cur->next;
            if(next) nnext = next->next;
        }
        cur = newHead->next;
        delete newHead;
        return cur;
    }
};

重排链表

  • 题目链接

重排链表icon-default.png?t=O83Ahttps://leetcode.cn/problems/reorder-list/description/

  • 算法原理

  • 代码步骤
/**
 * 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:
    void reorderList(ListNode* head) 
    {
        if(head == nullptr || head->next == nullptr || head->next->next == nullptr)
        {
            return;
        }

        // 找到中间结点
        ListNode* slow = head, *fast = head;
        while(fast && fast->next)
        {
            slow = slow->next;
            fast = fast->next->next;
        }

        cout << slow->val << " " << slow->next->val << endl;

        // 逆序——头插
        ListNode* newHead = new ListNode(0);
        ListNode *cur = slow->next;
        slow->next = nullptr;
        while(cur)
        {
            slow->next = cur->next;
            cur->next = newHead->next;
            newHead->next = cur;

            cur = slow->next;
        }

        // 合并俩个链表
        ListNode *cur1 = head, *cur2 = newHead->next;
        ListNode* ret = new ListNode(0);
        cur = ret;
        while(cur1)
        {
            cur->next = cur1;
            cur = cur->next;
            if(cur1) cur1 = cur1->next;
            if(cur2)
            {
                cur->next = cur2;
                cur = cur->next;
                cur2 = cur2->next;
            }
        }

        head = ret->next;
        delete ret;
        delete newHead;
    }
};

合并k个升序链表

  • 题目链接

合并k个升序链表icon-default.png?t=O83Ahttps://leetcode.cn/problems/merge-k-sorted-lists/

  • 算法原理

  • 代码展示
/**
 * 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 {
    struct cmp
    {
        bool operator()(ListNode* l1, ListNode* l2)
        {
            return l1->val > l2->val;
        }
    };
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) 
    {
        priority_queue<ListNode*, vector<ListNode*>, cmp> heap;
        for(auto ch : lists)
        {
            if(ch) heap.push(ch);
        }

        ListNode* newHead = new ListNode(0);
        ListNode* prev = newHead;
        while(!heap.empty())
        {
            ListNode* tmp = heap.top();
            heap.pop();

            prev->next = tmp;
            prev = tmp;
            if(tmp->next) heap.push(tmp->next);
        }

        prev = newHead->next;
        delete newHead;
        return prev;
    }
};

k个一组翻转链表

  • 题目链接

k个一组翻转链表icon-default.png?t=O83Ahttps://leetcode.cn/problems/reverse-nodes-in-k-group/description/

  • 算法原理

  • 代码展示
/**
 * 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* reverseKGroup(ListNode* head, int k) {
        
        // 计算翻转次数
        int n = 0;
        ListNode *tmp = head;
        while(tmp)
        {
            tmp = tmp->next;
            n++;
        }
        n = n / k;
        
        ListNode newHead;
        newHead.next = nullptr;
        ListNode *prev = &newHead, *cur = head;
        
        for(int i = 0; i < n; i++)
        {
            tmp = cur;
            for(int j = 0; j < k; j++)
            {
                ListNode *next = cur->next;
                cur->next = prev->next;
                prev->next = cur;
                cur = next;
            }
            prev = tmp;
        }
        
        prev->next = cur;
        
        cur = newHead.next;
        return cur;
    }
};

猜你喜欢

转载自blog.csdn.net/dab112/article/details/142219164