将单向链表按某值划分为左边小,中间相等,右边大的形式
题目描述:
给定一个链表,再给定一个整数 pivot,请将链表调整为左部分都是值小于 pivot 的节点,中间部分都是值等于 pivot 的节点, 右边部分都是大于 pivot 的节点。
除此之外,对调整后的节点顺序没有更多要求。
输入描述:
第一行两个整数 n 和 pivot,n 表示链表的长度。
第二行 n 个整数 a i a_i ai 表示链表的节点。
示例1
输入
5 3
9 0 4 5 1
输出
1 0 4 5 9
题解:
法一:如果不考虑调整后的节点顺序,可以用一个节点数组保存各个节点,然后在数组上进行交换。时间复杂度 O ( N ) O(N) O(N),额外空间复杂度为 O ( N ) O(N) O(N)。
法一代码:
# include <bits/stdc++.h>
using namespace std;
struct list_node{
int val;
struct list_node * next;
};
int pivot;
list_node * input_list(void)
{
int n, val;
list_node * phead = new list_node();
list_node * cur_pnode = phead;
scanf("%d%d", &n, &pivot);
for (int i = 1; i <= n; ++i) {
scanf("%d", &val);
if (i == 1) {
cur_pnode->val = val;
cur_pnode->next = NULL;
}
else {
list_node * new_pnode = new list_node();
new_pnode->val = val;
new_pnode->next = NULL;
cur_pnode->next = new_pnode;
cur_pnode = new_pnode;
}
}
return phead;
}
list_node * list_partition(list_node * head, int pivot)
{
//在下面完成代码
if (!head || !head->next) return head;
vector<list_node*> arr;
list_node *p = head;
int len = 0;
while (p) {
arr.push_back(p);
++len;
p = p->next;
}
int l = -1, r = len, now = 0;
while (now != r) {
if (arr[now]->val < pivot) {
++l;
swap(arr[l], arr[now]);
++now;
}
else if (arr[now]->val == pivot) ++now;
else {
--r;
swap(arr[now], arr[r]);
}
}
for (int i = 1; i < len; ++i) {
arr[i - 1]->next = arr[i];
printf("%d ", arr[i - 1]->val);
}
arr[len - 1]->next = NULL;
printf("%d\n", arr[len - 1]->val);
return arr[0];
}
int main ()
{
list_node * head = input_list();
list_partition(head, pivot);
return 0;
}
法二:如果考虑节点的相对顺序,那么上面的做法就是不行的。我们可以考虑将链表拆成三个链表,分别保存节点值小于、等于和大于 pivot 的节点,然后将三个链表合起来就行。时间复杂度 O ( N ) O(N) O(N),额外空间复杂度 O ( 1 ) O(1) O(1)。
法二代码:
# include <bits/stdc++.h>
using namespace std;
struct list_node{
int val;
struct list_node * next;
};
int pivot;
list_node * input_list(void)
{
int n, val;
list_node * phead = new list_node();
list_node * cur_pnode = phead;
scanf("%d%d", &n, &pivot);
for (int i = 1; i <= n; ++i) {
scanf("%d", &val);
if (i == 1) {
cur_pnode->val = val;
cur_pnode->next = NULL;
}
else {
list_node * new_pnode = new list_node();
new_pnode->val = val;
new_pnode->next = NULL;
cur_pnode->next = new_pnode;
cur_pnode = new_pnode;
}
}
return phead;
}
list_node * list_partition(list_node * head, int pivot)
{
//在下面完成代码
if (!head || !head->next) return head;
list_node *lh = NULL, *lt = NULL;
list_node *mh = NULL, *mt = NULL;
list_node *rh = NULL, *rt = NULL;
list_node *p = head;
while (p) {
if (p->val < pivot) {
if (!lh) {
lh = lt = p;
} else {
lt = lt->next = p;
}
} else if (p->val == pivot) {
if (!mh) {
mh = mt = p;
} else {
mt = mt->next = p;
}
} else {
if (!rh) {
rh = rt = p;
} else {
rt = rt->next = p;
}
}
p = p->next;
}
if (lt) {
lt->next = mh;
if (!mt) mt = lt;
}
if (mt) mt->next = rh;
if (rt) rt->next = NULL;
p = lh ? lh : mh ? mh : rh;
head = p;
while (p) {
printf("%d ", p->val);
p = p->next;
}
return head;
}
int main ()
{
list_node * head = input_list();
list_partition(head, pivot);
return 0;
}