一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
每日刷题 2021.04.03
- leetcode原题链接:leetcode-cn.com/problems/so…
- 难度:中等
- 方法:插入排序
题目
- 给定单个链表的头
head,使用 插入排序 对链表进行排序,并返回 排序后链表的头 。 - 插入排序 算法的步骤:
- 插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。
- 每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。
- 重复直到所有输入数据插入完为止。
- 下面是插入排序算法的一个图形示例。部分排序的列表(黑色)最初只包含列表中的第一个元素。每次迭代时,从输入数据中删除一个元素(红色),并就地插入已排序的列表中。
- 对链表进行插入排序。
示例
输入: head = [4,2,1,3]
输出: [1,2,3,4]
解题思路
拓展
- 所谓稳定性:就是两个相等的元素在数组中相对的位置,排序后是否改变
- 不改变:稳定的排序
- 改变:不稳定的排序
插入排序
- 生活中的场景:打扑克牌的时候,每次摸一张牌,就将它插入到手上已有的牌中的合适位置,逐渐完成整个排序。
- 遍历过程中,
write指针都指向当前链表之前最大的那个值,所以当read指针读到了小于write指针的是,需要作出删除插入的操作 - 首先
write指针就是read的前一个指针,所以很容易就能删除当前的read指针 - 然后找到插入点,这里如果是双向指针,可以从尾到前查找,当然也可以从
head开始查找 - 从起始
head节点开始查找比当前read指针值大的节点,在它之前插入 - 最后得到链表就是所求: 在遍历的过程中反复遍历,时间复杂度应该是
0(nlogn)
快速排序(经典题目)
AC代码
var insertionSortList = function(head) {
if(!head || !head.next) return head
let emptyNode = new ListNode()
emptyNode.next = head
let write = head
let read =write.next
while(read){
if(read.val<write.val){
// 先删除
let next = read.next
write.next = next
// 从empty指针开始,查找要插入的位置
let prev = emptyNode
let temp = emptyNode.next
while(temp.val<=read.val){
temp = temp.next
prev = prev.next
}
// 插入到 temp 之前
prev.next = read
read.next = temp
read = next
}else{
read = read.next
write=write.next
}
}
return emptyNode.next
};
总结
- 在一些有时间复杂度要求的题目中,使用快速排序,会比冒泡排序更优。