题目要求
将一个链表,按照某一个标准,小于该标准的放置在链表的前面,等于的放置在中间,大于的放置在后面,不要求稳定性。
实现思路:
在前面第十五题:荷兰国旗问题中,我们已经解决了类似的问题,我们实现的思路是,遍历整个链表,然后将每一个节点放置到数组中去,然后使用荷兰国旗问题的思路来解决,在数组荷兰国旗话之后,在遍历数组,将数组转为链表,在笔试中,我们应该使用这样的解决方案。
代码实现:
package com.isea.brush;
/**
* 将一个链表按照与pivot的关系,分成小于,等于,大于三部分
* 实现思路:将链表遍历一遍,放入到Node类型的数组中,按照解决荷兰国旗的问题来解决
* 最后将数组重新组建成为一个链表,返回
*/
public class SmallEqualBig {
public static class Node {
private int data;
private Node next;
public Node(int value) {
this.data = value;
}
}
public static Node smallEqualBig(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];
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 less = -1;
int more = nodeArr.length;
int index = 0;
while (index < more) {
if (nodeArr[index].data < pivot) {
swap(nodeArr, ++less, index++);
} else if (nodeArr[index].data > pivot) {
swap(nodeArr, --more, index);
} else {
index++;
}
}
}
private static void swap(Node[] arr, int i, int j) {
/* arr[i].data = arr[i].data ^ arr[j].data;
arr[j].data = arr[i].data ^ arr[j].data;
arr[i].data = arr[i].data ^ arr[j].data;*/
int tem = arr[i].data;
arr[i].data = arr[j].data;
arr[j].data = tem;
}
public static void printLinkedList(Node node) {
System.out.print("Linked List: ");
while (node != null) {
System.out.print(node.data + " ");
node = node.next;
}
System.out.println();
}
public static void main(String[] args) {
Node head1 = new Node(7);
head1.next = new Node(9);
head1.next.next = new Node(1);
head1.next.next.next = new Node(8);
head1.next.next.next.next = new Node(5);
head1.next.next.next.next.next = new Node(2);
head1.next.next.next.next.next.next = new Node(5);
printLinkedList(head1);
// head1 = listPartition1(head1, 4);
head1 = smallEqualBig(head1, 5);
printLinkedList(head1);
}
}
这里,我们对于问题进一步升级:
保持原来链表中元素的稳定性,不能打破原来的数据的顺序,比如:9->0->4->5->1 ,排序的标准是pivot=3,输出之后是
0->1->9->4->5。另外要求:假如链表的长度是N,时间复杂度是O(N),额外空间复杂度是O(1)
代码实现:
package com.isea.brush;
/**
* 将一个链表按照与pivot的关系,分成小于,等于,大于三部分,要求时间复杂度是O(N),额外空间复杂度是O(1),做到稳定性
* 实现思路:第一次遍历链表,找到链表中第一个小于,等于,大于pivot的元素,分别赋值给less,equal,more
* 第二次遍历链表,将小于pivot的元素接在less链表上,等于pivot的元素接在equal链表上,大于pivot的元素接在more链表上
* 最后在将less,equal,more链表合并,返回头节点。下面的代码中将两次循环放在了一起。
*/
public class SmallEqualBig {
public static class Node {
private int data;
private Node next;
public Node(int value) {
this.data = value;
}
}
public static Node smallEqualBig(Node head, int pivot) {
Node lessHead = null;
Node lessEnd = null;
Node equalHead = null;
Node equalEnd = null;
Node moreHead = null;
Node moreEnd = null;
Node next = null; // save the next node
// 遍历链表,将链表分发到三个子链表中
while (head != null) {
next = head.next;
head.next = null;
if (head.data < pivot) {
if (lessHead == null) {
lessHead = head;
lessEnd = head;
} else {
lessEnd.next = head;
lessEnd = head;
}
} else if (head.data == pivot) {
if (equalHead == null) {
equalHead = head;
equalEnd = head;
} else {
equalEnd.next = head;
equalEnd = head;
}
} else {
if (moreHead == null) {
moreHead = head;
moreEnd = head;
} else {
moreEnd.next = head;
moreEnd = head;
}
}
head = next;
}
// small and equal reconnected
if (lessEnd != null) {
lessEnd.next = equalHead;
equalEnd = equalHead == null ? lessEnd : equalEnd;
}
// all reconnected
if (equalEnd != null) {
equalEnd.next = moreHead;
}
return lessHead != null ? lessHead : equalHead != null ? equalHead : moreHead;
}
public static void printLinkedList(Node node) {
System.out.print("Linked List: ");
while (node != null) {
System.out.print(node.data + " ");
node = node.next;
}
System.out.println();
}
public static void main(String[] args) {
Node head1 = new Node(7);
head1.next = new Node(9);
head1.next.next = new Node(1);
head1.next.next.next = new Node(8);
head1.next.next.next.next = new Node(5);
head1.next.next.next.next.next = new Node(2);
head1.next.next.next.next.next.next = new Node(5);
printLinkedList(head1);
// head1 = listPartition1(head1, 4);
head1 = smallEqualBig(head1, 5);
printLinkedList(head1);
/**
* Linked List: 7 9 1 8 5 2 5
* Linked List: 1 2 5 5 7 9 8
*/
}
}