给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
1、暴力方法,先将链表的值存放到一个数组中,然后对这个数组进行快速排序,然后只需要遍历这个数组,将对应的数组的值赋值给链表的节点即可。但是这样做的话需要开辟空间给数组。 对应的代码:
class Solution {
public ListNode sortList(ListNode head) {
ListNode cur = head;
List<Integer> list = new ArrayList<Integer>();
while(cur != null){
list.add(cur.val);
cur = cur.next;
}
int[] arr = new int[list.size()];
int i;
for(i = 0; i < arr.length; i++){
arr[i] = list.get(i);
}
sort(arr,0,arr.length - 1);
cur = head;
for(i = 0; i < arr.length; i++){
cur.val = arr[i];
cur = cur.next;
}
return head;
}
public void sort(int[] arr,int low,int high){
if(low < high){
int pivot = getPivot(arr,low,high);
System.out.println(pivot);
int i = low,j = high - 1;
while(i < j){
while(i < j && arr[++i] <= pivot);
while(i < j && arr[--j] >= pivot);
if(i >= j)
break;
swap(arr,i,j);
}
arr[high - 1] = arr[i];
arr[i] = pivot;
sort(arr,low,i - 1);
sort(arr,i + 1,high);
}
}
public void swap(int[] arr,int i,int j){
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
public int getPivot(int[] arr,int low,int high){
int mid = (low + high) / 2;
if(arr[low] > arr[mid])
swap(arr,low,mid);
if(arr[low] > arr[high])
swap(arr,low,high);
if(arr[mid] > arr[high])
swap(arr,mid,high);
swap(arr,mid,high - 1);
return arr[high - 1];
}
}
运行结果:
2、利用归并排序 但是对于链表来说,利用归并排序,首先我们需要获取中间的节点。怎么实现这一步呢?利用快慢指针就好了,快指针走的是慢指针的2被,此时当快指针走完整个链表的时候,那么慢指针就是终点的位置了。然后进入递归,当链表为空或者只有一个节点的时候,那么就结束递归,进行合并的操作了。
对应的代码:
class Solution {
public ListNode sortList(ListNode head) {
return mergeSort(head);
}
public ListNode mergeSort(ListNode head){
if(head != null && head.next != null){
ListNode cur,pre,tmp;
pre = head;
cur = head;
while(cur != null && cur.next != null && cur.next.next != null){
pre = pre.next;
cur = cur.next.next;
}
tmp = pre.next;
pre.next = null;
ListNode left = mergeSort(head);
ListNode right = mergeSort(tmp);
ListNode sorted = merge(left,right);
return sorted;
}else{
return head;
}
}
public ListNode merge(ListNode head1,ListNode head2){
ListNode cur1,cur2,pre,tmp;
ListNode root = new ListNode(0);
root.next = head1;
pre = root;
cur1 = head1;
cur2 = head2;
while(cur1 != null && cur2 != null){
if(cur1.val < cur2.val){
cur1 = cur1.next;
}else{
tmp = cur2.next;
cur2.next = pre.next;
pre.next = cur2;
cur2 = tmp;
}
pre = pre.next;
}
if(cur2 != null)
pre.next = cur2;
return root.next;
}
}
运行结果:
但是考虑到ListNode是一个引用类型,那么在方法中对形参修改,会影响到实际的参数,所以原来的代码是这样的,但是结果是错误的,如果有大佬明白错误的原因的话,请指正。
public ListNode sortList(ListNode head) {
mergeSort(head);
return head;
}
public void mergeSort(ListNode head){
if(head != null && head.next != null){
ListNode cur,pre,tmp;
pre = head;
cur = head;
while(cur != null && cur.next != null && cur.next.next != null){
pre = pre.next;
cur = cur.next.next;
}
tmp = pre.next;
pre.next = null;
mergeSort(head);
mergeSort(tmp);
ListNode sorted = merge(head,tmp);
}
}
public void merge(ListNode head1,ListNode head2){
ListNode cur1,cur2,pre,tmp;
ListNode root = new ListNode(0);
root.next = head1;
pre = root;
cur1 = head1;
cur2 = head2;
while(cur1 != null && cur2 != null){
if(cur1.val < cur2.val){
cur1 = cur1.next;
}else{
tmp = cur2.next;
cur2.next = pre.next;
pre.next = cur2;
cur2 = tmp;
}
pre = pre.next;
}
if(cur2 != null)
pre.next = cur2;
head1 = root.next;
}
|