在O(n log n)的时间内使用常数级空间复杂度对链表进行排序。
public ListNode sortList (ListNode head) { if (head==null || head.next==null) return head; ListNode fast = head.next; ListNode slow = head; while (fast!=null && fast.next!=null) { fast=fast.next.next; slow=slow.next; } // 获取链表的两个部分 ListNode h1 = head; ListNode h2 = slow.next; slow.next=null; // 对两个部分递归进行归并排序 h1 = sortList(h1); h2 = sortList(h2); // 归并有序链表 return merge(h1,h2); } public ListNode merge(ListNode h1,ListNode h2) { ListNode head = new ListNode(-1); ListNode tail = head; while (h1!=null && h2!=null) { if (h1.val<=h2.val) { tail.next=h1; tail=tail.next; h1=h1.next; } else { tail.next=h2; tail=tail.next; h2=h2.next; } } tail.next=h1!=null?h1:h2; return head.next; }
import java.util.*; /* * public class ListNode { * int val; * ListNode next = null; * } */ public class Solution { /** * * @param head ListNode类 * @return ListNode类 */ public ListNode sortList (ListNode head) { // write code here if(head == null || head.next == null) return head; ListNode slow = head; ListNode fast = head.next; while(fast != null && fast.next != null){ slow = slow.next; fast = fast.next.next; } ListNode tmp = slow.next; slow.next = null; ListNode left = sortList(head); ListNode right = sortList(tmp); ListNode h = new ListNode(0); ListNode res = h; while(left != null && right != null){ if(left.val <= right.val){ h.next = left; left = left.next; } else { h.next = right; right = right.next; } h = h.next; } h.next = left != null ? left : right; return res.next; } }
import java.util.*; /* * public class ListNode { * int val; * ListNode next = null; * } */ public class Solution { /** * * @param head ListNode类 * @return ListNode类 */ public ListNode sortList (ListNode head) { // write code here if(head==null || head.next==null) return head; ListNode mid = findMidList(head); //断开 ListNode midNext = mid.next; mid.next=null; return mergeList(sortList(head),sortList(midNext)); } public ListNode findMidList(ListNode h){ if(h==null || h.next==null) return h; ListNode l1 =h; ListNode l2 =h; while(l2.next!=null && l2.next.next!=null){ l1=l1.next; l2=l2.next.next; } return l1; } public ListNode mergeList(ListNode left,ListNode right){ ListNode head ,relist;//结果 if(left==null)return right; if(right==null)return left; ListNode f1=left.next,f2=right.next; //头结点判断 if(left.val<right.val){ relist=head=left; f2=right; }else{ relist=head=right; f1=left; } while(f1!=null && f2 !=null){ if(f1.val<f2.val){ relist.next=f1; relist=relist.next; f1 = f1.next; }else{ relist.next=f2; relist=relist.next; f2 = f2.next; } } if(f1!=null){ relist.next=f1; } if(f2!=null){ relist.next=f2; } return head; } }
/** * Definition for singly-linked list. * class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class Solution { public ListNode sortList(ListNode head) { if(head==null||head.next==null) return head; ListNode mid=findmid(head); ListNode right=mid.next; mid.next=null; return merge(sortList(head),sortList(right)); } public ListNode findmid(ListNode head){ if(head==null||head.next==null) return head; ListNode fast,slow; fast=slow=head; while(fast.next!=null&&fast.next.next!=null){ fast=fast.next.next; slow=slow.next; } return slow; } public ListNode merge(ListNode left,ListNode right){ if(left==null) return right; if(right==null) return left; ListNode head,t; if(left.val<right.val){ t=left; head=t; left=left.next; } else{ t=right; head=t; right=right.next; } while(left!=null&&right!=null){ if(left.val<right.val){ t.next=left; left=left.next; t=t.next; } else{ t.next=right; right=right.next; t=t.next; } } if(left==null){ t.next=right; } if(right==null){ t.next=left; } return head; } }
public class Solution {
private static void swap(ListNode a, ListNode b) {
int tmp = a.val;
a.val = b.val;
b.val = tmp;
}
private static int len(ListNode head) {
int n = 0;
while(head!=null){
n++;
head = head.next;
}
return n;
}
class MaxHeap {
ListNode[] heap;
private int length;
MaxHeap(ListNode head){
length = len(head);
heap = new ListNode[length];
int i = 0;
while (head!=null){
heap[i++] = head;
head = head.next;
}
adjust();
}
// 从start节点开始,通过“下沉”来调整堆,如果一旦下移节点,换下去的节点就可能被破坏子节点最大堆性质,需要继续调整。
private void adjNodeDown(int start, int end){
ListNode curNode = heap[start];
int next = 2*start+1;
while (next <= end) {
if (next+1 <= end && heap[next+1].val > heap[next].val) {
next++;
}
if (curNode.val >= heap[next].val) {
break;
} else {
swap(curNode, heap[next]);
curNode = heap[next];
next = 2*next +1;
}
}
}
// 调整二叉堆为最大堆
private void adjust(){
if(length<2) return;
//从最后一个非叶子节点开始遍历,通过子节点对应父节点是floor((i-1)/2)推导得来
//从叶子节点开始遍历也可以,如果没有叶子节点就跳过去 int start = (length-2)/2;
while (start >= 0){
adjNodeDown(start--, length-1);
}
}
// 递增排序,依赖最大堆性质,每次取出根节点(最大值)往数组后面放,缩小堆大小并重新调整,获取新的最大值
ListNode sortAsc(){
int i = length-1;
while (i>0){
swap(heap[0], heap[i]);
adjNodeDown(0, --i);
}
return heap[0];
}
}
public ListNode sortList(ListNode head) {
if(head==null) return null;
MaxHeap maxHeap = new MaxHeap(head);
return maxHeap.sortAsc();
}
}
public class Solution { public ListNode sortList(ListNode head) { if (head == null) { return null; } return mergeSort(head); } public ListNode mergeSort(ListNode head) { if (head.next == null) { return head; } ListNode pre = null; ListNode slow = head; ListNode fast = head; while (fast != null && fast.next != null) { pre = slow; slow = slow.next; fast = fast.next.next; } pre.next = null; ListNode l1 = mergeSort(head); ListNode l2 = mergeSort(slow); return merge(l1, l2); } public ListNode merge(ListNode l1, ListNode l2) { ListNode dummy = new ListNode(0); ListNode cur = dummy; while (l1 != null && l2 != null) { if (l1.val < l2.val) { cur.next = l1; cur = cur.next; l1 = l1.next; } else { cur.next = l2; cur = cur.next; l2 = l2.next; } } if (l1 != null) { cur.next = l1; } if (l2 != null) { cur.next = l2; } return dummy.next; } }
/** * Definition for singly-linked list. * class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class Solution { public ListNode sortList(ListNode head) { if(head == null)return null; else return mergeSort(head); } public ListNode mergeSort(ListNode head){ if(head == null || head.next == null){ return head; } ListNode fast = head; ListNode slow = head; ListNode pre = null; while(fast!=null && fast.next != null){ // 划分 O(n) fast = fast.next.next; pre = slow; slow = slow.next; } if(slow != fast){ pre.next = null; } ListNode left = head; ListNode right = slow; ListNode l = mergeSort(left); //递归求解左半部分 T(n/2) ListNode r = mergeSort(right); // 递归求解右半部分 T(n/2) return merge(l,r); } public ListNode merge(ListNode left, ListNode right){ //有序单链表的归并,空间复杂度O(1) if(left == null){ return right; } if(right == null){ return left; } ListNode resHead = null; // resHead 新生成链表的表头 ListNode res = null; // res 跟踪新链表尾端 if(left.val>right.val){ resHead = right; right = right.next; }else { resHead = left; left = left.next; } res = resHead; while(right!=null && left!=null){ if(left.val<right.val){ res.next = left; left = left.next; }else { res.next = right; right = right.next; } res = res.next; } if(left!=null){ res.next = left; } if(right!=null){ res.next = right; } return resHead; } }
public class Solution { public ListNode sortList(ListNode head) { if (head==null) return null; return fen( head ); } public ListNode bing(ListNode start,ListNode left) { ListNode s = start; ListNode l = left; ListNode node = null; while(start!=null && left!=null) { if(start.val<=left.val) { if(node!=null) node.next = start; node = start; start = start.next; }else{ if(node!=null) node.next = left; node = left; left = left.next; } } if(start==null) node.next=left; if(left==null) node.next=start; if (s.val<=l.val) return s; return l; } public ListNode fen(ListNode node) { if(node.next==null) return node; ListNode root = node.next; node.next = null; ListNode q = bing( node,fen( root ) ); return q; } }我也不知道我的答案满不满足题意,反正我过了,嘿嘿
package LinkedList; //本题涉及的知识点: // 1.链表的定义; // 2.构归并排序的sort和merge函数的实现; // 3.链表的指针操作, // 4.合并两个有序链表 public class SortList { class ListNode{//链表节点的定义 int val; ListNode next; ListNode(int x){ this.val = x; this.next = null; }//带一个参数的构造函数 } public ListNode sortList(ListNode head) { //框架:1:自上而下的归并写法。 sort(a,low,mid);sort(a,mid+1,high);merge(a,low,mid,high); if (head==null||head.next==null) return head; ListNode fast = head; ListNode slow = head; while (fast.next!=null&&fast.next.next!=null){ if (head==null || head.next==null){ slow = head; break; } fast = fast.next.next; slow = slow.next; } ListNode mid = slow; //这里要断开链接,分两步:先获取后一个节点,然后将前一个节点的下一个节点指向空 ListNode midNext = mid.next;//获取后一个节点,作为后半部分的头结点 mid.next = null;//指向空 ListNode left = sortList(head); ListNode right = sortList(midNext); return merge(left,right); } //归并操作,将两个有序的链表合并在一起 private ListNode merge(ListNode left, ListNode right) { if (left==null) return right; if (right==null) return left; ListNode retNode = null; ListNode curNode = null;//在已排序部分滑动 while (left!=null&&right!=null){ if (left.val<right.val){ if (retNode == null){//只判断一次,retNode是不是没有赋值 retNode = left; curNode = left; }else { curNode.next = left;//将新的节点添加到已排序链表的后面 curNode = left;//更新指针 } left = left.next; }else { if (retNode == null){//只判断一次,retNode是不是没有赋值 retNode = right; curNode = right; }else { curNode.next = right;//将新的节点添加到已排序链表的后面 curNode = right;//更新指针 } right = right.next; } } if (left!=null) curNode.next = left; else curNode.next = right; return retNode; } }
Sort a linked list in O(n log n) time using constant space complexity.
Example 1:
Input: 4->2->1->3
Output: 1->2->3->4
Example 2:
Input: -1->5->3->4->0
Output: -1->0->3->4->5
最近忙着追《都挺好》,差点忘记每天的任务。这一题要求时间复杂度为O(n log n) 并且用常数级别的空间复杂度。对于链表这种数据结构,不像数组那么方便,因此堆排序以及快速排序不是很方便,因此这一题用归并排序比较合适,并且对于本题,空间上不需要用数组来存储,因此是常数级别的。
class Solution {
//归并排序的归过程
public ListNode sortList(ListNode head) {
//1.判定是否为空或者只有一个元素,这也是归并排序中归的停止条件
if(head == null || head.next == null){
return head;
}
//2.将链表截成两段
ListNode pre = null;
ListNode slow = head;
ListNode fast = head;
while(fast != null && fast.next != null){
pre = slow;
slow = slow.next;
fast = fast.next.next;
}
//3.此时pre跟slow指的一样,现在将链表从中间断开
pre.next = null;
//4.继续再对上面分开的链表再分
ListNode l1 = sortList(head);
ListNode l2 = sortList(slow);
//5.递归分开之后就应该按照一定的规则合并了
return merge(l1,l2);
}
//归并排序的并过程
private ListNode merge(ListNode l1,ListNode l2){
//新建一个结点用于串联并过程结果
ListNode tmp = new ListNode(0);
ListNode p = tmp;
//并的过程,谁小谁就接到p后面
while(l1!=null && l2!=null){
if(l1.val < l2.val){
p.next = l1;
l1 = l1.next;
}else{
p.next = l2;
l2 = l2.next;
}
p = p.next;
}
//如果有一段没有结束,直接接到后面即可
if(l1 != null){
p.next = l1;
}
if(l2 != null){
p.next = l2;
}
//返回下一个结点
return tmp.next;
}
}
/************** * 归并排序的实现 最终要的在于实现二路归并的算法 * 分成两个部分 对左半部分进行归并排序 对右半部分进行归并排序 * 左右部分进行二路归并 **************/ public ListNode sortList(ListNode head) { //链表长度判断 if(head==null||head.next==null) { return head; } ListNode midNode=findMidNode(head); ListNode rightFirst=midNode.next; midNode.next=null; ListNode leftHead=sortList(head); ListNode rightHead=sortList(rightFirst); return mergeList(leftHead,rightHead); } /****************** * 查找链表的中间位置 并返回 * 查找思路为使用两个引用 一个一次后移两格(快指针),一个一次后移一格(慢指针) * 当快指针走到结尾时,慢指针正好走到中间位置 * *链表节点个数为偶数2n时,fast走到空时 ,slow在n位置 *链表节点为奇数2n+1时,fast.next为空时,slow在n的位置 *将链表分为两半时,中间节点分到前半部分 **************/ private ListNode findMidNode(ListNode head) { //为空或只有一个节点 if(head==null||head.next==null) { return head; } //定义快节点和慢节点 ListNode fastNode=head.next; ListNode slowNode=head; //直到快节点走到null或者快节点的下一个节点为null while(fastNode!=null&&fastNode.next!=null) { fastNode=fastNode.next.next; slowNode=slowNode.next; } //返回中间位置节点 return slowNode; } /******************** * 链表的二路归并 * 返回连接后的头节点 类似多项式的合并 ********************/ private ListNode mergeList(ListNode first,ListNode second) { //左边为空 直接返回 if(first==null) { return second; } if(second==null) { return first; } ListNode curFirst=first; ListNode curSecond=second; //找寻头节点 使用first存储 second节点用于 if(first.val<second.val) { curFirst=curFirst.next;//指针后移 } else { first=second; curSecond=curSecond.next; } second=first;//已成链的最后一个节点 //循环查找 将节点搭在链上 while(curFirst!=null&&curSecond!=null) { if(curFirst.val<curSecond.val) { second.next=curFirst;//将first连接在节点之后 curFirst=curFirst.next;//first指针后移 指向下一个 } else { second.next=curSecond; curSecond=curSecond.next; } second=second.next;//链尾新加入一个节点 } //判断哪条链遍历完成 if(curFirst==null) second.next=curSecond; else { second.next=curFirst; } //返回头结点 return first; }
while(head!=null){//然后用MergeSort进行排序,排完后在对每个节点进行值覆盖,输出SL节点al.add(head.val);
public ListNode sortList(ListNode head) { if (head == null || head.next == null) { return head; } ListNode mid = gitMid(head); ListNode midNext = mid.next; mid.next = null; return mergeSort(sortList(head), sortList(midNext)); } private ListNode mergeSort(ListNode sortList, ListNode sortList2) { ListNode preHead = new ListNode(0); ListNode curl1 = sortList; ListNode curl2 = sortList2; ListNode cur = preHead; while (curl1 != null && curl2 != null) { if (curl1.val < curl2.val) { cur.next = curl1; curl1 = curl1.next; } else { cur.next = curl2; curl2 = curl2.next; } cur = cur.next; } cur.next = curl1 == null ? curl2 : curl1; return preHead.next; } /* * 快慢指针 */ private ListNode gitMid(ListNode head) { if (head == null || head.next == null) { return head; } ListNode slow = head; ListNode quick = head; while (quick.next != null && quick.next.next != null) { slow = slow.next; quick = quick.next.next; } return slow; }
大家不是用的归并就是用的快速,我这贴个偷巧的解法。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
/**
* Created by 怪兽 on 2018/4/17.
*/
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
public class Solution {
public ListNode sortList(ListNode head) {
if(head == null)
return null;
ArrayList<ListNode> list = new ArrayList<>();
ListNode tmp = head;
while (tmp != null && tmp.next != null) {
list.add(tmp);
tmp = tmp.next;
}
list.add(tmp);
Collections.sort(list, Comparator.comparingInt(o -> o.val));
ListNode node = list.get(0);
for(int i = 1;i < list.size();i++){
node.next = list.get(i);
node = list.get(i);
}
node.next = null;
return list.get(0);
}
}
public class Solution { public ListNode sortList(ListNode head) { //利用归并排序,由于链表的特殊性,不会像数组那样需要额外的线性空间 //1. 首先对于null输入和只有单个节点,直接返回 if (head == null || head.next == null) return head; //2. 利用快慢指针,找到链表的中点 ListNode slow = head; ListNode fast = head; while (fast.next != null && fast.next.next != null) { fast = fast.next.next; slow = slow.next; } //slow为中点,排序后归并返回 ListNode midNext = slow.next; slow.next = null; slow = sortList(midNext); head = sortList(head); return merge(head, slow); } private ListNode merge(ListNode head1, ListNode head2) { ListNode newHead = new ListNode(Integer.MIN_VALUE); ListNode current = newHead; while (head1 != null && head2 != null) { if (head1.val < head2.val) { current.next = head1; head1 = head1.next; } else { current.next = head2; head2 = head2.next; } current = current.next; } if (head1 != null) current.next = head1; if (head2 != null) current.next = head2; return newHead.next; } }
public class Solution {public ListNode sortList(ListNode head) {if(head == null || head.next == null)return head;ListNode slow = head;ListNode fast = head.next;while(fast.next != null && fast.next.next != null){slow = slow.next;fast = fast.next.next;}ListNode rightHead = slow.next;slow.next = null;ListNode left = sortList(head);ListNode right = sortList(rightHead);return mergeList(left,right);}private ListNode mergeList(ListNode left,ListNode right){if(left == null)return right;if(right == null)return left;ListNode result;if(left.val < right.val){result = left;left = left.next;}else {result = right;right = right.next;}ListNode slide = result;slide.next = null;while(left != null && right != null){if(left.val < right.val){slide.next = left;left = left.next;}else {slide.next = right;right = right.next;}slide = slide.next;}if(left != null)slide.next = left;if(right != null)slide.next = right;return result;}}