题目描述
给定一个单项链表的头结点head,节点的值类型是整型,再给定一个整数pivot。实现一个调整链表的函数,将链表的左边都是值小于pivot的节点,右边都是值大于pivot的节点。
例如:
9-->0-->4-->5-->1 pivot = 3
输出:
1-->0-->4-->9-->5 也可以是
0-->1-->9-->5-->4
思路
此题解法还是使用【快排/芬兰国旗】解决问题,区别在于这是链表,要先将链表转换成数组。
public static class Node {
int val;
Node next;
public Node(int data) {
this.val = data;
}
}
public static Node ListPartition1(Node head, int pivot) {
if (head == null) {
return null;
}
Node cur = head;
// 链表转换成数组
int i = 0;
while (cur != null) {
i++;
cur = cur.next;
}
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 static void arrPartition(Node[] nodeArr, int pivot) {
int small = -1;
int big = nodeArr.length;
int index = 0;
while (index != big) {
if (nodeArr[index].val < pivot) {
swap(nodeArr, ++small, index++);
} else if (nodeArr[index].val == pivot) {
index++;
} else {
swap(nodeArr, --big, index);
}
}
}
private static void swap(Node[] nodeArr, int i, int index) {
Node temp = nodeArr[i];
nodeArr[i] = nodeArr[index];
nodeArr[index] = temp;
}
进阶
新增要求
- 左中右三个部分也要进行排序
- 时间复杂度为O(N),空间复杂度为O(1)
显然上述的解决方案不是稳定的,空间复杂度为O(N)
思路:
左中右三个部分要求排序,可以将数值分为三个部分。小的部分,等于的部分,大于的部分。
从头到位遍历链表,对每个链表和pivot进行比较,小的放在小的部分,大的放在大的部分。那么如何存放?
需要每个部分维护两个节点,头结点和尾结点。
- 插入为空的时候,头结点尾结点都是插入的节点
- 头结点不为空的时候,尾结点的next指向插入节点,再移动尾结点到最后一个节点。
如此三个部分的排序就是稳定的了。最后一步时进行三个部分的合并,最后就得到排序后的链表。
代码实现如下:
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.val < pivot) {
if (sH == null) {
sH = head;
sT = head;
} else {
sT.next = head;
sT = head;
}
} else if (head.val == 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;
}