题目链接:
题目描述:
思路:
归并排序
递归实现
用双指针找到中间点,然后把链表分成两个部分,不断进行这个操作,直到next或当前节点为null
返回当前节点,回到“上一步”
在“上一步”里,把返回的节点接受为自己的左右两段部分的头结点
然后根据大小进行合并
相邻节点直接合并
省去拆分的操作,直接合并相邻的节点
实现代码:
class Solution {
public ListNode sortList(ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode fast = head.next , slow = head;
//分割
while(fast != null && fast.next!= null){
fast = fast.next.next;
slow = slow.next;
}
ListNode tmp = slow.next;
slow.next = null;
//再分割
ListNode left = sortList(head);
ListNode right = sortList(tmp);
//虚拟头
ListNode dummy = new ListNode(0);
ListNode cur = dummy;
//合并
while(left != null && right != null){
if(left.val < right.val){
cur.next = left;
left = left.next;
} else{
cur.next = right;
right = right.next;
}
cur = cur.next;
}
cur.next = left != null ? left : right;
return dummy.next;
}
}
class Solution {
public ListNode sortList(ListNode head) {
if(head == null){
return head;
}
int length = 0;
ListNode node = head;
while(node != null){
length++;
node = node.next;
}
ListNode dummy = new ListNode(0,head);
for(int sublength = 1; sublength < length; sublength = sublength *2){
ListNode pre = dummy, cur = dummy.next;
while(cur != null){
//找到第1段
ListNode head1 = cur;
for(int i = 1; i < sublength && cur.next != null; i++){
cur = cur.next;
}
ListNode head2 = cur.next;
cur.next = null;
//找到第2段
cur = head2;
for(int i = 1; i < sublength && cur != null && cur.next != null ; i++){
cur = cur.next;
}
//找到剩下的,下一次while就是合并剩下的里面前两段
ListNode next = null;
if(cur != null){
next = cur.next;
cur.next = null;
}
//合并
ListNode merged = merge(head1,head2);
pre.next = merged;
while(pre.next != null){
pre = pre.next;
}
cur = next;
}
}
return dummy.next;
}
public ListNode merge(ListNode head1, ListNode head2){
ListNode dummy = new ListNode(0);
ListNode tmp = dummy, tmp1 = head1, tmp2 = head2;
while(tmp1 != null && tmp2 != null){
if(tmp1.val <= tmp2.val){
tmp.next = tmp1;
tmp1 = tmp1.next;
}else{
tmp.next = tmp2;
tmp2 = tmp2.next;
}
tmp = tmp.next;
}
tmp.next = tmp1 != null ? tmp1 : tmp2;
return dummy.next;
}
}