將單向鏈表按某值劃分成左邊小、 中間相等、 右邊大的形式
【 題目】 給定一個單鏈表的頭節點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;
}