关键点:
1、利用快排的思想
- 将链表放在数组中;
- 利用荷兰国旗思想将链表进行调整;
- 然后将数组中的链表串联起来 。
2、仅用链表结构
代码:
- 将链表分成三个部分small、equal、big
- 将三个链表串联起来
- 特别注意三个链表都有可能为空
//一、荷兰国旗改进快排 + LinkedList /Node[] /ArrayList实现
//T = O(N) S = O(N)
public static Node partition1(Node head,int pivot) {
if(head == null) return head;
//1、将链表存放在数组里
LinkedList<Node> arr = new LinkedList<Node>();
Node cur = head;
while(cur != null) {
arr.add(new Node(cur.value));
cur = cur.next;
}
//2、将数组进行partition调整
int less = -1;
int more = arr.size();
int i = 0;
while(i != more) {
if(arr.get(i).value < pivot) {
swap(arr,++less,i++);
}else if(arr.get(i).value == pivot) {
i++;
}else {
swap(arr,--more,i);
}
}
//3、将调整后的数组串成链表
for(i = 1;i < arr.size();i++) {
arr.get(i-1).next = arr.get(i);
}
arr.get(arr.size()-1).next = null;
return arr.get(0);
}
public static void swap(LinkedList<Node> arr,int i,int j) {
Node temp = arr.get(i);
arr.set(i, arr.get(j));
arr.set(j, temp);
}
//二、借用链表结构+指针实现
//T = O(N) S = O(1)
public static Node partition2(Node head,int pivot) {
if(head == null) return null;
//1、将链表分成三部分small 、 equal、big
Node sH = null;//small head
Node sT = null;//small tail
Node eH = null;//equal head
Node eT = null;//equal tail
Node bH = null;//big head
Node bT = null;//big tail
Node cur = head;
Node next = null;//记录下一个节点 因为每操作一个节点会将该节点与链表断开
while(cur != null) {
next = cur.next;
cur.next = null;//断开该节点 将该节点连接到相应的部分中
if(cur.value < pivot) {
if(sH == null) {
sH = cur;
sT = cur;
}else {
sT.next = cur;
sT = cur;
}
}else if(cur.value == pivot){
if(eH == null) {
eH = cur;
eT = cur;
}else {
eT.next = cur;
eT = cur;
}
}else {
if(bH == null) {
bH = cur;
bT = cur;
}else {
bT.next = cur;
bT = cur;
}
}
cur = next;
}
//2、将链表三部分连接起来
//注意:每一部分都有可能没有节点
//2.1 链接small和equal部分
if(sT != null) {
sT.next = eH;
eT = eT==null ? sT : eT;
}
//2.2前面和big部分链接
if(eT != null) {
eT.next = bH;
}
return sH !=null ? sH : eH != null ? eH : bH;
}