将单向链表按某值划分成左边小、 中间相等、 右边大的形式
【 题目】 给定一个单链表的头节点head, 节点的值类型是整型, 再给定一个整
数pivot。 实现一个调整链表的函数, 将链表调整为左部分都是值小于pivot的
节点, 中间部分都是值等于pivot的节点, 右部分都是值大于pivot的节点。
【 进阶】 在实现原问题功能的基础上增加如下的要求
【 要求】 调整后所有小于pivot的节点之间的相对顺序和调整前一样
【 要求】 调整后所有等于pivot的节点之间的相对顺序和调整前一样
【 要求】 调整后所有大于pivot的节点之间的相对顺序和调整前一样
【 要求】 时间复杂度请达到O(N), 额外空间复杂度请达到O(1)。
笔试用:变成数组,数组上partition,然后再返回链表
public static Node listPartition1(Node head, int pivot) {
if (head == null) {
return head;
}
//变成数组
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数组Partition
arrPartition(nodeArr, pivot);
//变成链表
for (i = 1; i != nodeArr.length; i++) {
nodeArr[i - 1].next = nodeArr[i];
}
nodeArr[i - 1].next = null;
return nodeArr[0];//返回链表的head
}
public static void arrPartition(Node[] nodeArr, int pivot) {
int small = -1;
int big = nodeArr.length;
int index = 0;
while (index != big) {
if (nodeArr[index].value < pivot) {//如果小于p,
swap(nodeArr, ++small, index++);//首先交换small和index的位置,然后各自+1,表示
} else if (nodeArr[index].value == pivot) {
index++;
} else {
swap(nodeArr, --big, index);
}
}
}
public static void swap(Node[] nodeArr, int a, int b) {
Node tmp = nodeArr[a];
nodeArr[a] = nodeArr[b];
nodeArr[b] = tmp;
}
面试:
6个指针 Head tail equal,依次遍历原链表,注意边界连接问题
链表if的时候很多是为了next不出错,
if (sT != null) {//如果有小于区域
sT.next = eH;不用管eH是什么,就算是null这句话也是对的。
public static Node listPartition2(Node head, int pivot) {
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 next = null; // save next node 遍历用一个节点~ ~ ~
// every node distributed to three lists
while (head != null) {
//链表的遍历 就是这样
next = head.next;//先记录原先的下一个的环境
head.next = null;//因为涉及到链表的重连,原先的next结构要在新的里面初始化成null,所以需要先null
if (head.value < pivot) {
if (sH == null) {
sH = head;
sT = head;
} else {
sT.next = head;//老的 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;//遍历
}
// small and equal reconnect
//边界问题出错,就是next调用的时候出错,所以这里就是先做了if
if (sT != null) {//如果有小于区域
sT.next = eH;//如果有等于区域eT=eT,如果没有等于区域但是有小于区域eT=sT
eT = eT == null ? sT : eT;//下一步,谁去连eh,谁就变成eT
}//上面的eT很巧妙~ ~ ~如果没有小于区域也没有等于区域,也就是上下if都没有跑,此时的eT就是eT,没变。
// all reconnect
if (eT != null) {//就是如果有小于或等于的区域
eT.next = bH;
}
//如果sh存在就是sh,如果不存在但是存在eh就选eh,否则就选bh返回
return sH != null ? sH : eH != null ? eH : bH;
}