LeetCode——1、链表

博客围绕链表展开,介绍了反转链表(含全部反转和指定区间反转)、求两链表交点(用STL - set和双指针法)、链表求环(判断有无环及找出起始节点,有STL - set和快慢指针法)、链表划分、复杂链表深度拷贝以及合并排序链表(2个和K个排序链表)等常见问题及对应解决方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

〇、目录

在这里插入图片描述

一、反转链表

1、简单版:反转全部节点

在这里插入图片描述

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* newhead=NULL;
        while(head)
        {
            ListNode* nex=head->next;
            head->next=newhead;
            newhead=head;
            head=nex;
        }
        return newhead;
    }
};

在这里插入图片描述

2、进阶版:从指定节点到指定节点反转

在这里插入图片描述

class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        int change_len=n-m+1;
        ListNode* pre_head=NULL;
        ListNode* result=head;
        while(head && --m)
        {
            pre_head=head;
            head=head->next;
        }
        ListNode* modify_list_tail=head;
        ListNode* newnode=NULL;
        while(head && change_len)
        {
            ListNode* nex=head->next;
            head->next=newnode;
            newnode=head;
            head=nex;
            change_len--;
        }
        modify_list_tail->next=head;
        if(pre_head)
        {
            pre_head->next=newnode;
        }
        else
        {
            result=newnode;
        }
        return result;
    }
};

二、求两个链表的交点

法一、使用STL——set

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        std::set<ListNode*> node_set;
        while(headA)
        {
            node_set.insert(headA);
            headA=headA->next;
        }
        while(headB)
        {
            if(node_set.find(headB)!=node_set.end())
            {
                return headB;
            }
            headB=headB->next;
        }
        return NULL;
    }
};

法二、双指针

class Solution {
public:
    int len(ListNode* node)
    {
        int length=0;
        while(node)
        {
            node=node->next;
            length++;
        }
        return length;
    }
    
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* longnode;
        ListNode* shortnode;
        int dis=0;
        int len1=len(headA);
        int len2=len(headB);
        if(len1>len2)
        {
            longnode=headA;
            shortnode=headB;
            dis=len1-len2;
        }
        else
        {
            longnode=headB;
            shortnode=headA;
            dis=len2-len1;
        }
        
        while(dis)
        {
            longnode=longnode->next;
            dis--;
        }
        while(longnode && shortnode && longnode!=shortnode)
        {
            longnode=longnode->next;
            shortnode=shortnode->next;
        }
        return longnode;
    }
};

三、链表求环

1、简单版:判断链表是否有环

在这里插入图片描述

class Solution {
public:
    bool hasCycle(ListNode *head) {
        ListNode* fast=head;
        ListNode* slow=head;
        if(head==NULL)
        {
            return false;
        }
        while(fast && fast->next)
        {

            fast=fast->next->next;
            slow=slow->next;
            
            if(fast==slow)
            {
                return true;
            }
           
        }
         return false;
    }
};

2、进阶版:找出环的起始节点

在这里插入图片描述

法一、使用STL—set

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        std::set<ListNode*> node_set;
        while(head)
        {
            if(node_set.find(head)!=node_set.end())
            {
                return head;
            }
            node_set.insert(head);
            head=head->next;
        }
        return NULL;   
    }
};

法二、快慢指针

在这里插入图片描述

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fast=head;
        ListNode* slow=head;
        ListNode* meet=NULL;
        if(!head)
        {
            return NULL;
        }
        while(fast && fast->next)
        {
            
            fast=fast->next->next;
            slow=slow->next;
            if(fast==slow)
            {
                meet=fast;
                break;
            }
        }
        
        if(meet==NULL)
        {
            return NULL;
        }
        while(head && meet)
        {
            if(head==meet)
            {
                return head;
            }
            head=head->next;
            meet=meet->next;
        }
        return NULL;
    }
};

四、链表划分

在这里插入图片描述
使用临时头节点:

class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
        ListNode less_head(0);
        ListNode more_head(0);
        ListNode* less_ptr=&less_head;
        ListNode* more_ptr=&more_head;
        while(head)
        {
            if(head->val < x)
            {
                less_ptr->next=head;
                less_ptr=head;
            }
            else
            {
                more_ptr->next=head;
                more_ptr=head;
            }
            head=head->next;
        }
        less_ptr->next=more_head.next;
        more_ptr->next=NULL;
        return less_head.next;
    }
};

五、复杂链表的深度拷贝

在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    Node* copyRandomList(Node* head) {
        std::map<Node*,int> node_map;
        std::vector<Node*> node_vec;
        int i=0;
        Node* ptr=head;
        while(ptr)
        {
            node_vec.push_back(new Node(ptr->val));
            node_map[ptr]=i;
            ptr=ptr->next;
            i++;
        }
        node_vec.push_back(0);
        ptr=head;
        i=0;
        while(ptr)
        {
            node_vec[i]->next=node_vec[i+1];
            if(ptr->random)
            {
                int rid=node_map[ptr->random];
                node_vec[i]->random=node_vec[rid];
            }
            ptr=ptr->next;
            i++;
        }
        return node_vec[0];
    }
};

六、合并排序链表

1、简单版:2个排序链表

在这里插入图片描述

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if(!l1)
        {
            return l2;
        }
        if(!l2)
        {
            return l1;
        }
        if(l1->val < l2->val)
        {
            l1->next=mergeTwoLists(l1->next, l2);
            return l1;
        }
        else
        {
            l2->next=mergeTwoLists(l1, l2->next);
            return l2;
        }
    }
};

2、进阶版:K个排序链表

在这里插入图片描述

方法一、所有节点放到一个vector里,调用sort函数排序。

bool cmp(ListNode* p1, ListNode* p2)
    {
        return p1->val<p2->val;
    }
class Solution {
public:
    
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        std::vector<ListNode*> node_vec;
        for(int i=0;i<lists.size();i++)
        {
            ListNode* head=lists[i];
            while(head)
            {
                node_vec.push_back(head);
                head=head->next;
            }
        }
        if(node_vec.size()==0) return NULL;
        std::sort(node_vec.begin(),node_vec.end(),cmp);
        for(int i=1;i<node_vec.size();i++)
        {
                node_vec[i-1]->next=node_vec[i];
        }
        node_vec[node_vec.size()-1]->next=NULL;
        return node_vec[0];
    }
};

方法二、分制

在这里插入图片描述

class Solution {
public:
    ListNode* merge2lists(ListNode* l1,ListNode* l2)
    {
        if(!l1)
        {
            return l2;
        }
        if(!l2)
        {
            return l1;
        }
        if(l1->val < l2->val)
        {
            l1->next=merge2lists(l1->next,l2);
            return l1;
        }
        else
        {
            l2->next=merge2lists(l1,l2->next);
            return l2;
        }
    }
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        if(lists.size()==0)
            return NULL;
        if(lists.size()==1)
            return lists[0];
        if(lists.size()==2)
            return merge2lists(lists[0],lists[1]);
        std::vector<ListNode*> l1_vec;
        std::vector<ListNode*> l2_vec;
        int mid=lists.size()/2;
        for(int i=0;i<mid;i++)
        {
            l1_vec.push_back(lists[i]);
        }
        for(int i=mid;i<lists.size();i++)
        {
            l2_vec.push_back(lists[i]);
        }
        ListNode* l1=mergeKLists(l1_vec);
        ListNode* l2=mergeKLists(l2_vec);
        return merge2lists(l1,l2);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值