将单向链表按某值划分成左边小、中间相等、右边大的形式
2018-03-03 20:23
561 查看
【题目】
给定一个单向链表的头节点head,节点的值类型是整型,再给定一个整数pivot。实现一个调整链表的函数,将链表调整为左部分都是值小于pivot的节点,中间部分都是值等于pivot的节点,右部分都是值大于pivot的节点。除这个要求外,对调整后的节点顺序没有更多的要求。例如:链表9->0->4->5->1,pivot=3。调整后链表可以是1->0->4->9->5,也可以是0->1->9->5->4。总之,满足左部分都是小于3的节点,中间部分都是等于3的节点(本例中这个部分为空),右部分都是大于3的节点即可。对某部分内部的节点顺序不做要求。
思路:
方法一. 经典做法:准备三个队列,遍历整个链表,将小于、等于和大于pivot的值依次放入三个队列中,再将队列弹出。
方法二. 遍历整个链表,找到第一个小于划分值pivot的数作为一个链表的头部,找到第一个等于划分值pivot的数作为一个链表的头部,找到第一个大于划分值pivot的数作为一个链表的头部。在第二次遍历时,找到一个小于划分值的数就在对应的头部下加上,等于和大于同理。最后,将三块链表收尾相连。注意:边界的处理问题,比如可能没有小于划分值的数,在相连时应当注意。
代码public class Code_12_SmallerEqualBigger {
public static class Node {
public int value;
public Node next;
public Node(int data) {
this.value = data;
}
}
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(nodeArr, pivot);
for (i = 1; i != nodeArr.length; i++) {
nodeArr[i - 1].next = nodeArr[i];
}
nodeArr[i - 1].next = null;
return nodeArr[0];
}
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) {
swap(nodeArr, ++small, index++);
} 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;
}
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;
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;
}
// small and equal reconnect
if (sT != null) {
sT.next = eH;
eT = eT == null ? sT : eT;
}
// all reconnect
if (eT != null) {
eT.next = bH;
}
return sH != null ? sH : eH != null ? eH : bH;
}
public static void printLinkedList(Node node) {
System.out.print("Linked List: ");
while (node != null) {
System.out.print(node.value + " ");
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 = listPartition2(head1, 5);
printLinkedList(head1);
}
}
给定一个单向链表的头节点head,节点的值类型是整型,再给定一个整数pivot。实现一个调整链表的函数,将链表调整为左部分都是值小于pivot的节点,中间部分都是值等于pivot的节点,右部分都是值大于pivot的节点。除这个要求外,对调整后的节点顺序没有更多的要求。例如:链表9->0->4->5->1,pivot=3。调整后链表可以是1->0->4->9->5,也可以是0->1->9->5->4。总之,满足左部分都是小于3的节点,中间部分都是等于3的节点(本例中这个部分为空),右部分都是大于3的节点即可。对某部分内部的节点顺序不做要求。
思路:
方法一. 经典做法:准备三个队列,遍历整个链表,将小于、等于和大于pivot的值依次放入三个队列中,再将队列弹出。
方法二. 遍历整个链表,找到第一个小于划分值pivot的数作为一个链表的头部,找到第一个等于划分值pivot的数作为一个链表的头部,找到第一个大于划分值pivot的数作为一个链表的头部。在第二次遍历时,找到一个小于划分值的数就在对应的头部下加上,等于和大于同理。最后,将三块链表收尾相连。注意:边界的处理问题,比如可能没有小于划分值的数,在相连时应当注意。
代码public class Code_12_SmallerEqualBigger {
public static class Node {
public int value;
public Node next;
public Node(int data) {
this.value = data;
}
}
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(nodeArr, pivot);
for (i = 1; i != nodeArr.length; i++) {
nodeArr[i - 1].next = nodeArr[i];
}
nodeArr[i - 1].next = null;
return nodeArr[0];
}
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) {
swap(nodeArr, ++small, index++);
} 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;
}
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;
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;
}
// small and equal reconnect
if (sT != null) {
sT.next = eH;
eT = eT == null ? sT : eT;
}
// all reconnect
if (eT != null) {
eT.next = bH;
}
return sH != null ? sH : eH != null ? eH : bH;
}
public static void printLinkedList(Node node) {
System.out.print("Linked List: ");
while (node != null) {
System.out.print(node.value + " ");
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 = listPartition2(head1, 5);
printLinkedList(head1);
}
}
相关文章推荐
- Java——将单向链表按某值划分成左边小、中间相等、右边大的形式(进阶问题)
- 将单向链表按某值划分成左边小、中间相等、右边大的形式
- 将单向链表按某个值划分成左边小、中间相等、右边大的形式 Python 版
- 将单向链表按某值划分成左边小、 中间相等、 右边大的形式~迎娶是挺
- 链表问题---将单向链表按某值划分成左边小,中间相等,右边大的形式
- Java——将单向链表按某值划分成左边小、中间相等、右边大的形式(基础问题)
- [链表] - 将单向链表按某值划分成左边小、中间相等、右边大的形式
- 将单向链表按某值划分成左边小,中间相等,右边大
- C++将链表划分为左边小,中间等,右边大于pivotKey的形式
- 把单链表按某值划分成左边小,中间相等,右边大的形式,时间O(n),空间O(1)
- C++链表划分左边小中间等右边大 时间复杂度O(n) 空间复杂度O(1)
- [JS]链表划分给定中间值,小的在左边,大的在右边并保持原排序
- [JS]链表划分给定中间值,小的在左边,大的在右边并保持原排序
- 面试题12 在一个单向链表中 指定一个元素 x 然后将所有小于 x 的元素都放到 x 左边 剩下的元素放到 x 的右边
- 划分一个整形数组,把负数放在左边,零放在中间,正数放在右边
- 将整型数组划分为左右两部分,使左边全为奇数,右边全为偶数.
- 删除单向链表中间的某个结点
- C#字符串操作 取文本左边 取文本右边 取文本中间 取文本中间到List集合 指定文本倒序
- 2016年12月21日学习总结----单向循环链表操作程序(头插,尾插,中间插入,删除,逆序)
- 单向链表中间结点