LeetCode中级算法——链表

①奇偶链表在这里插入图片描述

数据规模:
在这里插入图片描述
思路:
整体思路不要想复杂了,就是活动next指针即可。重点收获在于——记住:链表和数组的重要差别是,链表没有下标的概念,也就是链表的访问虽然是顺序的,但是可以通过修改指针来更改既定的顺序!

代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode *oddEvenList(ListNode *head)
    {
        if (head == nullptr || head->next == nullptr || head->next->next == nullptr)
        {
            return head;
        }
        ListNode *res = head;
        ListNode *nt = head->next;
        ListNode *ou = head->next;
        ListNode *ji = head;
        ListNode *tmp = head;
        int now = 0;
        while (true)
        {
            ++now;
            head = tmp;
            if (head == nullptr)
            {
                break;
            }
            if (now % 2 == 0)
            {
                tmp = head->next;
                if(tmp == nullptr)
                {
                    break;
                }
                ou->next = tmp->next;
                ou = ou->next;
            }
            else
            {
                tmp = head->next;
                if (tmp == nullptr)
                {
                    break;
                }
                if(tmp->next == nullptr)
                {
                    continue;
                }
                ji->next = tmp->next;
                ji = ji->next;
            }
        }
        ji->next = nt;
        return res;
    }
};

②相交链表

在这里插入图片描述
在这里插入图片描述
思路:
这个题这是第二遍做了,第一遍做的时候应该是参考了题解,但这次自己又给出了一个方法~~(感觉比题解好一些)~~ 。

题解思路:
用双指针的方法,用第一个指针F从listA开始遍历,用第二个指针P从listB开始遍历。
假设listA更短一些,则在F遍历完后,让F再从B开始遍历;同理对于P也是再从A开始遍历。
假设链表构造为下图:
在这里插入图片描述
则在F遍历到2的节点(即相交节点时),P也会遍历到2的节点,即当F与P相等时,说明找到了相交节点处。
可以这样想:A链 = A1 + C,B链 = B1 + C,其中C是公共部分。如果A、两链相交,则双指针在遍历完一次A1+B1+C后,一定会相遇,同理如果不想交,则C = NULL,在遍历完A1+B1后,两指针都指向空,返回任意指针也符合题意。
非常巧妙、且数学的做法!

个人思路:
用数据规模的偷工减料方法, 由于数据规模规定每一个节点的范围是1~1e5,则不妨先用F指针遍历A链,修改每一个节点的值,使之成为人为链表节点(也就是+1e5即可,因为自然链表的值不可能超过1e5,只有人为标记链表的值才会超过1e5),之后让P指针遍历B链,如果在遍历时,P指针指向的当前节点的值超过了1e5,说明之前被遍历过了,且这是相交节点的第一个节点,记录下来,然后重新遍历一遍A链,重新将值重置回来即可(再减去1e5),返回记录下来的地方(如果不相交,则指向空也结束了)

总而言之,个人思路较为取巧,题解思路更为巧妙,两者复杂度差别不大。

题解代码及最终结果:

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode * f = headA;
        ListNode * p = headB;
        while(f!=p)
        {
            if(f == nullptr)
            {
                f = headB;
            }
            else
            {
                f = f->next;
            }
            if(p == nullptr)
            {
                p = headA;
            }
            else
            {
                p = p->next;
            }
        }
        return f;
    }
};

在这里插入图片描述

个人代码:

ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode * f = headA;
        while(f!=nullptr)
        {
            f->val += 100005;
            f = f->next;
        }
        ListNode * p = headB;
        while(p!=nullptr)
        {
            if(p->val >= 100005)
            {
                break;
            }
            p = p->next;
        }
        f = headA;
        while(f!=nullptr)
        {
            f->val -= 100005;
            f = f->next;
        }
        return p;
    }

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Mac-lengs

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

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

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

打赏作者

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

抵扣说明:

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

余额充值