leetcode刷题笔记一百四十八题 排序列表
源地址:148. 排序链表
问题描述:
在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
示例 1:
输入: 4->2->1->3
输出: 1->2->3->4
示例 2:输入: -1->5->3->4->0
输出: -1->0->3->4->5
//最初的想法与很多人一致,使用快慢指针分割进行归并排序
//但是由于使用了递归,时间复杂度为O(nlogn), 空间复杂度为O(logn)
/**
* Definition for singly-linked list.
* class ListNode(var _x: Int = 0) {
* var next: ListNode = null
* var x: Int = _x
* }
*/
object Solution {
def sortList(head: ListNode): ListNode = {
if (head == null || head.next == null) return head
var slow = head
var fast = head.next
while (fast != null && fast.next != null){
fast = fast.next.next
slow = slow.next
}
var mid = slow.next
var start = head
slow.next = null
var left = sortList(head)
var right = sortList(mid)
var h = ListNode(0)
val res = h
while (left != null && right != null){
if (left.x < right.x){
h.next = left
left = left.next
}
else{
h.next = right
right = right.next
}
h = h.next
}
if (left != null) h.next = left
else h.next = right
return res.next
}
}
//若要实现空间复杂度O(1),需要将递归改为迭代处理,使用intv标记当前当前作用范围,逐渐扩大,直至与链表长度一致
import util.control.Breaks._
object Solution {
def sortList(head: ListNode): ListNode = {
var h = head
var length = 0
var intv = 1
//测量链表长度
while (h != null){
h = h.next
length += 1
}
//构建辅助头结点
val res = ListNode(0)
res.next = head
while (intv < length){
breakable{
var pre = res
var cur = res.next
//基于intv 对链表进行归并
//breakable{
while (cur != null){
//intln("yes")
var cur1 = cur
var i = intv
while (i > 0 && cur != null){
i -= 1
cur = cur.next
}
//第一段intv未满,第二段为空
if (i > 0) break()
var cur2 = cur
i = intv
while (i > 0 && cur != null){
cur = cur.next
i -= 1
}
var length1 = intv
var length2 = intv - i
while (length1 > 0 && length2 > 0){
if (cur1.x < cur2.x){
pre.next = cur1
cur1 = cur1.next
length1 -= 1
}
else{
pre.next = cur2
cur2 = cur2.next
length2 -= 1
}
pre = pre.next
}
if (length1 > 0){
pre.next = cur1
}
else{
pre.next = cur2
}
//更新pre指针,连接同层链表
while (length1 > 0){
pre = pre.next
length1 -= 1
}
while (length2 > 0){
pre = pre.next
length2 -= 1
}
pre.next = cur
}
}
intv *= 2
}
return res.next
}
}