链表分割_牛客题霸_牛客网 (nowcoder.com)
链表去做的话,可以分为带哨兵位和不带哨兵位两种,但是不带哨兵位会更麻烦一些,更容易出现空指针问题。
这里两种思路都是:将小于x的结点尾插到less链表中,将大于x的结点尾插到greater链表中,最终再将lesstail指向greaterhead。
不带哨兵位:
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
#include <cstddef>
class Partition {
public:
ListNode* partition(ListNode* pHead, int x) {
// write code here
if(pHead == NULL) return NULL;//空链表返回空
if(pHead -> next == NULL) return pHead;
ListNode* lesshead = NULL, * lesstail = NULL;
ListNode* greaterhead = NULL, * greatertail = NULL;
ListNode* cur = pHead, *next = pHead -> next;
while (cur)
{
if(cur->val < x)
{
if (lesstail == NULL)
{
cur -> next = NULL;
lesshead = lesstail = cur;
}
else
{
cur -> next = NULL;
lesstail -> next = cur;
lesstail = cur;
}
}
else
{
if (greatertail == NULL)
{
cur -> next = NULL;
greaterhead = greatertail = cur;
}
else {
cur -> next = NULL;
greatertail -> next = cur;
greatertail = cur;
}
}
cur = next;
if(cur) //如果不判断的话,最后cur走到最后一个结点的时候,next产生空指针问题。
next = cur -> next;
}
if(lesshead == NULL) return greaterhead;//如果第一个链表为空,则直接返回第二个链表头指针
lesstail -> next = greaterhead;
return lesshead;
}
};
带哨兵位的就相对简单一些:
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
#include <cstddef>
class Partition {
public:
ListNode* partition(ListNode* pHead, int x) {
// write code here
if(pHead == NULL) return NULL;
if(pHead -> next == NULL) return pHead;
ListNode * lesshead = (ListNode*)malloc(sizeof(ListNode));
lesshead -> next = NULL;
ListNode * greaterhead = (ListNode*)malloc(sizeof(ListNode));
greaterhead -> next = NULL;
ListNode * lesstail = lesshead, * greatertail = greaterhead,*cur = pHead,*next = cur->next;
while(cur)
{
if(cur -> val < x)
{
cur -> next = NULL;
lesstail -> next = cur;
lesstail = cur;
}
else
{
cur -> next = NULL;
greatertail -> next = cur;
greatertail = cur;
}
cur = next;
if(cur)
next = cur -> next;
}
lesstail -> next = greaterhead -> next;
//把两个链表拼在一起的时候需要去掉第二个链表的头结点
free(greaterhead);
return lesshead->next;
//返回的时候不能返回头结点的地址,因为头结点不存任何数据,所以要返回头结点指向的那个结点的地址。
}
};
其中,还有一些需要规避的小问题,注释里都写到了。
分享一个小技巧:
因为做oj类的题目时,链表问题调试起来就会有些麻烦,还要用头插尾插方式进行构建链表样例
但是其实不用,一般这类题目放到我们的vs中的话,我们可以快速构建链表:
ListNode* a = (ListNode*)malloc(sizeof(ListNode));
assert(a);
ListNode* b = (ListNode*)malloc(sizeof(ListNode));
assert(b);
ListNode* c = (ListNode*)malloc(sizeof(ListNode));
assert(c);
ListNode* d = (ListNode*)malloc(sizeof(ListNode));
assert(d);
a->val = 0;
b->val = 7;
c->val = 2;
d->val = 0;
a->next = b;
b->next = c;
c->next = d;
d->next = NULL;
ListNode* plist = a;
SLPrint(partition(plist, 5));
这样就可以随心构建链表,然后进行调试。