package com.my.util; /** * 单向链表节点 * */ public class SingleNode { public int value; public SingleNode next; public SingleNode(int data){ this.value = data; } } package com.my.suanfa; import com.my.util.SingleNode; /** * 按照左右半区的方式重新组合单链表 * 时间复杂度O(N),额外空间复杂度O(1) * 将单链表根据左右两区拆分为两个单链表 * */ public class Solution17 { public void relocate(SingleNode head) { //如果链表为空或者只有一个节点,则不需要重新组合 if(head == null || head.next == null) { return; } //遍历链表找到中间位置 SingleNode mid = head; SingleNode right = head.next; while(right.next != null && right.next.next != null) { mid = mid.next; right = right.next.next; } //mid的后继节点就是右区的第一个节点 right = mid.next; //此时mid是左区的最后一个节点,则将mid的后继节点设为空 mid.next = null; //此时已经找到了左区的第一个节点和右区的第一个节点,开始合并左右两区 mergeLR(head, right); } /** * 合并左右两区 * left左区第一个节点 * right右区第一个节点 * */ public void mergeLR(SingleNode left, SingleNode right) { SingleNode next = null; while(left.next != null) { //next记录右区未合并部分 next = right.next; right.next = left.next; left.next = right; left = right.next; right = next; } //此时left是左区的最后一个节点,如果总的节点数为偶数,则右区还剩一个节点, //如果总结点数为奇数,右区还剩两个节点,无论右区剩一个节点还是两个节点, //都是连接在左区最后一个节点的后面,因此这最后一个节点要特殊处理 left.next = right; } }