LeetCode之链表类题目

链表类题目之CPP版

🚀 反转链表

ListNode* ReverseList(ListNode* head) {
    // write code here 双指针
    ListNode* pre = nullptr;
    ListNode* cur = head;
    while(cur != nullptr){
        auto tmp = cur->next;
        cur->next = pre;
        pre = cur;
        cur = tmp;
    }
    return pre;
}

🚀 链表内指定区间反转

ListNode* reverseBetween(ListNode* head, int m, int n) {
    // write code here
    ListNode* dummpy = new ListNode(-1);
    dummpy->next = head;
    ListNode* pre = dummpy;
    for(int i = 0; i < m - 1; i++){
        pre = pre->next;
    }
    ListNode* cur = pre->next;
    for(int i = 0; i < n - m; i++){
        auto tmp = cur->next; 
        cur->next = cur->next->next;
        // 顺序不能改变
        tmp->next = pre->next;
        pre->next = tmp;
    }
    return dummpy->next;
}

🚀 合并两个排序的链表

ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
    // write code here
    ListNode* dummpy = new ListNode(-1);
    ListNode* cur = dummpy;
    while(pHead1 != nullptr && pHead2 != nullptr){
        if(pHead1->val <= pHead2->val){
            cur->next = pHead1;
            pHead1 = pHead1->next;
        }else{
            cur->next = pHead2;
            pHead2 = pHead2->next;
        }
        cur = cur->next;
    }
    if(pHead1 != nullptr) cur->next = pHead1;
    if(pHead2 != nullptr) cur->next = pHead2;
    return dummpy->next;
}

🚀 合并k个已排序的链表

  • c++优先队列priority_queue(自定义比较函数)通过struct重载()操作符

    struct cmp{
        bool operator()(ListNode* a, ListNode* b){
            return a->val > b->val; // 完成greater功能
        }
    };
    
  • 通过优先级队列实现

    struct cmp{
        bool operator()(ListNode* a, ListNode* b){
            return a->val > b->val;
        }
    };
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        // write code here
        priority_queue<ListNode*, vector<ListNode*>, cmp> heap;
        ListNode* dummpy = new ListNode(-1);
        for(auto node: lists){
            if(node != nullptr){
                heap.push(node);
            }
        }
        ListNode* cur = dummpy;
        while(!heap.empty()){
            auto tmp = heap.top(); heap.pop(); //取出堆顶元素并弹出
            cur->next = tmp;
            cur = cur->next;
            if(tmp->next != nullptr){
                heap.push(tmp->next);
            }
        }
        return dummpy->next;
    }
    

🚀 判断链表中是否有环

class Solution {
public:
    // 双指针
    bool hasCycle(ListNode *head) {
        ListNode* low = head;
        ListNode* fast = head;
        while(fast != nullptr && fast->next != nullptr){
            fast = fast->next->next;
            low = low->next;
            if(fast == low){
                return true;
            }
        }
        return false;
    }
};

🚀 链表中环的入口节点

关键在于:入口节点到头节点的距离 = N*相遇点到入口节点的距离. 视频解析

ListNode* EntryNodeOfLoop(ListNode* pHead) {
    ListNode* fast = pHead;
    ListNode* low = pHead;
    while(fast != nullptr && fast->next != nullptr){
        fast = fast->next->next;
        low = low->next;
        if(fast == low){
            break;
        }
    }
    if(fast == nullptr || fast->next == nullptr) return nullptr;
    fast = pHead;
    while(fast != low){
        fast = fast->next;
        low = low->next;
    }
    return low;
}

🚀 链表中倒数第k个节点

  • 双指针:让fast指针先走k步,然后fastlow齐头并进,当fast指针走到nullptr时,low指针即为倒数第k个节点
  • 需要注意k的合法性,比如k大于链表的长度
ListNode* FindKthToTail(ListNode* pHead, int k) {
    // write code here 双指针
    ListNode* fast = pHead;
    ListNode* low = pHead;
    for(int i = 0; i < k; i++){
        if(fast != nullptr){ //判断fast是否为nullptr
            fast = fast->next;
        }else{
            return nullptr;
        }
    }
    while(fast != nullptr){
        fast = fast->next;
        low = low->next;
    }
    return low;
}

🚀 两个链表的第一个公共节点

  • 双指针:每个指针遍历一个链表,当其中一个指针遍历到nullptr时,则重新指向另一个链表的头节点。当两个指针相遇时即为第一个公共头节点。

  • 需要注意当其中一个链表为空时,直接返回nullptr

    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        if(pHead1 == nullptr || pHead2 == nullptr) return nullptr;
        //双指针
        ListNode* p1 = pHead1;
        ListNode* p2 = pHead2;
        while(p1 != nullptr || p2 != nullptr){
            if(p1 == nullptr) p1 = pHead2;
            if(p2 == nullptr) p2 = pHead1;
            if(p1 == p2) return p1;
            p1 = p1->next;
            p2 = p2->next;
        }
        return nullptr;
    }
    

