链表排序
来源:互联网 发布:算法经典书籍 编辑:程序博客网 时间:2024/06/09 23:56
题目
在 O(n log n) 时间复杂度和常数级的空间复杂度下给链表排序。
您在真实的面试中是否遇到过这个题? Yes
样例
给出 1->3->2->null,给它排序变成 1->2->3->null.
解题
尝试快速排序,划分节点不知道怎么找
参考链接
快速排序
找到小于x,找到等于x,找到大于x,三个链表合并
注意:
如果小于x和等于x的在一起考虑,有错误
如:1 3 2
第一次划分 成1 和3 2
3 2 始终 是划分在一起,出现栈溢出
/** * Definition for ListNode. * public class ListNode { * int val; * ListNode next; * ListNode(int val) { * this.val = val; * this.next = null; * } * } */ public class Solution { /** * @param head: The head of linked list. * @return: You should return the head of the sorted linked list, using constant space complexity. */ public ListNode sortList(ListNode head) { // write your code here if(head == null) return head; ListNode sortList = quickSort(head); return sortList; } public ListNode quickSort(ListNode head){ if(head==null || head.next==null) return head; ListNode lowHead = new ListNode(0); ListNode low = lowHead; ListNode highHead = new ListNode(0); ListNode high = highHead; ListNode midHead = new ListNode(0); ListNode mid = midHead; ListNode p = head; int x = p.val; while(p!=null){ if(p.val <x){ low.next = p; low = low.next; }else if(p.val >x){ high.next = p; high = high.next; }else{ mid.next = p; mid = mid.next; } p = p.next; } low.next = null;// 断开 mid.next = null; high.next = null; ListNode l1 = quickSort(lowHead.next); ListNode l2 = quickSort(highHead.next); ListNode merge = concat(l1,midHead.next,l2); return merge; } public ListNode concat(ListNode low,ListNode mid,ListNode high){ ListNode lowLast = getLastNode(low); ListNode midLast = getLastNode(mid); if(low==null){ midLast.next = high; return mid; } lowLast.next = mid; midLast.next = high; return low; } public ListNode getLastNode(ListNode head){ if(head ==null) return head; ListNode last = head; while(last.next!=null){ last = last.next; } return last; }}
上面链接中给了归并排序算法
public ListNode mergeSort(ListNode head){ if(head == null || head.next == null) return head; ListNode mid = findMiddle(head); ListNode right = sortList(mid.next); // 先右边排序 mid.next = null;// 断开 ListNode left = sortList(head); return merge(left, right); } private ListNode merge(ListNode head1, ListNode head2) { ListNode dummy = new ListNode(0); ListNode tail = dummy; while (head1 != null && head2 != null) { if (head1.val < head2.val) { tail.next = head1; head1 = head1.next; } else { tail.next = head2; head2 = head2.next; } tail = tail.next; } if (head1 != null) { tail.next = head1; } else { tail.next = head2; } return dummy.next; } public ListNode findMiddle( ListNode head){ ListNode slow = head; ListNode fast = head; while(fast!=null && fast.next!=null && fast.next.next!=null){ slow = slow.next; fast = fast.next.next; } return slow; }
桶排序
min - max之间的数转化成a - b 之间的方式
一般归一化的方式:
可以发现:min转化成 1 ,max转化成 0
下面需要将其转化到:a-b之间
一般认为是这样转化:
但是还是会发现max转化成最小值,min转化成最大值
桶排序要使较大的数放在大桶号,较小的数放在小桶号
上面等式还需要改变
这样就好了
public class Solution { /** * @param head: The head of linked list. * @return: You should return the head of the sorted linked list, using constant space complexity. */ public ListNode sortList(ListNode head) { // write your code here if(head == null) return head; ListNode sortList = bucketSort(head); return sortList; } public ListNode bucketSort(ListNode head){ if(head == null || head.next == null) return head; int min = getMin(head); min = min>0?min:0; int max = getMax(head); max = max>0?max:0; int N = 14; int a = 0; int b = N-1; ListNode[] bucket = new ListNode[N]; for(int i=0;i<N;i++){ bucket[i] = new ListNode(0); } ListNode p = head; while(p!=null){ int val = p.val; int index = val%N; ListNode pNext = p.next; if(val<0) index =0; else{ index = b - (b-a)*(max - val)/(max - min); } insertList(bucket[index],p); p = pNext; } ListNode sortHead = new ListNode(0); ListNode cur = sortHead; for(int i=0;i<N;i++){ ListNode bk = bucket[i].next; while(bk!=null){ cur.next = bk; cur = cur.next; bk = bk.next; } } return sortHead.next; } public int getMax(ListNode head){ ListNode p = head; int max = p.val; while(p!=null){ max = max<p.val?p.val:max; p = p.next; } return max; } public int getMin(ListNode head){ ListNode p = head; int min = p.val; while(p!=null){ min = min>p.val?p.val:min; p = p.next; } return min; } // 有头节点的插入 public void insertList(ListNode head,int val){ ListNode insertNode = new ListNode(val); insertNode.next =null; ListNode prev = head; // 插入在头 if(prev.next==null){ prev.next = insertNode; return; } // 插入在中间 while(prev.next!=null){ if(prev.next.val<=val){ prev = prev.next; }else{ insertNode.next = prev.next; prev.next = insertNode; return; } } // 插入在末尾 prev.next = insertNode; } // 有头节点的插入 public void insertList(ListNode head,ListNode o){ ListNode insertNode = o; ListNode prev = head; if(prev.next==null){ prev.next = insertNode; prev = prev.next; prev.next =null; return; } int val = insertNode.val; while(prev.next!=null){ if(prev.next.val<=val){ prev = prev.next; }else{ insertNode.next = prev.next; prev.next = insertNode; return; } } // 插入在末尾 prev.next = insertNode; prev = prev.next; prev.next =null; }}
0 0
- 链表排序 归并排序
- 链表排序--选择排序
- 链表排序--快速排序
- 链表排序--归并排序
- 排序3:插入排序(普通插入排序 + 折半插入排序 + 链表插入排序 + 希尔排序)
- LIST排序, Struct排序, qsort排序, STL::LIST sort排序, 链表排序
- 单向链表排序:快速排序和归并排序
- 单向链表排序-归并排序
- 链表排序,使用插入排序,
- 链表排序-直接插入排序
- 链表的一种排序---冒泡排序
- c 链表排序 - 选择排序
- 链表排序之插入排序
- 插入排序进行链表排序
- 优化冒泡排序 & 链表选择排序
- 链表排序之选择排序
- 链表排序之冒泡排序
- 链表排序(归并排序)
- Maven打包可执行Jar的集中方法
- html页面input只许输入数字
- 数论知识点1——快速幂取模-LightOJ 1282
- 大数据
- Cookie 的路径以及 Cookie 域
- 链表排序
- Overriding与Overloading
- 解析网络数据之前先?
- Active Shape Models with Stasm 接口使用
- remove()
- svn中出现红色感叹号
- scrapy 写入json文件
- Android】保存Fragment切换状态
- 代码执行先后整理