Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x.
You should preserve the original relative order of the nodes in each of the two partitions.
For example,
Given 1->4->3->2->5->2 and x = 3,
return 1->2->2->4->3->5.
Version1: Using extra memory space.
Analysis: It's straightforward. Just create two lists, small and large. Scan the original list one time and build small and large appropriately. Finally, concatenate small and large and return small.next as the result.
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode partition(ListNode head, int x) {
ListNode large = new ListNode(0);
ListNode curl = large;
ListNode small = new ListNode(0);
ListNode curs = small;
ListNode current = head;
if(head == null) {
return head;
}
if(current.val >= x) {
curl.next = current;
curl = curl.next;
}
else if(current.val < x) {
curs.next = current;
curs = curs.next;
}
while(current.next != null) {
current = current.next;
if(current.val >= x) {
curl.next = current;
curl = curl.next;
}
else if(current.val < x) {
curs.next = current;
curs = curs.next;
}
}
curs.next = large.next;
curl.next = null;
return small.next;
}
}
Analysis: First, scan the original list. Let the last node that smaller than x to be the begin node of insertion, while choose the first node that equal or larger than x to be the end node of insertion. After that, scan the rest of the original list, insert into the range defined by the first step if needed. Typically, four pointers are needed, i.e. current, previous, insertBegin and insertEnd. Moreover,newhead, which points to head, is a "fake head" in case that the head of the original list is changed during the operation. In terms of the final result, newhead.next is always returned. Specifically, if the first node is equal or greater than x, the range defined by insertBegin and insertEnd pointers should just between newhead and the first node. However, if the first node is smaller than x, everything is just the same as usual.
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode partition(ListNode head, int x) {
ListNode newhead = new ListNode(0);
newhead.next = head;
ListNode current = newhead.next;
ListNode previous = null;
ListNode insertBegin = newhead;
ListNode insertEnd = null;
if(head == null) {
return head;
}
while(current != null) {
if(insertEnd == null) {
if(current.val >= x) {
insertEnd = current;
}
else {
insertBegin = insertBegin.next;
}
previous = current;
current = current.next;
}
else {
if(current.val < x) {
insertBegin.next = current;
insertBegin = current;
previous.next = current.next;
current.next = insertEnd;
current = previous.next;
}
else {
previous = current;
current = current.next;
}
}
}
return newhead.next;
}
}
Update 02/03/2014:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode partition(ListNode head, int x) {
if(head==null || head.next==null) return head; // edge case
ListNode newhead = new ListNode(0);
newhead.next = head;
ListNode smaller = newhead; // points to the last node that smaller than x
while(smaller.next!=null && smaller.next.val<x) {
smaller = smaller.next;
}
if(smaller.next==null) return newhead.next; // all nodes are smaller than x
ListNode pre = smaller.next;
ListNode cur = pre.next;
while(cur != null) {
if(cur.val < x) {
pre.next = cur.next;
cur.next = smaller.next;
smaller.next = cur;
smaller = cur;
cur=pre.next;
}
else {
pre = cur;
cur = cur.next;
}
}
return newhead.next;
}
}

本文详细介绍了两种链表分区算法:使用额外内存空间的方法和原地分区的方法。通过实例演示如何将链表按照指定值x进行分割,确保所有小于x的节点位于前面,大于等于x的节点位于后面,同时保持原始相对顺序不变。
320

被折叠的 条评论
为什么被折叠?



