刷题 - 分治

面试经典 150 题 - 分治

148. 排序链表⭐️⭐️⭐️ - 快慢指针找中间节点 - 归并排序


伪代码:

  • 将链表拆分成两半,返回右半边头节点(左半边头节点就是原始链表头节点)
  • 对左边进行排序并返回左边头节点
  • 对右边进行排序返回右边头节点
  • 传入左右半边头节点,合并两个升序链表
cpp 复制代码
// bug1: 把 cur_a->val <= cur_b->val 写成 cur_a <= cur_b
// 优化1:使用快慢指针找到中间节点,而不是两次遍历

//  分治的思想: 链表排序 = 断开左右半部分连接,对左半部分进行排序 + 对右半部分进行排序 + 合并两个升序链表
//  返回 升序链表的头节点
class Solution {
public:
    // 返回中间节点并拆分链表
    ListNode* splitList(ListNode* head) {
        if (head == nullptr || head->next == nullptr) return nullptr;
        ListNode* slow = head;
        ListNode* fast = head;
        ListNode* prev = nullptr;
        while (fast && fast->next) {
            prev = slow;
            slow = slow->next;
            fast = fast->next->next;
        }
        if (prev) prev->next = nullptr; // 拆分链表
        return slow;
    }
    // 合并两个升序链表 (不使用 dummy_head)
    ListNode* mergeList(ListNode* head_a, ListNode* head_b) {
        if (!head_a) return head_b;
        if (!head_b) return head_a;
        ListNode* merged_head = nullptr;  // 合并后链表的头节点
        ListNode* cur = nullptr;          // 当前操作的节点
        // 初始化 merged_head 和 cur
        if (head_a->val <= head_b->val) {
            merged_head = head_a;
            head_a = head_a->next;
        } else {
            merged_head = head_b;
            head_b = head_b->next;
        }
        cur = merged_head;
        // 合并剩余节点
        while (head_a && head_b) {
            if (head_a->val <= head_b->val) {
                cur->next = head_a;
                head_a = head_a->next;
            } else {
                cur->next = head_b;
                head_b = head_b->next;
            }
            cur = cur->next;
        }
        cur->next = (head_a != nullptr) ? head_a : head_b; 
        return merged_head;
    }

    // 归并排序
    ListNode* sortList(ListNode* head) {
        if (head == nullptr || head->next == nullptr) return head;
        // 拆分链表
        ListNode* mid = splitList(head);
        // 递归排序前半部分和后半部分
        ListNode* left = sortList(head);
        ListNode* right = sortList(mid);
        // 合并排序后的两个链表
        return mergeList(left, right);
    }
};
相关推荐
老歌老听老掉牙20 小时前
优化样条曲线拟合参数解决三维建模中的截面连续性问题
c++·opencascade·样条曲线
散峰而望21 小时前
【算法竞赛】栈和 stack
开发语言·数据结构·c++·算法·leetcode·github·推荐算法
不爱吃糖的程序媛21 小时前
OpenHarmony 通用C/C++三方库 标准化鸿蒙化适配
c语言·c++·harmonyos
fqbqrr21 小时前
2601C++,导出控制
c++
陌路2021 小时前
日志系统7--异步日志的实现
c++
程序员Jared21 小时前
C++11—this_thread
c++·this_thread
mjhcsp1 天前
C++ Manacher 算法:原理、实现与应用全解析
java·c++·算法·manacher 算法
Z1Jxxx1 天前
0和1的个数
数据结构·c++·算法
朔北之忘 Clancy1 天前
2020 年 6 月青少年软编等考 C 语言二级真题解析
c语言·开发语言·c++·学习·青少年编程·题解·尺取法
消失的旧时光-19431 天前
C++ 中的 auto 与 nullptr:不是语法糖,而是类型系统升级
开发语言·c++