赞
踩
leetcode刷了9题了,一直没有在博客上面记录一下,发现做完一题忘了一题所以今天开始做一道记一道。
首先这个方法肯定不满足题目要求的常数级空间复杂度,但是还是从这里入手,因为算法太渣了。。。。
链表的排序要比数组排序难,主要是链表的断链还有重新建立连接。递归需要的时间复杂度为递归的深度为logn
递归排序的思想很简单,先把递归的把左面和右面排好序然后在merge
代码分为两个部分
//链表排序 要求nlogn public class leetcode148 { public static class ListNode{ public int val; public ListNode next; public ListNode( int val){ this.val = val; } } //排序cut部分 public static ListNode mergeSort(ListNode head){ if(head==null||head.next==null){ return head; } ListNode slow = head; ListNode quick = head.next; while(quick!=null&&quick.next!=null){ slow = slow.next; quick = quick.next.next; } ListNode tmp = slow.next; slow.next = null; // printList(head); // printList(tmp); head = mergeSort(head); tmp = mergeSort(tmp); return merge(head,tmp); } //合并部分 private static ListNode merge(ListNode head, ListNode tmp) { ListNode p1 = head; ListNode p2 = tmp; ListNode tempH = new ListNode(0); ListNode h = tempH; while(p1!=null&&p2!=null){ if(p1.val<p2.val){ h.next = p1; h = p1; p1=p1.next; }else{ h.next = p2; h = p2; p2=p2.next; } } if(p1!=null){ h.next = p1; } if(p2!=null){ h.next = p2; } // printList(tempH.next); return tempH.next; } //打印链表 public static void printList(ListNode head){ ListNode p = head; while(p!=null){ System.out.print(p.val+"->"); p=p.next; } System.out.println(); } public static void main(String[] args) { ListNode a = new ListNode(9); a.next= new ListNode(1); a.next.next = new ListNode(7); a.next.next.next = new ListNode(3); a.next.next.next.next = new ListNode(5); a.next.next.next.next.next = new ListNode(2); printList(a); ListNode head = mergeSort(a); printList(head); } }
如果要求空间复杂度为O(1)的话就不能用递归来排序了,只能用迭代的方式
先1个1个合并然后2个2个合并,结束条件为合并的个数大于等于链表长度
代码主要是控制两个循环
cut操作可以将链表截断前n长度并返回后面的部分
cut操作可能size大小比链表长度要大,所以要在循环里判断一下
dummyhead的用处:
每轮cur都从新指向头结点,所以定义一个虚拟的头结点,这样很方便就能找到新的结点(开始代码写错了,写的是cur=head,但是head已经被排在后面了)
因为头结点会变化,定义一个虚拟的头结点代替头结点的指针。
/*merge 和 数据结构 在上面有*/ //不用递归的归并排序 public static ListNode mergeSort2(ListNode head){ if(head==null||head.next==null){ return head; } //先求链表的长度 int length = 0; ListNode p = head; while(p!=null){ p=p.next; length++; } ListNode dummyHead = new ListNode(Integer.MIN_VALUE); dummyHead.next = head; //迭代控制每次合并的size大小 for(int size=1;size<=length;size <<=1){ //不能用head头结点 head头结点已经变化到末尾了 ListNode cur = dummyHead.next; ListNode tail = dummyHead; //按size大小合并一轮 while(cur!=null){ ListNode left = cur; ListNode right = cut(left,size); cur = cut(right,size); tail.next = merge(left,right); //tail指针指向最后一个结点可以连接merge完的链表 while(tail.next!=null){ tail=tail.next; } } //printList(dummyHead.next); } return dummyHead.next; } //切断链表的n个结点 然后返回剩余部分的head public static ListNode cut(ListNode head,int size){ if(head==null){ return null; } ListNode cur = head; while(--size!=0&&cur.next!=null){ cur = cur.next; } ListNode p = cur.next; cur.next = null; return p; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。