4.24 log | 链表内指定区间反转,合并两个排序的链表,合并k个已排序的链表

 链表内指定区间反转

class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        ListNode* dummy=new ListNode(0);
        dummy->next=head;
        ListNode* result=dummy;
        stack<ListNode*> st;
        for(int i=1;i<m;i++) dummy=dummy->next;
        ListNode* left=dummy; 
        for(int i=m;i<=n;i++){
            dummy=dummy->next;
            st.push(dummy);
        } 
        ListNode* right=dummy->next;
        while(!st.empty()){
            left->next=st.top();
            st.pop();
            left=left->next;
        }
        left->next=right;
        return result->next;
    }
};

全链表反转用递归几行代码就能解决,而这题是在限定区间里反转所以用栈来做代码更简洁,把链表划分为区间外左边,区间,区间外右边,三部分,只操作其中区间部分,首先求出链表到达区间的前一位left,然后用stack储存区间内指针,并求出区间外后边第一位right,然后再用while循环,left指向st.top()依次反转区间内指针指向,最后输出表头,注意不能输出head,head可能被反转到后面。

总结,用栈来处理反转区间,以及左右两边衔接处的处理

合并两个排序的链表

class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
        ListNode* p=new ListNode(0);
        ListNode* q=new ListNode(0);
        p->next=pHead1;
        q->next=pHead2;
        ListNode* result=p;
        while(p->next!=NULL&&q->next!=NULL){
            if(p->next->val<q->next->val){
                p=p->next;
            }else{
                ListNode* temp1=p->next;
                ListNode* temp2=q->next->next;
                p->next=q->next;
                p->next->next=temp1;
                p=p->next;
                q->next=temp2;
            }
        }
        if(p->next==NULL) p->next=q->next;
        return result->next;
    }

这道题我的解法是在原链表基础上合并链表,不用格外空间,首先创建两个拟头分别指向两个头结点,本题我选用head1作为母表,再创建一个指针copy head1拟头,然后进入while循环判断,逻辑就是大于head1的值p往后走,小于head1就要把q插入p,然后改变q的指向,对于q来说就是删除节点,不用后移,只能改变指向。

    ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
        // write code here
        if(pHead1==NULL) return pHead2;
        if(pHead2==NULL) return pHead1;
        if(pHead1->val<pHead2->val){
            pHead1->next=Merge(pHead1->next, pHead2);
            return pHead1;
        }else{
            pHead2->next=Merge(pHead1, pHead2->next);
            return pHead2;
        }
    }
};

这道题用合并二叉树的思路也很简洁,用递归几行代码解决,谁小就返回谁,并根据该节点向下递归

合并k个已排序的链表


class Solution {
public:
    struct cmp{
    public:
        bool operator()(ListNode* a,ListNode* b){
            return  a->val>b->val;   
        }
    };
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        // write code here
        priority_queue<ListNode*,vector<ListNode*>,cmp> que;
        for(int i=0;i<lists.size();i++){
            if(lists[i]!=NULL) que.push(lists[i]);
        }
        ListNode* result=new ListNode(0);
        ListNode* head=result;
        while(!que.empty()){
            ListNode* node=que.top();
            que.pop();
            head->next=node;
            head=head->next;
            if(node->next!=NULL) que.push(node->next);
        }
        return result->next;
    } 
};

大顶堆的堆顶为最大元素,其余更小的元素在堆下方,小顶堆与其刚好相反。优先级队列默认是大顶堆,重载小顶堆,里面是逻辑是大于。首先遍历一遍链表数组,小顶堆优先级队列储存所有链表的头结点,然后新建链表储存优先级队列的栈顶,被储存节点的下一个节点不为空,则优先级队列储存该节点下一个节点,直到优先级队列为空

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值