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

给定一个单向链表的头节点head,节点的值类型是整数,在给定一个pivot.实现一个调整链表的函数,将链表调整为左部分都是小于pivot的节点,中间部分都是值等于pivot的节点,右部分是值大于pivot的节点。

要求1:调整后每部分的节点从左到右的顺序与原链表中节点的先后顺序一致。

要求2:如果链表长度为N,时间复杂度达到O(N),空间复杂度达到O(1).

 

 

 

package com.javause.Algorithm.divideNodeList;

 

import org.junit.Test;

 

/**

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

 *

 * @author 2017-kxd

 *

 */

public class DivideNodeList {

 

  /**

   * 普通方法,将链表所有的节点放入一个额外的数组,然后统一调整位置

   *

   * O(n),时间复杂度O(n)

   */

  public class Node {

 

    public int value;

    public Node next;

 

    public Node(int data) {

      this.value = data;

    }

  }

 

  public Node listPartition1(Node head, int pivot) {

    if (head == null) {

      return head;

    }

    Node cur = head;

    int i = 0;

    while (cur != null) {

      cur = cur.next;

      i++;

    }

    Node[] nodeArr = new Node[i];

    i = 0;

    cur = head;

    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];

  }

 

  private void arrPartition(Node[] nodeArr, int pivot) {

    int small = -1;

    int big = nodeArr.length;

    int index = 0;

    while (index != big) {

      if (nodeArr[index].value < pivot) {

        swap(nodeArr, ++small, index++);

      } else if (nodeArr[index].value == pivot) {

        index++;

      } else {

        swap(nodeArr, --big, index);

      }

    }

 

  }

 

  public void swap(Node[] nodeArr, int a, int b) {

    Node tmp = nodeArr[a];

    nodeArr[a] = nodeArr[b];

    nodeArr[b] = tmp;

  }

 

  @Test

  public void test() {

    Node node1 = new Node(9);

    Node node2 = new Node(0);

    Node node3 = new Node(4);

    Node node4 = new Node(5);

    Node node5 = new Node(1);

    node1.next = node2;

    node2.next = node3;

    node3.next = node4;

    node4.next = node5;

 

    Node cur = listPartition1(node1, 3);

    while (cur != null) {

      System.out.println(cur.value);

      cur = cur.next;

    }

  }

 

}

 

 

 

 

 

 

package com.javause.Algorithm.divideNodeList;

 

import org.junit.Test;

 

/**

 * 将链表按某个值分割后,保持左中右三部分都保存原来的顺序, 时间复杂度为O(n),空间复杂度为O(1)

 */

public class DivideNodeList2 {

  public class Node {

 

    public int value;

    public Node next;

 

    public Node(int data) {

      this.value = data;

    }

  }

 

  public static Node listPartition2(Node head, int pivot) {

    Node sH = null; // 小的头

    Node sT = null;// 小的尾

    Node eH = null;

    Node eT = null;

    Node bH = null;// 大的头

    Node bT = null;// 大的尾

    Node next = null; // 保存下一个节点

 

    // 对所有节点进行分割

    while (head != null) {

      next = head.next;

      head.next = null;

      if (head.value < pivot) {

        if (sH == null) {

          sH = head;

          sT = head;

        } else {

          sT.next = head;

          sT = head;

        }

      } else if (head.value == pivot) {

        if (eH == null) {

          eH = head;

          eT = head;

 

        } else {

          eT.next = head;

          eT = head;

        }

      } else {

        if (bH == null) {

          bH = head;

          bT = head;

        } else {

          bT.next = head;

          bT = head;

        }

      }

      head = next;

    }

 

    // 小的部分和相等部分重连

    if (sT != null) {

      sT.next = eH;

      eT = eT == null ? sT : eT;

 

    }

    // 所有的重新连接

    if (eT != null) {

      eT.next = bH;

 

    }

    return sH != null ? sH : eH != null ? eH : bH;

  }

 

  @Test

  public void test() {

    Node node1 = new Node(7);

    Node node2 = new Node(9);

    Node node3 = new Node(1);

    Node node4 = new Node(8);

    Node node5 = new Node(5);

    Node node6 = new Node(2);

    Node node7 = new Node(5);

    node1.next = node2;

    node2.next = node3;

    node3.next = node4;

    node4.next = node5;

    node5.next = node6;

    node6.next = node7;

 

    Node cur = listPartition2(node1, 5);

    while (cur != null) {

      System.out.println(cur.value);

      cur = cur.next;

    }

  }

}

 

转载于:https://my.oschina.net/iioschina/blog/1517518

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值