题目要求:不改变原链表的相对顺序,所以不能用头插。尾插:适用不改变相对顺序。这里我们使用带哨兵位的头结点,可以简化一些条件判断,剩去一些判空操作。
ListNode* partition(ListNode* pHead, int x) {
struct ListNode*lesshead,*lesstail,*greaterhead,*greatertail;
greaterhead = greatertail = (struct ListNode*)malloc(sizeof(struct ListNode));
lesshead = lesstail = (struct ListNode*)malloc(sizeof(struct ListNode));
lesstail->next = greatertail->next = NULL;
struct ListNode*cur = pHead;
while(cur)
{
if(cur->val < x)
{
lesstail->next = cur;
lesstail = lesstail->next;
}
else
{
greatertail->next = cur;
greatertail = greatertail->next;
}
cur = cur->next;
}
lesstail->next = greaterhead->next;
greatertail->next = NULL;
struct ListNode*head = lesshead->next;
free(greaterhead);
free(lesshead);
return head;
}
首先我们创建两个带头的链表,和一个遍历指针 cur。然后遍历分别插入链表。我们把链表连接起来时,首先我们的链表是带头的,所以我们要跳过头节点,并且我们的Max链表的最后一个元素不一定为NULL,我们要手动置为NULL。返回时,保存节点时也要跳过头指针,然后一个个free掉空间,避免造成内存泄漏。
首先,最容易想到的就是暴力解法——把他们都遍历一遍,但这样时间复杂度为O(M*N),非常笨比的解法。并且需要注意的是一个节点只有一个next。
思路:计算出两个链表的长度,让长的先走差距步(交点之前的部分一定没有交点,就没必要去遍历),再和短的同时走,这样时间复杂度为O(N)
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
if(headA == NULL || headB == NULL)
{
return NULL;
}
struct ListNode *curA = headA,*curB = headB;
int lenA = 1,lenB = 1;
//计算差距步
while(curA->next)
{
lenA++;
curA = curA->next;
}
while(curB->next)
{
lenB++;
curB = curB->next;
}
int gap = abs(lenA - lenB);
//判断是否有交点
if(curA != curB)
return NULL;
//假设法分辨哪个长哪个短
struct ListNode *shortlist = headA,*longlist = headB;
if(lenA > lenB)
{
longlist = headA;
shortlist = headB;
}
//长的链表先走差距步
while(gap--)
{
longlist = longlist->next;
}
while(shortlist != longlist) //for循环适合用于遍历数组,通过下标操作打印
{
shortlist = shortlist->next;
longlist = longlist->next;
}
return shortlist;
}