码字不易,记得点赞加收藏
题目:给定一个无序单链表的头节点head,实现单链表的选择排序。
要求:额外空间复杂度为O(1)。
解答:既然要求额外空间复杂度为O(1),就不能把链表装进数组等容器中排序,排好序之后再重新连接。选择排序是从未排序的部分中找到最小值,然后放在排好序部分的尾部,逐渐将未排序的部分缩小,最后全部变成排好序的部分。
1.开始时默认为整个链表都是未排序的状态,对于找到的第一个最小值节点,肯定是整个链表的最小值节点,将其设置为新的头节点newHead。
2.每次在未排序的部分中找到最小值节点,然后把这个节点从未排序的节点中删除,当然删除的过程应当保证未排序的部分的链表在结构上不至于断开,例如2->1->3,删除1节点后,链表变成2->3,这就是我们应该找到删除节点的前一个节点。
3.把删除的节点(也就是每次的最小值节点)连接到排好序部分的链表尾部。
4.全部过程处理完后,整个链表已经是有序,返回newHead
和选择排序一样,如果链表的长度为N,时间复杂度为O(N^2),额外空间复杂度为O(1)
public static class Node{
public int value;
public Node next;
public Node(int data){
this.value = data;
}
}
public static Node selectionSort(Node head){
// 排序部分尾部
Node tail = null;
//未排序部分头部
Node cur = head;
//最小节点的前一个节点
Node smallPre = null;
//最小的节点
Node small = null;
while (cur != null){
small = cur;
smallPre = getSmallestPreNode(cur);
if(smallPre != null){
small = smallPre.next;
smallPre.next = small.next;
}
cur = cur == small ? cur.next : cur;
if(tail == null){
head = small;
}else{
tail.next = small;
}
tail = small;
}
return head;
}
public static Node getSmallestPreNode(Node head){
Node smallPre = null;
Node small = head;
Node pre = head;
Node cur = head.next;
while (cur != null){
if(cur.value < small.value){
smallPre = pre;
small = cur;
}
pre = cur;
cur = cur.next;
}
return smallPre;
}