美文网首页
链表的分化问题

链表的分化问题

作者: 熊白白 | 来源:发表于2017-07-11 21:36 被阅读5次

对于一个链表,我们需要用一个特定阈值完成对它的分化,使得小于这个值的结点移到前面,等于的值在中间,大于该值的结点在后面,同时保证两类结点内部的位置关系不变。
本题最优的解法是:
遍历该链表,把其中小于/等于/大于的结点挂接在新的三个链表中,然后把这三个链表串接起来。因为没有new和delete操作,所以仅需很少的空间和时间开销。

不完整代码

ListNode* listDivide(ListNode* head, int val) {
//分别是三个链表的表头和表尾指针。表尾方便在尾部挂接结点。
        ListNode *h1=nullptr,*h2=nullptr,*h3=nullptr,*p1=nullptr,*p2=nullptr,*p3=nullptr;
        ListNode *p=head;
        while(p){
//遍历,每个结点找到属于它的三个链表中的一个,挂接到尾部。
            if(p->val<val){
//特别注意头指针为空的情况。
                if(h1==nullptr){
                    h1=p;
                    p1=h1;
                }else{
                    p1->next=p;
                    p1=p1->next;
                }
            }else if(p->val==val){
                if(h2==nullptr){
                    h2=p;
                    p2=h2;
                }else{
                    p2->next=p;
                    p2=p2->next;
                }
            }else{
                if(h3==nullptr){
                    h3=p;
                    p3=h3;
                }else{
                    p3->next=p;
                    p3=p3->next;
                }
            }
            p=p->next;
        }
        //拼合三个链表
        p1->next=h2;
        p2->next=h3;
        p3->next=nullptr;//特别注意尾部的nullptr
        return h1;
}

以上的代码看似正常,其实是有问题的。问题在于拼合链表的时候,三个链表不一定每个都是有内容的。空指针的拼接往往会出错。
结合上述冗长的代码,可以把三个链表指针放在数组内进行遍历:利用一个belong函数,得到每个结点应该归属的链表,再进行操作。拼合的时候,利用一个变量tail,只对不为空的链表进行拼接。

int belong(const int a,const int b){
    if(a<b)
        return 0;
    if(a==b)
        return 1;
    if(a>b)
        return 2;
}
ListNode* listDivide(ListNode* head, int val) {
    ListNode *h[3]={};
    ListNode *t[3]={};
    ListNode *p=head;
    while(p){
        int pos=belong(p->val,val);
        if(h[pos]==nullptr){
            h[pos]=p;
            t[pos]=p;
        }else{
            t[pos]->next=p;
            t[pos]=p;
        }
        p=p->next;
    }
    head=nullptr;
    ListNode* tail=nullptr;
    for(int i=0;i<3;++i){
        if(h[i]){
            if(!head){
                head=h[i];
                tail=t[i];
            }else{
                tail->next=h[i];
                tail=t[i];
            }
        }
    }
    tail->next=nullptr;
    return head;
}

相关文章

  • 链表的分化问题

    对于一个链表,我们需要用一个特定阈值完成对它的分化,使得小于这个值的结点移到前面,等于的值在中间,大于该值的结点在...

  • 链表的分化

    对于一个链表,我们需要用一个特定阈值完成对它的分化,使得小于等于这个值的结点移到前面,大于该值的结点在后面,同时保...

  • 5_5链表的分化

    对于一个链表,我们需要用一个特定阈值完成对它的分化,使得小于等于这个值的结点移到前面,大于该值的结点在后面,同时保...

  • 1.数据结构-链表问题

    链表相关问题 删除节点 链表去重 有环链表 反转链表 链表排序 链表相交 其他问题 面试题 02.03. 删除中间...

  • 调整链表为小于等于k的在前,大于k的在后

    调整链表为小于等于k的在前,大于k的在后 对于一个链表,我们需要用一个特定阈值完成对它的分化,使得小于等于这个值的...

  • LeetCode 探索中级 [俩数相加][奇偶链表][相交链表]

    链表 @[链表|双指针] 链表问题相对容易掌握。 不要忘记"双指针解法",它不仅适用于数组问题,而且还适用于链表问...

  • 链表问题

    前言 如果说数据结构是算法的基础,那么数组和链表就是数据结构的基础。 因为像堆,栈,对,图等比较复杂的数组结基本上...

  • 数据结构与算法之循环链表(3.4)

    目录 单向循环链表双向循环链表约瑟夫问题如何发挥循环链表的最大威力? 一 单向循环链表 单向循环链表 - 只有一个...

  • 44_递归的思想与应用(中)

    关键词:单链表的转置、单向排序链表的合并、汉诺塔问题、全排列问题 0. 单链表的转置 1. 单向排序链表的合并 2...

  • 为什么说家庭中的“分化如此重要”

    家庭中出现的问题基本上都跟分化不良有关,那么,什么是“分化”呢? 自我分化有两个过程,一是把自我从他人那里分化出来...

网友评论

      本文标题:链表的分化问题

      本文链接:https://www.haomeiwen.com/subject/tetvhxtx.html