刷题——分割链表、相交链表

题目要求:不改变原链表的相对顺序,所以不能用头插。尾插:适用不改变相对顺序。这里我们使用带哨兵位的头结点,可以简化一些条件判断,剩去一些判空操作。

    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掉空间,避免造成内存泄漏。


image.png
首先,最容易想到的就是暴力解法——把他们都遍历一遍,但这样时间复杂度为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;


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

裙下的霸气

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值