C++数据结构与算法 -- 链表

本文探讨了如何通过快慢指针技巧高效地判断链表是否为回文,同时介绍了利用哈希表记录节点位置的优化方法,以及在不使用额外空间的情况下实现链表自身的修改。此外,还涉及到了链表相交问题的解决策略,包括环的检测和无环/有环情况下的交点查找。
摘要由CSDN通过智能技术生成

链表

菜鸡一枚,不喜勿喷~~~~~~

  • 换头需要返回值
  • 不换头不用返回值

技巧

  • 快慢指针
  • 额外的数据结构记录(哈希表等)

回文链表

  • 利用栈(先入后出)
  • 快慢指针(快指针走两步、慢指针走一步,快指针走完,慢指针走到终点)
  • 链表的自身修改实现 不需要额外的空间复杂度
//回文链表  时间复杂度O(N)  空间复杂度O(1)  链表的自身修改实现 不需要额外的空间复杂度
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        ListNode* fast = head, * show = head;
        while (fast->next && fast->next->next)
        {
            show = show->next;
            fast = fast->next->next;
        }
        fast = show->next;
        show->next = nullptr;
        ListNode* fastNest = nullptr;
        while (fast)
        {
            fastNest = fast->next;
            fast->next = show;
            show = fast;
            fast = fastNest;
        }
        fast = head;
        fastNest = show;
        bool res = true;
        while (fast && fastNest)
        {
            if (fast->val != fastNest->val)
            {
                res = false;
                break;
            }
            fast = fast->next;
            fastNest = fastNest->next;
        }
        fast = show->next;
        show->next = nullptr;
        while (fast)
        {
            fastNest = fast->next;
            fast->next = show;
            show = fast;
            fast = fastNest;
        }
        return res;
    }
};

相交问题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cBlqfJBr-1643973726450)(C:\Users\26737\AppData\Roaming\Typora\typora-user-images\image-20220203111344059.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tm2Ph2xb-1643973726451)(C:\Users\26737\AppData\Roaming\Typora\typora-user-images\image-20220203111355755.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mjwFKTfE-1643973726451)(C:\Users\26737\AppData\Roaming\Typora\typora-user-images\image-20220203111405926.png)]

 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 isIntersectList
{
public:
    ListNode* isIntersect(ListNode*& head1, ListNode*& head2)
    {
        if (head1==nullptr||head2==nullptr)
        {
            return nullptr;
        }
        ListNode* loop1 = isLoop(head1);
        ListNode* loop2 = isLoop(head2);
        //无环情况
        if (loop1 == nullptr && loop2 == nullptr)
        {
            return noLoop(head1,head2);
        }
        //一个有环 一个无环不可能有相交的

        //两个都有环的情况
        if (loop1!=nullptr&&loop2!=nullptr)
        {
            return haveLoop(head1, loop1, head2, loop2);
        }
    }
private:
    //判断是否有环
    ListNode* isLoop(ListNode* &head)
   {
        if (head == nullptr || head->next == nullptr || head->next->next == nullptr)
            return nullptr;
        ListNode* fast = head->next->next, *slow = head->next;
        while (fast!=slow)
        {
            if (fast->next == nullptr||fast->next->next== nullptr)
            {
                return nullptr;
            }
            fast = fast->next->next;
            slow = slow->next;
        }
        fast = head;
        while (fast!=slow)
        {
            fast = fast->next;
            slow = slow->next;
        }
        return fast;
    }
    //无环
    ListNode* noLoop(ListNode*& head1, ListNode*& head2)
    {
        int len1{ 1 }, len2{ 1 };
        ListNode* end1, *end2;
        ListNode* h1 = head1;
        ListNode* h2 = head2;
        while (h1->next!= nullptr)
        {
            ++len1;
            h1 = h1->next;
        }
        end1 = h1;
        while (h2->next != nullptr)
        {
            ++len2;
            h2 = h2->next;
        }
        end2 = h2;
        if (end1 != end2)
            return nullptr;
        int n = len1 - len2;
        h1 = n > 0 ? head1 : head2;
        h2 = n > 0 ?  head2 : head1;
        n = abs(n);
        while (n > 0)
        {
            h1 = h1->next;
            n--;
        }
        while (h1!=h2)
        {
            h1 = h1->next;
            h2 = h2->next;
        }
        return h1;
    }
    //有环
    ListNode* haveLoop(ListNode*& head1,ListNode*&loop1, ListNode*& head2, ListNode*& loop2)
    {
        ListNode* cur1 = head1, * cur2 = head2;
        int n = 0;
        //交点在环外的情况
        if (loop1==loop2)
        {
            while (cur1!=loop1)
            {
                cur1 = cur1->next;
                ++n;
            }
            while (cur2!=loop2)
            {
                cur2 = cur2->next;
                --n;
            }
            //长的
            cur1 = n > 0 ? head1 : head2;
            //短的
            cur2 = n > 0 ? head2 : head1;
            n = abs(n);
            while (n>0)
            {
                cur1 = cur1->next;
                ++n;
            }
            while (cur1!=cur2)
            {
                cur1 = cur1->next;
                cur2 = cur2->next;
            }
            return cur1;
        }
        //交点在环内的情况
        else
        {
            ListNode* temp = loop1->next;
            while (temp!=loop2)
            {
                temp = temp->next;
                if (temp == loop1)
                    return nullptr;
            }
            //loop1 和 loop2都一样
            return loop1;
        }
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值