1、数组
题目没要求稳定性,利用分治算法求解
void partition(std::vector<int>& arr, int val)
{
if (arr.size() < 2)
{
return;
}
int left = 0, right = arr.size() - 1;
//遍历一遍,使小于等于val在左,大于val的在右
while (left < right)
{
while (left < right && arr[left] <= val)
{
++left;
}
while (left < right && arr[right] > val)
{
--right;
}
//交换left和right所在位置的数值
swap(arr[left], arr[right]);
}
//此时必然left=right,并且所在位置为第一个>val的值
//令left=0,左侧重新遍历,找到等于val的值和right交换
left = 0;
while (left < right)
{
//right指针负责寻找从右往左第一个小于val的值
while (arr[right] >= val)
{
--right;
}
//left指针负责寻找从左往右第一个=val的值
while (arr[left] != val)
{
++left;
}
if (left < right)
{
swap(arr[left], arr[right]);
}
}
}
复杂度分析:
时间复杂度O(N),额外空间复杂度O(1),但是不具有稳定性。
2、链表
对链表而言,比较好的解决方法是利用链表特性,将原链表按照小于val,等于val,大于val分成3个链表,再进行组合。但是如果不熟练的情况下需要多多调试
void partitionN(Node *hd, int val)
{
Node * s_head = nullptr; //保存小于val头结点
Node * s_end = nullptr; //保存小于val尾结点
Node * e_head = nullptr; //保存等于val头结点
Node * e_end = nullptr; //保存等于val尾结点
Node * b_head = nullptr; //保存大于val头结点
Node * b_end = nullptr; //保存大于val尾结点
//遍历一遍,将链表根据小于val,等于val,大于val拆分成3个链表
while (nullptr != hd)
{
if (hd->data < val)
{
if (nullptr == s_head)
{
s_head = hd;
s_end = hd;
}
else
{
s_end->next = hd;
s_end = hd;
}
}
else if(hd->data > val)
{
if (nullptr == b_head)
{
b_head = hd;
b_end = hd;
}
else
{
b_end->next = hd;
b_end = hd;
}
}
else
{
if (nullptr == e_head)
{
e_head = hd;
e_end = hd;
}
else
{
e_end->next = hd;
e_end = hd;
}
}
hd = hd->next;
}
//将3个链表尾的next指针置空,避免成环
if (nullptr != s_end) s_end->next = nullptr;
if (nullptr != e_end) e_end->next = nullptr;
if (nullptr != b_end) b_end->next = nullptr;
//将3个链表组合成一个链表返回
if (nullptr != s_head)
{
hd = s_head;
s_end->next = b_head;
}
if(nullptr != e_head)
{
if (nullptr == hd)
{
hd = e_head;
}
else
{
s_end->next = e_head;
}
e_end->next = b_head;
}
if (nullptr == hd)
{
hd = b_head;
}
}
复杂度分析:
时间复杂度O(N),额外空间复杂度O(1),且具有稳定性。