给定一个单向链表的头节点head,节点的值类型是整数,在给定一个pivot.实现一个调整链表的函数,将链表调整为左部分都是小于pivot的节点,中间部分都是值等于pivot的节点,右部分是值大于pivot的节点。
要求1:调整后每部分的节点从左到右的顺序与原链表中节点的先后顺序一致。
要求2:如果链表长度为N,时间复杂度达到O(N),空间复杂度达到O(1).
package com.javause.Algorithm.divideNodeList;
import org.junit.Test;
/**
* 将单向链表按某值划分成左边小,中间相等,右边大的形式
*
* @author 2017-kxd
*
*/
public class DivideNodeList {
/**
* 普通方法,将链表所有的节点放入一个额外的数组,然后统一调整位置
*
* O(n),时间复杂度O(n)
*/
public class Node {
public int value;
public Node next;
public Node(int data) {
this.value = data;
}
}
public Node listPartition1(Node head, int pivot) {
if (head == null) {
return head;
}
Node cur = head;
int i = 0;
while (cur != null) {
cur = cur.next;
i++;
}
Node[] nodeArr = new Node[i];
i = 0;
cur = head;
for (i = 0; i != nodeArr.length; i++) {
nodeArr[i] = cur;
cur = cur.next;
}
arrPartition(nodeArr, pivot);
for (i = 1; i != nodeArr.length; i++) {
nodeArr[i - 1].next = nodeArr[i];
}
nodeArr[i - 1].next = null;
return nodeArr[0];
}
private void arrPartition(Node[] nodeArr, int pivot) {
int small = -1;
int big = nodeArr.length;
int index = 0;
while (index != big) {
if (nodeArr[index].value < pivot) {
swap(nodeArr, ++small, index++);
} else if (nodeArr[index].value == pivot) {
index++;
} else {
swap(nodeArr, --big, index);
}
}
}
public void swap(Node[] nodeArr, int a, int b) {
Node tmp = nodeArr[a];
nodeArr[a] = nodeArr[b];
nodeArr[b] = tmp;
}
public void test() {
Node node1 = new Node(9);
Node node2 = new Node(0);
Node node3 = new Node(4);
Node node4 = new Node(5);
Node node5 = new Node(1);
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
Node cur = listPartition1(node1, 3);
while (cur != null) {
System.out.println(cur.value);
cur = cur.next;
}
}
}
package com.javause.Algorithm.divideNodeList;
import org.junit.Test;
/**
* 将链表按某个值分割后,保持左中右三部分都保存原来的顺序, 时间复杂度为O(n),空间复杂度为O(1)
*/
public class DivideNodeList2 {
public class Node {
public int value;
public Node next;
public Node(int data) {
this.value = data;
}
}
public static Node listPartition2(Node head, int pivot) {
Node sH = null; // 小的头
Node sT = null;// 小的尾
Node eH = null;
Node eT = null;
Node bH = null;// 大的头
Node bT = null;// 大的尾
Node next = null; // 保存下一个节点
// 对所有节点进行分割
while (head != null) {
next = head.next;
head.next = null;
if (head.value < pivot) {
if (sH == null) {
sH = head;
sT = head;
} else {
sT.next = head;
sT = head;
}
} else if (head.value == pivot) {
if (eH == null) {
eH = head;
eT = head;
} else {
eT.next = head;
eT = head;
}
} else {
if (bH == null) {
bH = head;
bT = head;
} else {
bT.next = head;
bT = head;
}
}
head = next;
}
// 小的部分和相等部分重连
if (sT != null) {
sT.next = eH;
eT = eT == null ? sT : eT;
}
// 所有的重新连接
if (eT != null) {
eT.next = bH;
}
return sH != null ? sH : eH != null ? eH : bH;
}
public void test() {
Node node1 = new Node(7);
Node node2 = new Node(9);
Node node3 = new Node(1);
Node node4 = new Node(8);
Node node5 = new Node(5);
Node node6 = new Node(2);
Node node7 = new Node(5);
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
node5.next = node6;
node6.next = node7;
Node cur = listPartition2(node1, 5);
while (cur != null) {
System.out.println(cur.value);
cur = cur.next;
}
}
}