【笔记:左程云算法与数据结构】4.链表

用快慢指针找到链表的中点

“定制”三种不同的情况
1.元素个数为偶数时,慢指针指向中间偏左的元素
2.元素个数为偶数时,慢指针指向中间偏右的元素
3.慢指针指向中间的前一个元素请添加图片描述
代码:

//1.元素个数为偶数时,慢指针指向中间偏左的元素
ListNode* EndOfFirstHalf1(ListNode* head)
{
    ListNode* fast = head;
    ListNode* slow = head;
    while(fast->next!=nullptr)
    {
        fast = fast->next;
        if (fast->next != nullptr)
        {
            slow = slow->next;
            fast = fast->next;
        }
        else
            break;
    }
    return slow;
}

第一种情况,只有在快指针顺利移动两次时,慢指针才移动一次

ListNode* EndOfFirstHalf2(ListNode* head)
{
    ListNode* fast = head;
    ListNode* slow = head;
    while (fast->next != nullptr)
    {
        fast = fast->next;
        slow = slow->next;
        //先移动慢指针,再进行快指针的第二次移动
        if (fast->next != nullptr)
        {
            fast = fast->next;
        }
        else
            break;
    }
    return slow;
}

第二种情况,即使快指针只能移动一次,慢指针也移动

//3.慢指针指向中间的前一个元素
//这种情况也就是在第一种情况的基础上,慢指针在开始时就少移动一次
ListNode* EndOfFirstHalf3(ListNode* head)
{
    ListNode* fast = head->next->next;
    ListNode* slow = head;
    while (fast->next != nullptr)
    {
        fast = fast->next;
        if (fast->next != nullptr)
        {
            slow = slow->next;
            fast = fast->next;
        }
        else
            break;
    }
    return slow;
}

第三种情况,即在第一种情况的基础上,慢指针在开始时就少移动一次

回文链表

笔试写法:双链表+栈

例题:复制含有随即指针结点的链表(力扣138题)

在这里插入图片描述

使用额外空间

哈希表

key(ListNode)value (ListNode)
老结点对应的克隆出的新节点

首先不用管结点间的关系,直接复制结点,再遍历

class Solution {
public:
    Node* copyRandomList(Node* head) {
        unordered_map<Node*,Node*> m;
        Node *p=head;
        //首先复制结点
        while(p!=nullptr)
        {
            Node* pnew=new Node(p->val);
            m.insert(make_pair(p,pnew));
            p=p->next;
        }
        //构造结点间的关系
        p=head;
        while(p!=nullptr)
        {
            Node* pnew=m[p];
            pnew->next=m[p->next];
            pnew->random=m[p->random];
            p=p->next;
        }
        return m[head];
    }
};
不使用额外空间

直接复制,将复制后的结点放在原结点的后面
在这里插入图片描述

//不使用额外空间
class Solution {
public:
    Node* copyRandomList(Node* head) {
        if (!head) return nullptr;
        Node* cur = head;
        //首先复制结点,并将新结点置于旧结点之后
        while (cur != nullptr)
        {
            Node* next = cur->next;
            cur->next = new Node(cur->val);
            cur->next->next = next;
            cur = next;
        }
        //构建random关系
        cur = head;
        Node* ans = head->next;
        while (cur != nullptr)
        {
            Node* newp = cur->next;
            Node* next = newp->next;
            if (cur->random) newp->random = cur->random->next;
            cur = next;
        }
        //分离
        cur = head;
        while (cur != nullptr)
        {
            Node* newp = cur->next;
            Node* next = newp->next;
            cur->next = next;
            if (next) newp->next = next->next;
            cur = next;
        }

        return ans;
    }
};

例题:链表中环的入口节点

快慢指针

快指针走两步,慢指针走一步;当相遇时,快指针返回头结点,两个结点都每次走一步,再次相遇的位置即入口节点

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* LF=head;
        ListNode* LS=head;
        while(LF!=nullptr)
        {
            LF=LF->next;
            LS=LS->next;
            if(LF)
            {
                LF=LF->next;
                if(LF==LS)//相遇
                {
                    LF=head;
                    while(LF!=LS)
                    {
                        LF=LF->next;
                        LS=LS->next;
                    }
                    return LF;
                }
            }
            else return nullptr;
        }
        return nullptr;
    }
};

例题:链表相交

1.都无环:

在这里插入图片描述

class Solution {
public:
    ListNode* getIntersectionNode(ListNode* headA, ListNode* headB) {
        ListNode* pA = headA, * pB = headB;
        while (pA != nullptr || pB != nullptr)
        {
            if (pA == pB) return pA;
            if (pA == nullptr) pA = headB;
            else if (pB == nullptr) pB = headA;
            else
            {
                pA = pA->next;
                pB = pB->next;
            }
        }
        return nullptr;
    }
};
2.都有环:

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值