按基准划分链表(分为三段)

问题描述:

给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点放在前面,等于 x 的节点放在中间,大于x的结点放在后面。

该问题为leetcode86分隔链表的加强版。

实现思路:

1.链表分隔

首先定义三个小链表,遍历该链表,将小于x值的插到第一个链表后面,等于的插到第二个链表之后,大于的插入第三个链表后面。

2.小表合并

将这三个链表依次首位相连连成一个大链表;

具体实现:

预先分配两个长度为3数组,heads,lasts 依次存放小于,大于,等于的头结点和尾结点;

链表分割:为了插入方便(不用空值判定)期间,为每个小节点都初始化一个头结点(该节点不存元素),后续判断直接在尾结点上插入并将尾结点后移;(总体没啥难度)

链表合并:这部分的难度在于需要处理好链表小链表为空情况,之前写了好几个版本,都不是很满意,一大堆if else 我都不想往下看。精简版实现如下:

head = null;对heads从后往前遍历,若heads[i].next != null,就把lasts[i]链到head前面,再令head指向heads[i]的后一个位置。(由于为了方便插入heads[i]上并没存放元素,从他的next开始存放,因此判断,赋值都是heads[i].next)

下图中为了没有画出空的头节点,从其下一个结点开始画的。

初始化:x = 8时

i = 2

i = 1 时,由于heads[i] = null ,因此结果同 i= 2 情况

i = 0时:

如上完成分隔。

代码实现:

    class Node<T> {
         T data;
         Node<T> next;
         public Node() {};
         public Node(T data) {this.data = data;}
    } 
    public static Node<Integer> selution3(Node<Integer> head,int num){
         //最终版
         Node<Integer>[] heads = new Node[3];
         Node<Integer>[] lasts = new Node[3];
         for(int i = 0;i < 3;i++) {
             heads[i] = new Node<Integer>();//小链表头结点不存元素
             lasts[i] = heads[i];
         }
         //分割为三个小链表
         for(Node<Integer> p = head;p != null;p = p.next) {
             if(p.data < num) {
                 lasts[0].next = p;
                 lasts[0] = lasts[0].next;
             }else if(p.data > num) {
                 lasts[2].next = p;
                 lasts[2] = lasts[2].next;
             }else {
                 lasts[1].next = p;
                 lasts[1] = lasts[1].next;
             }
         }
         head = null;
         //拼接 从后往前拼接
         for(int i = 2;i >= 0;i--) {
             if(heads[i].next != null) {
                 lasts[i].next = head;
                 head = heads[i].next;
                 heads[i].next = null;
             }
         }
         return head;
     }

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值