在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;}}