🚀 链表相加

  • 反转链表,逐节点相加,当两个节点都为空且进位为空时,循环结束。

    ListNode* addInList(ListNode* head1, ListNode* head2) {
        // write code here
        ListNode* p1 = reverseList(head1);
        ListNode* p2 = reverseList(head2);
        // 结果链表
        ListNode* dummpy = new ListNode(-1);
        ListNode* pre = dummpy;
        ListNode* cur = nullptr;
        int carry = 0;
        while(p1 != nullptr || p2 != nullptr || carry != 0){
            int val1 = p1 == nullptr ? 0: p1->val;
            int val2 = p2 == nullptr ? 0: p2->val;
            int sum = val1 + val2 + carry;
            cur = new ListNode(sum%10);
            pre->next = cur;
            pre = pre->next;
            carry = sum / 10;
            if(p1 != nullptr) p1 = p1->next; 
            if(p2 != nullptr) p2 = p2->next;
        }
        return reverseList(dummpy->next);
    }
    ListNode* reverseList(ListNode* head){
        ListNode* pre = nullptr;
        ListNode* cur = head;
        while(cur != nullptr){
            auto tmp = cur->next;
            cur->next = pre;
            pre = cur;
            cur = tmp;
        }
        return pre;
    }
    

🚀 单链表排序

class Solution {
  public:
    ListNode* sortInList(ListNode* head) {
        // 统计链表长度
        int length(0);
        for(ListNode* node=head; node != nullptr; node=node->next) length++;
		// 循环O(logN)次
        for(int i = 1; i < length; i *= 2){
            // 初始化结果链表
            ListNode* dummpy = new ListNode(-1), *cur = dummpy;
            int cnt = ceil(1.0*length/(2.0*i));
            // 依次排序
            while(cnt--){
                ListNode* p = head, *q = head;
                for(int j = 0; j < i && q; j++) q = q->next;
                // 记录下一次排序的起始位置
                ListNode* next = q;
                for(int j = 0; j < i && next; j++) next = next->next;
                // 归并排序
                int l = 0, r = 0;
                while(l < i && r < i && p && q){
                    if(p->val <= q->val) cur = cur->next = p, p = p->next, l++;
                    else cur = cur ->next = q, q = q->next, r++;
                }
                // 扫尾
                while(l < i && p) cur = cur->next = p, p = p->next, l++;
                while(r < i && q) cur = cur ->next = q, q = q->next, r++;

                head = next;
            }
            cur->next = nullptr;
            head = dummpy->next;
        }
        return head;
    }
};

🚀 判断一个链表是否回文

  • 快慢指针找到中点,然后反转后半部分链表,最后一一对比即可

    bool isPail(ListNode* head) {
        // 找到链表的中点
        ListNode* fast = head, *low = head;
        while(fast != nullptr && fast->next != nullptr){
            fast = fast->next->next;
            low = low->next;
        }
        low = reverseList(low);
        fast = head;
        // 一一对比
        while(fast != nullptr && low != nullptr){
            if(fast->val != low->val) return false;
            fast = fast->next;
            low = low->next;
        }
        return true;
    }
    ListNode* reverseList(ListNode* head){
        ListNode* pre = nullptr;
        ListNode* cur = head;
        while(cur){
            auto temp = cur->next;
            cur->next = pre;
            pre = cur;
            cur = temp;
        }
        return pre;
    }
    

🚀 链表的奇偶重排

ListNode* oddEvenList(ListNode* head) {
    // write code here
    if(head == nullptr || head->next == nullptr) return head;

    ListNode* pre = head;
    ListNode* cur = head->next;
    ListNode* curHead = head->next;
    while(cur != nullptr && cur->next != nullptr){
        // 交叉连接
        pre->next = cur->next;
        pre = pre->next;

        cur->next = pre->next;
        cur = cur->next;
    }
    pre->next = curHead;
    return head;
}

🚀 删除有序链表中的重复元素

ListNode* deleteDuplicates(ListNode* head) {
    // write code here
    ListNode* low = head, *fast = head;
    while(fast != nullptr){
        while(fast != nullptr && low->val == fast->val) fast = fast->next;
        low->next = fast;
        low = fast;
    }
    return head;
}

🚀 删除有序链表中的重复元素Ⅱ

ListNode* deleteDuplicates(ListNode* head) {
    // write code here
    // 头节点可能会被删除, 新建一个虚拟头节点
    ListNode* dummpy = new ListNode(-1);
    dummpy->next = head;
    ListNode* pre = dummpy;
    while(pre->next != nullptr){
        auto cur = pre->next;
        while(cur != nullptr && pre->next->val == cur->val) cur = cur->next;
        if(pre->next->next == cur) pre = pre->next;
        else pre->next = cur;
    }
    return dummpy->next;
}

😸点赞是最大的鼓励😸
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值