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

题目:给定一个单向链表的头结点head,节点的值类型是整型,再给定一个整数privot。实现一个调整链表的函数,将链表调整为左部分都是值小于privot的节点,中间部分都是值等于privot的节点,右部分都是大于privot的节点。
例如:链表9-0-4-5-1,pivot=3。
调整后是1-0-4-9-5,也可以是0-1-9-5-4。
解法1:我们可以利用数组额外空间来实现:
1。先遍历一遍链表,得到链表长度。
2。建立一个链表数组。
3。利用三向快排的划分
4。调整数组中的next值。
代码如下:

class Node{
    public int value;
    public Node next;
    public Node(int data){
        this.value=data;
    }
}
public class quicklist {
    public Node listPartition1(Node head,int privot){
        if (head==null){
            return head;
        }
        Node cur=head;
        int i=0;
        //先遍历一遍获得链表的
        while(cur!=null){
            i++;
            cur=cur.next;
        }
        Node[] nodeArr=new Node[i];
        i=0;
        cur=head;
        for (i = 0; i !=nodeArr.length ; i++) {
            nodeArr[i]=cur;
            cur=cur.next;
        }
        //调整在数组中的顺序
        arrPartion(nodeArr,privot);
        //调整赋值
        for (i = 0; i != nodeArr.length; i++) {
            nodeArr[i-1].next=nodeArr[i];//
        }
        nodeArr[i-1].next=null;
        return nodeArr[0];
    }

    /**
     * 三向切分快排一趟交换,需要三个记录量
     * @param nodeArr
     * @param privot
     */
    private void arrPartion(Node[] nodeArr, int privot) {
        int small=-1;
        int big=nodeArr.length;
        int index=0;
        while (index!=big){
            if (nodeArr[index].value<privot){
                swap(nodeArr,++small,index++);
            }else if (nodeArr[index].value==privot){
                index++;
            }else {
                swap(nodeArr,--big,index);
            }
        }
    }

    private void swap(Node[] nodeArr, int i, int j) {
        Node tmp=nodeArr[i];
        nodeArr[i]=nodeArr[j];
        nodeArr[j]=tmp;
    }
}

解法二:不需要额外空间复杂度的情况下完成调整:
1。将原链表中的所有节点一次划分进三个链表,三个链表分别为small代表左部分,equal代表中间部分,big代表右部分。
例如,链表7-9-1-8-5-2-5,privot=5。在划分之后,small,equal,big分别为:
small:1-2-null
equal:5-5-null
big:7-9-8-null
2。重新串联
3。需要重点判断null。
具体代码这里不予列出。。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值