给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。
你应当 保留 两个分区中每个节点的初始相对位置。
示例:
输入:head = [1, 4, 3, 2, 5, 2],x = 3
输出:[1, 2, 2, 4, 3, 5]
输入:head = [2, 1],x = 2
输出:[1, 2]
个人解法:
创建一个不含数据的头节点 result ,并用指针 cur 指向,用来存储最终结果
用临时指针 temp 指向给定链表的头节点,进行遍历
在第一次遍历中,比较每个节点的元素值与 x 的大小关系,若小于 x ,则将该节点连接到结果链表的末尾,若大于等于 x ,则将该节点加入到一个 ArrayList 中,每次比较后将当前指针后移一位
也就是说,第一次遍历,将所有小于 x 的节点都以正确的相对位置,连接到了结果链表的末尾,遍历结束后,再按照 ArrayList 中的顺序,将大于等于 x 的节点也连接到结果链表的末尾,为了避免链表出现循环情况,将最后一个节点的 next 置空,最终返回 result.next 即可
public ListNode partition(ListNode head, int x) {
ListNode result = new ListNode(0);
ListNode cur = result;
ListNode temp = head;
ArrayList<ListNode> rest = new ArrayList<>();
while (temp != null) {
if (temp.val < x) {
cur.next = temp;
cur = cur.next;
} else {
rest.add(temp);
}
temp = temp.next;
}
for (int i = 0; i < rest.size(); i++) {
cur.next = rest.get(i);
cur = cur.next;
}
cur.next = null;
return result.next;
}
官方解法:
维护两个链表 small 和 large
small 链表按顺序存储所有小于 x 的节点,large 链表按顺序存储所有大于等于 x 的节点
最后将 small 链表的末尾节点的 next 指向 large 链表的头节点即可
具体做法如下:
创建 smallHead 和 largeHead 节点分别为两个链表的哑节点,从头节点开始遍历链表,判断当前链表的节点值与 x 的大小关系,如果小于就将其连接到 small 链表的末尾,反之连接到 large 链表的末尾
遍历结束后,置空 large 链表末尾节点的 next,并将 small 链表末尾元素的 next 指向 large 链表的第一个含数据的节点,最终返回 smallHead.next 即可
public ListNode partition1(ListNode head, int x) {
ListNode small = new ListNode(0);
ListNode smallHead = small;
ListNode large = new ListNode(0);
ListNode largeHead = large;
while (head != null) {
if (head.val < x) {
small.next = head;
small = small.next;
} else {
large.next = head;
large = large.next;
}
head = head.next;
}
large.next = null;
small.next = largeHead.next;
return smallHead.next;
}