将单向链表按某值划分成左边小、中间相等、右边大的形式

【题目】 给定一个单向链表的头节点head,节点的值类型是整型,再给定一个 整 数pivot。实现一个调整链表的函数,将链表调整为左部分都是值小于 pivot 的节点,中间部分都是值等于pivot的节点,右部分都是值大于 pivot的节点。 除这个要求外,对调整后的节点顺序没有更多的要求。 例如:链表9->0->4->5>1,pivot=3。 调整后链表可以是1->0->4->9->5,也可以是0->1->9->5->4。总 之,满 足左部分都是小于3的节点,中间部分都是等于3的节点(本例中这个部 分为空),右部分都是大于3的节点即可。对某部分内部的节点顺序不做 要求。

进阶: 在原问题的要求之上再增加如下两个要求。 在左、中、右三个部分的内部也做顺序要求,要求每部分里的节点从左 到右的 顺序与原链表中节点的先后次序一致。 例如:链表9->0->4->5->1,pivot=3。 调整后的链表是0->1->9->4->5。 在满足原问题要求的同时,左部分节点从左到 右为0、1。在原链表中也 是先出现0,后出现1;中间部分在本例中为空,不再 讨论;右部分节点 从左到右为9、4、5。在原链表中也是先出现9,然后出现4, 最后出现5。 如果链表长度为N,时间复杂度请达到O(N),额外空间复杂度请达到O(1)。

解决思路:

  1. 首先我们先满足进阶之前的要求,只需要将链表调整成,左边小于参考值,中间等于参考值,右边大于参考值。我们可以通过一盒辅助数组,将链表元素全部拷贝过去,然后对数组执行调整,调整思路可以参考快速排序的思想,将数组分为三个区域。
    核心代码:
//通过数组进行换划分
    public static void arrPartition(Node[] nodeArr,int pivot){
        int small=-1;
        int big=nodeArr.length;
        int index=0;
        while (index!=big){
            if (nodeArr[index].data<pivot){
                aswap(nodeArr,++small,index++);
            }else if (nodeArr[index].data==pivot){
                index++;
            }else {
                aswap(nodeArr,--big,index);
            }
        }
    }
  1. 满足进阶条件,即,保持原来相对位置不变,并且空间复杂度为O(N),这就使得我们不能够借用辅助空间来完成。我们可以将原链表拆分成小于,等于,大于区域的小链表,然后去遍历原列表,将大于,小于,等于数分别放到对应链表中。最后将三个链表连接起来就可以了。
    eg:第一次找到第一个小于参考值的数。将它放进小于区域,这样就保证了在前面小于参考值的数先进入小于区域,然后整体就保证了相对位置不变。
    核心代码:
//方法二:不需要辅助数组,链表拆分成小于部分,等于部分,大于部分。
    // 三个小链表,最后在合成,空间复杂度为O(N)
    public static Node partition2(Node head,int pivot){
        Node sH=null;//small head
        Node sE=null;//small end
        Node eH=null;//equal head
        Node eE=null;//equal end
        Node bH=null;//big head
        Node bE=null;//big end
        Node next=null;
        while (head!=null){
            next=head.next;
            head.next=null;
            if (head.data<pivot){
                if (sH == null) {
                    sH=head;
                    sE=head;
                }else {
                    sE.next=head;
                    sE=head;
                }
            }else if(head.data==pivot){
                if (eH==null){
                    eH=head;
                    eE=head;
                }else {
                    eE.next=head;
                    eE=head;
                }
            }else {
                if (bH==null){
                    bH=head;
                    bE=head;
                }else {
                    bE.next=head;
                    bE=head;
                }
            }
            head=next;
        }
        //将小于和等于链表进行连接
        if (sE!=null){
            sE.next=eH;
            eE=eE==null?sE:eE;
        }
        //连接整个链表
        if (eE!=null){
            eE.next=bH;
        }
        return sH!=null?sH:eH!=null?eH:bH;
    }

完整代码:

package basic_class_03;

/**
 * 类名:Code_12_SmallerEqualBigger<br>
 * 功能:将单链表按某值进行划分成左边小,中间想等,右边大的形式<br>
 * 作者:java战士<br>
 * 日期:2019/9/4<br>
 * 版本:v1.0.0
 * 历史修订:
 */
public class Code_12_SmallerEqualBigger {

    public static class Node{
        public int data;
        public Node next;

        public Node(int data) {
            this.data = data;
        }
    }
    //第一种方法将链表拷贝到数组中然后进行划分,最后在数组考回链表中,
    // 这种做法空间复杂度为O(),没有要求保持原来的相对顺序不变
    public static Node partition1(Node head,int pivot){
        if (head==null){
            return head;
        }
        Node cur=head;
        int i=0;
        while (cur!=null){
            i++;
            cur=cur.next;
        }
        Node[] nodeArr=new Node[i];
        cur=head;
        i=0;
        for (i=0;i!=nodeArr.length;i++){
            nodeArr[i]=cur;
            cur=cur.next;
        }
        arrPartition(nodeArr,pivot);
        for (i=1;i<nodeArr.length;i++){
            nodeArr[i-1].next=nodeArr[i];
        }
        nodeArr[i-1].next=null;
        return nodeArr[0];
    }
    //方法二:不需要辅助数组,链表拆分成小于部分,等于部分,大于部分。
    // 三个小链表,最后在合成,空间复杂度为O(N)
    public static Node partition2(Node head,int pivot){
        Node sH=null;//small head
        Node sE=null;//small end
        Node eH=null;//equal head
        Node eE=null;//equal end
        Node bH=null;//big head
        Node bE=null;//big end
        Node next=null;
        while (head!=null){
            next=head.next;
            head.next=null;
            if (head.data<pivot){
                if (sH == null) {
                    sH=head;
                    sE=head;
                }else {
                    sE.next=head;
                    sE=head;
                }
            }else if(head.data==pivot){
                if (eH==null){
                    eH=head;
                    eE=head;
                }else {
                    eE.next=head;
                    eE=head;
                }
            }else {
                if (bH==null){
                    bH=head;
                    bE=head;
                }else {
                    bE.next=head;
                    bE=head;
                }
            }
            head=next;
        }
        //将小于和等于链表进行连接
        if (sE!=null){
            sE.next=eH;
            eE=eE==null?sE:eE;
        }
        //连接整个链表
        if (eE!=null){
            eE.next=bH;
        }
        return sH!=null?sH:eH!=null?eH:bH;
    }
    //通过数组进行换划分
    public static void arrPartition(Node[] nodeArr,int pivot){
        int small=-1;
        int big=nodeArr.length;
        int index=0;
        while (index!=big){
            if (nodeArr[index].data<pivot){
                aswap(nodeArr,++small,index++);
            }else if (nodeArr[index].data==pivot){
                index++;
            }else {
                aswap(nodeArr,--big,index);
            }
        }
    }

    public static void aswap(Node[] nodeArr,int a,int b){
        Node temp=nodeArr[a];
        nodeArr[a]=nodeArr[b];
        nodeArr[b]=temp;
    }

    public static void printLinkList(Node head){
        System.out.print("Linked List:");
        while (head!=null){
            System.out.print(head.data+" ");
            head=head.next;
        }
        System.out.println();
    }
    public static void main(String[] args){
        Node head1=new Node(9);
        head1.next=new Node(0);
        head1.next.next=new Node(4);
        head1.next.next.next=new Node(5);
        head1.next.next.next.next=new Node(1);
        printLinkList(head1);
        //head1=partition1(head1,4);
        head1=partition2(head1,3);
        printLinkList(head1);
    }
}

结果展示:(以3作为参考值)
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值