链表翻转三题 BM1 BM2 BM3

输入:指向第一个节点的指针head

准备工作

定义链表结构,输出链表,初始化链表

struct ListNode{
    explicit ListNode(int n):val(n){}
    int val;
    struct ListNode* next= nullptr;
};

ListNode* List_init(int num){
    auto *head = new ListNode(1);
    ListNode *p = head;
    for (int i=2;i<=num;i++) {
        auto q=new ListNode(i);
        p->next=q;
        p=q;
    }
    return head;
}

void showoff(ListNode* head){
    auto p=head;
    while (p){
        cout<<p->val<<" ";
        p=p->next;
    }
    cout<<endl;
}

BM1 翻转链表

要求:翻转整个链表,输出指向翻转后的第一个节点指针

思路:遍历链表,头插生成新链表

ListNode* reverse_list(ListNode* head){
    if (head== nullptr||head->next== nullptr){
        return head;
    }
    auto new_head = new ListNode(0);
    auto p = head;
    while (p){
        auto new_node = new ListNode(p->val);
        new_node->next=new_head->next;
        new_head->next=new_node;
        p=p->next;
    }
    return new_head->next;
}

BM2 翻转链表指定区间

BM3 分组翻转链表

两题一起考虑

封装一个函数,输入一个一对指针,分别指向待翻转链表分组第一个节点前一个节点(即前一组末或理解为加装头节点)与本组末节点,输出一对指针,分别指向翻转后的组头与组末

pair<ListNode*, ListNode*> reverseBetween(ListNode* head, ListNode* end){
    // 翻转head->next到end
    if (head== nullptr||head->next== nullptr){
        return {head,end};
    }
    auto new_head = new ListNode(0);
    auto p = head->next;
    auto new_end = new ListNode(p->val);
    new_head->next=new_end;
    p=p->next;
    while (p!=end->next){
        auto new_node = new ListNode(p->val);
        new_node->next=new_head->next;
        new_head->next=new_node;
        p=p->next;
    }
    return {new_head->next,new_end};
}

利用此函数完成两题,均加装头节点

ListNode* reverseBetween(ListNode* head,int m,int n){
    if (m>n||head== nullptr||head->next== nullptr){
        return head;
    }
    auto newhead = new ListNode(0);
    newhead->next=head;
    auto verse_head = newhead;
    auto verse_end= head;
    while (--m){
        verse_head=verse_head->next;
    }
//    cout<<verse_head->val<<endl;
    while (--n){
        verse_end=verse_end->next;
    }
//    cout<<verse_end->val<<endl;
    auto (p)= reverseBetween(verse_head,verse_end);
//    showoff(p.first);
    verse_head->next=p.first;
    p.second->next=verse_end->next;
    return newhead->next;
}
ListNode* reverseKGroup(ListNode* head, int k)  //按分组翻转
{
    auto newhead = new ListNode(0);
    newhead->next=head;
    auto p=newhead,q=newhead;
    //p指向翻转组前组末,q指向本组末
    while (true){
        int count=k;
        while (count--)
        {
            q=q->next;
            if (q== nullptr){
                return newhead->next;
            }
        }
        auto r=reverseBetween(p,q);
        p->next=r.first;
        r.second->next=q->next;
        q=r.second;
        p=q;
    }
}

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务