147.对链表进行插入排序
1.题目介绍
给定单个链表的头 head ,使用 插入排序 对链表进行排序,并返回 排序后链表的头 。
插入排序 算法的步骤:
1.插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。
2.每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。
3.重复直到所有输入数据插入完为止。
下面是插入排序算法的一个图形示例。部分排序的列表(黑色)最初只包含列表中的第一个元素。每次迭代时,从输入数据中删除一个元素(红色),并就地插入已排序的列表中。
对链表进行插入排序。
示例 1:
输入: head = [4,2,1,3]
输出: [1,2,3,4]
示例 2:
输入: head = [-1,5,3,4,0]
输出: [-1,0,3,4,5]
2.题解
2.1 插入排序
思路
首先要理解插入排序,冒泡排序,选择排序的区别,这里请移步排序算法
插入排序总之就是维护一个有序数列,每次从数列外部取一个进入数列,同时完成排序。
对于链表也是一样,不过要维护的是指针,来区分有序数列和待排序数列。
这里我们维护一个lastSorted作为有序数列的尾结点,curr指向第一个待排序的数,即lastSorted->next
这里有两种情况:1.待排序的数就是最大的,直接lastSorted=lastSorted->next;即可
2.有序数列中有比待排序数更大的,这时候就要遍历有序链表,查看插入位置
遍历途中使用一个指针pre,通过判断pre->next->val是否大于curr->val,判断具体插入位置,链表插入就是三指针插入法即可
这里dummyHead很好的维护了头节点的位置,因为由于不断地插入排序,实际的头节点是在不断地变化的,有着dummyHead这个虚拟头结点,能帮我们很快定位头结点。
代码
/**
* 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* insertionSortList(ListNode* head) {
if (head == nullptr)
return head;
ListNode* dummyHead = new ListNode(0,head);
ListNode* lastNode = head;
ListNode* curr = head->next;
while(curr != nullptr){
if (lastNode->val <= curr->val) lastNode = lastNode->next;
else{
ListNode* pre= dummyhead;
while(pre->next->val <= curr->val) pre = pre->next;
lastNode->next = curr->next;
curr->next = pre->next;
pre->next = curr;
}
curr = lastNode->next;
}
ListNode* ans = dummyHead->next;
delete dummyHead;
return ans;
}
};
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了