当前位置: 首页 > news >正文

力扣HOT100之链表: 148. 排序链表


这道题直接用蠢办法来做的,直接先遍历一遍链表,用一个哈希表统计每个值出现的次数,由于std::map<int, int>会根据键进行升序排序,因此我们将节点的值作为键,其在整个链表中的出现次数作为值,当所有元素统计完毕以后,我们直接按照顺序遍历哈希表,然后将一个键对应的值填入到链表中,当哈希表中所有键都填充完毕时,链表就排序好了,直接返回即可。

/**
 * 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) {
        map<int, int> hash;  //记录各个值的
        ListNode* current = head;
        while(current){
            hash[current -> val]++;
            current = current -> next;
        }
        current = head;
        for(auto i : hash){
            while(i.second > 0){
                current -> val = i.first;
                current = current -> next;
                i.second--;
            }
        }
        return head;
    }
};

在手撕面试的时候这样做肯定是不行的,我又去看了下灵神的题解,他的思路也比较简单易懂,但是需要两道题的前置基础,分别是876. 链表的中间结点和21. 合并两个有序链表,这里就不细讲两道题的解题思路了,我们直接将两道题的函数(middleNode()和mergeTwoLists())搬过来用就行了,假设我们现在已经有了这两个功能的函数,然后我们直接进行递归处理,将一个链表进行排序可以分为如下步骤:

  1. 调用middleNode()获取该链表的中间节点,并将中间节点与上一节点的连接切断,从而分成两条长度相近的链表;
  2. 将两条链表的进行排序,也就是递归调用本题的sortList()函数,然后函数分别返回两条排序过后链表的头节点;
  3. 然后调用mergeTwoLists()将两个有序链表合并,最终拼接回一条完整的链表
  4. 返回链表的头节点
    在这里有几个细节需要说明:1.将中间节点与上一节点的连接断开的操作应当在middleNode()函数内进行,在主函数中是无法追溯到中间节点的上一节点的;2.本题函数需要明确递归终止条件,我们很容易想到:当长度为n(n > 2)的链表被递归拆分出长度为2的子链表时,将其拆分为两条长度为1的链表,此时已经不可拆分,也无需排序,所以当链表只含头节点这一个节点时,直接返回头节点即可。**还有一种极端情况:**当输入的原始链表为空时,也不需要进行排序,直接返回头节点即可。
    下面是我的代码
/**
 * 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:
    //876. 链表的中间结点(代码不完全与那题一样,本题还须做断开链表处理)
    ListNode* middleNode(ListNode* head) {
        ListNode* fast = new ListNode();
        ListNode* slow = new ListNode();
        fast = head;
        slow = head;
        ListNode* pre;
        while(fast && fast -> next){
            pre = slow;
            slow = slow -> next;
            fast = fast -> next -> next;
        }
        pre -> next = nullptr;
        return slow;
    }
    //21. 合并两个有序链表
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        //处理终止条件
        if(!list1) return list2;
        if(!list2) return list1;
        //递归主体逻辑
        if(list1 -> val < list2 -> val){
            list1 -> next = mergeTwoLists(list1 -> next, list2);
            return list1;
        }
        else{
            list2 -> next = mergeTwoLists(list2 -> next, list1);
            return list2;
        }
    }
    ListNode* sortList(ListNode* head) {
        //终止条件
        //链表为空或链表仅有一个节点则无需排序,直接返回
        if(!head || !head -> next)
            return head;
        //递归主体逻辑
        //1.将链表拆成两条
        ListNode* left = head;
        ListNode* right = middleNode(head);
        //2.将两条链表进行排序
        left = sortList(left);
        right = sortList(right);
        //3.将两条有序链表合并
        head = mergeTwoLists(left, right);
        return head;
    }
};

相关文章:

  • queue容器
  • 3.软考高项(信息系统项目管理师)-范围管理
  • Openssl升级至openssl9.8p1含全部踩坑内容
  • Socket多路复用网络编程应用总结
  • RDD行动算子和累加器
  • 低代码控件开发平台:飞帆中粘贴富文本的控件
  • C++学习中常见的数组越界问题及解决方案
  • fit 转 gpx
  • w286入校申报审批系统设计与实现
  • 单片机方案开发 代写程序/烧录芯片 九齐/应广等 电动玩具 小家电 语音开发
  • Gemini Deep Research惊艳升级:2.5 Pro模型带来的研究效率革命
  • Transformer 多卡并行计算-SimpleDataset设计:`labels`;input_ids;attention_mask是什么
  • 加速度计芯片的主要参数定义、计算、测试方法
  • 【LaTeX】
  • numpy初步掌握
  • 02142数据结构导论
  • 我可能用到的网站和软件
  • 三、TorchRec中的Optimizer
  • Linux——Shell编程之条件语句
  • 电容命名解析与多类型电容的必要性
  • 成都网站app开发/足球世界排名
  • 什么网站可以有人做详情页/网络营销方案
  • 甘肃省建设厅执业资格注册中心网站通知/站长查询域名
  • 网络软件开发公司/seo辅助优化工具
  • 网站开发实训目的/搜索seo神器
  • 全国住房和城乡建设厅证书查询网/seo网站关键词优化软件