86. 分隔链表
- 题目难度:中等
- 题目链接:分隔链表
一、题目描述
给你一个链表的头结点 head和一个特定的值 x,请你对链表进行分隔,使得所有 小于x的节点都出现在 大于等于x的节点之前。
你应当 保留 两个分区中每个节点的初始相对位置。
大白话解释
对链表进行一次遍历操作,小于x的移动到 分隔节点 的左侧,大于等于x节点的移动到 分隔节点的右侧(包含分隔节点),注意:不要改变每个节点的初始相对位置。其中 分隔节点 是 第一个大于等于 x的节点。
示例说明
题目给定 x = 3,则 分隔节点 = 4(链表中第一个大于等于 3 的节点)
二、算法实现
实现思路
- 定义一个新的节点
monitor,其中monitor.next指向给定链表的头结点 - 定义
ListNode curr指向给定链表的头结点 - 定义
ListNode currLeft指向monitor节点,表示curr节点的前驱节点 - 定义
ListNode seprateNode = null用于表示分隔节点 - 定义
ListNode seprateNodeLeft = monitor表示 分隔节点的前驱节点 - 判断
curr != null- 如果
curr.val < x- 如果
seprateNode = null,表示curr节点之前的节点都是 小于x的,只需要移动curr,currLeft,seprateNodeLeft指向下一个节点即可 - 如果
seperateNode != null,表示已经找到了分隔节点,需要将当前节点移动到 分隔节点 的左侧
- 如果
- 如果
curr.val >= x- 如果
seprateNode = null则表示当前节点是 分隔节点,此时seprateLeft无需移动了,只需要将curr,currLeft移动到下一个节点即可 - 如果
seprateNode != null,则表示curr节点已经位于分隔节点的右半区,无需节点交换,只需要将curr,currLeft移动到下一个节点即可
- 如果
- 如果
- 重复步骤6,直到
curr = null结束遍历链表
算法实现
public ListNode partition(ListNode head,int x){
if(null == head){
return null;
}
//# 定义新节点,指向head
ListNode monitor = new ListNode(-1,head);
//# 定义当前节点
ListNode curr = head;
//# 定义当前节点前驱节点
ListNode currLeft = monitor;
//# 定义分隔节点
ListNode seprateNode = null;
//# 定义分隔节点的前驱节点
ListNode seprateLeft = monitor;
while(null != curr) {
//# 分隔节点不为空,且当前节点小于x
if(curr.val < x && null != seprateNode) {
currLeft.next = curr.next;
curr.next = seprateNode;
seprateLeft.next = curr;
curr = currLeft.next;
seprateLeft = seprateLeft.next;
continue;
}
//# 找到分隔节点
if(null == seprateNode && curr.val >= x){
seprateNode = curr;
}
//# 移动到下一个节点
curr = curr.next;
currLeft = currLeft.next;
//# 如果分隔节点为空,则一直移动分隔节点的前驱节点,直达找到分隔节点后就不再移动
if(null == seprateNode) {
seprateLeft = seprateLeft.next;
}
}
return monitor.next;
}